home *** CD-ROM | disk | FTP | other *** search
- ;«LM0»RE-SOURCE DISASSEMBLER - modified by JIR 7/87 - 11/88
-
- ;Disassembly starts ≈ page 43.
- ;Commands, file handling in first half, except Symbol stuff at ≈ page 67.
-
- ;All label addrs stored per pcntr, displayed as pcntr + curorg.
- ;Hard-coded addrs found in B cmd stored at coded addr - curorg.
-
- PAGE 192,132
- CSEG segment byte public 'CODE'
- assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
-
- DB 256 DUP(?)
-
- bel equ 7
- tab equ 9
- cr equ 0Dh
- lf equ 0Ah
- initlcnt equ 20 ;lines displayed initially
- DefaultDTA equ 80h ;in PSP, used as buffer for disk read/writes
- symbas equ offset ctlbas + 3072 ;base of 16K symbol (label) table
- rembas equ symbas + 16384 ;base of 24K remark table
-
- ;The scheme above makes the .COM file shorter. MEMCHK routine makes sure
- ; there's enough room for these.
-
- start proc near
- jmp memchk
-
- banner db 'RE-SOURCE by C.Derouen, revised by J. Rebold '
- db 'Dec 88',cr,lf,'$'
-
- ;CHECK FOR DOS V2.0+
- memchk: mov ah,30h ;get DOS version
- int 21h
- cmp al,2
- jae good_vers
- mov dx,offset bad_vers
- mov ah,9
- int 21h
- int 20h ; Exit
-
- bad_vers db cr,lf,7,'DOS 2.0+ required. Sorry.$'
-
- good_vers:
- ;ALLOCATE RAM FOR BUFFERS & TARGET PGM
- mov ax,cs
- mov es,ax ;seg addr of block to change
- mov bx,2000h ;allocate 128K
- mov ah,4Ah ;modify allocated memory block
- int 21h
- jc L001
- jmp goodmem
- L001: cmp al,8
- jz notnuf
- cmp al,7
- jnz invalid
- mov dx,offset destro
- jmp short prtmsg
-
- invalid: mov dx,offset invmsg
- jmp short prtmsg
-
- notnuf: mov dx,offset nomem ;location of string to print
- prtmsg: mov ah,9 ;print string
- int 21h
- mov ah,4Ch ;set Errorlevel & exit
- mov al,08h ;Errorlevel=8, failure
- int 21h
-
- nomem db cr,lf,7,'Not enough memory - program aborted$'
- destro db cr,lf,7,'DOS mem ctl blocks destroyed - cannot allocate RAM$'
- invmsg db cr,lf,7,'Invalid MCB addr or other screwup - pgm aborted$'
-
- goodmem:
- cli
- mov ax,ds
- mov ss,ax ;SS=DS
- mov sp,offset stak ;machine stack now in buffer @ end pgm
- sti
- mov bx,rembas ;EQU symbas + 16K
- mov remtbl,bx ;used from now on - start of REM table
- mov dx,offset banner ;addr of intro message
- mov ah,9 ;print string
- int 21h
- call ClearTables
- mov al,cs:byte ptr [80h] ;length of cmd line incl the CR
- or al,al
- jz fstcmd
- ;There is something on the command line
- call prtstr
- db cr,lf,'Reading All Files of ',0
- mov di,offset FileString
- mov bx,81h ;point to 1st char of cmd line
- BlnkLoop:
- mov al,[bx]
- cmp al,' '
- jnz FirstChar
- inc bx
- jmp short BlnkLoop
- FirstChar:
- call MoveField
- mov DotPtr,di
- mov byte ptr [di],'.'
- mov bx,offset FileString
- ZLoop: mov al,[bx]
- or al,al
- jz ZLoopDone
- call typech
- inc bx
- jmp short ZLoop
-
- ZLoopDone:
- call LoadAll
- jmp short fstcmd
-
- Restart:
- call ClearTables
- fstcmd: call prtstr
- db cr,lf,'Enter ? for Stats, H for Help (or hit F1)',cr,lf,cr,lf,0
-
- nxcmd: mov hlpflg,0 ;cursor keys not to show help
- hlpcmd: mov wfiflg,0 ;don't write to file
- ; mov segflg,0 ;clear segment use flag (not now used)
- mov sp,offset stak ;for errors in CALLs that jmp to NXCMD
- call gtcmd
- mov bx, offset cmdbuf+2 ;first char of command
- ; cmp word ptr [bx+1],':S' ;'S:' in reverse order
- ; jz segonl ;just change segment
- mov al,[bx] ;get 1st char of command
- mov bx,offset CmdVectorTable
- mov ch,(offset VectorTblEnd-offset CmdVectorTable)/3 ;no. of entries
- FuncLoop:
- cmp al,cs:[bx] ;test char match
- jz fndfun
- inc bx
- inc bx
- inc bx
- dec ch
- jnz FuncLoop
- jmp cmerr
-
- fndfun: inc bx
- mov dx,cs:[bx] ;address of function
- jmp dx ;no, NOT jmp [dx] !!
-
- ;segonl: inc bx ;pre-adj BX to point to S: in cmdbuf
- ; call updseg
- ; jmp short nxcmd
-
- CmdVectorTable db cr
- dw offset hlpcmd
- db ';'
- dw offset cmrem ;enter Remark
- db 'A'
- dw offset cmatmt ;Attempt to find DB's
- db 'B'
- dw offset cmbld ;Build symbol table
- db 'C'
- dw offset cmctl ;enter Control (BEHISW) or dump table
- db 'D'
- dw offset cmdump ;hex Dump, also Dump Symbol table
- db 'E'
- dw offset cmentr ;Enter a label
- db 'H'
- dw offset cmhelp
- db 'K'
- dw offset cmkill ;Kill a label
- db 'L'
- dw offset cmload ;load files
- db 'N'
- dw offset cmpurg ;clear .CTL, .SMB, .REM tables
- db 'O'
- dw offset cmorg ;set ORG addr
- db 'P'
- dw offset CmPath ;change D:\path\ to save to
- db 'Q'
- dw offset cmexit ;enter Q to quit
- db 'R'
- dw offset CmRAMpara ;unassemble anywhere in RAM
- db 'S'
- dw offset CmSearch
- db 'T'
- dw offset cmtrim ;toggle Trim (prints addrs w/labels)
- db 'U'
- dw offset CmUnasm ;do Unassembly
- db 'W'
- dw offset CmWriteRSM ;write .RSM file
- db 'Z'
- dw offset cmeof ;write EOF to .ASM file & close
- db '?'
- dw offset CmStats
- VectorTblEnd db 0
-
- ;--------------------------------
- cmerr: mov wfiflg,0 ;clear 'write to file' flag
- call prtstr
- db 'Command Error at ',bel,0
- pop bx ;addr called from
- call Print00BX_ ; for debugging
- call prtstr
- db cr,lf,0
- cli
- mov sp,offset stak
- sti
- jmp nxcmd
-
- ;--------------------------------
- delim: cmp al,' '
- jz deliok
- cmp al,','
- jz deliok
- call cmerr ;expected delimiter missing
- deliok: ret
-
- ;--------------------------------
- ; Exit program here
- cmexit: cmp ChgFlag,0
- jz ByeBye
- call prtstr
- db cr,lf,'Unsaved changes - '
- db cr,lf,'hit U to update & exit, E to just exit.',0
- Gotta: mov ah,0 ;read next kbd char into AL
- int 16h
- or al,al ;check for non-ASCII key
- jz Gotta
- and al,5Fh ;make upper-case
- cmp al,'E'
- jz ByeBye
- cmp al,'U'
- jnz Gotta
- call sav_em
- ByeBye: mov ax,4C00h ;exit w/errorlevel = 0
- int 21h
-
- ;--------------------------------
- ;HELP SCREENS
-
- cmhelp: mov hlpflg,1 ;signal cursor keys - see gtcmd
- xor ah,ah
- mov bx,offset helptr
- mov al,helpno ;get which help screen
- add al,al
- add bx,ax
- mov dx,[bx] ;make dx point to desired screen
- mov ah,9 ;print string
- int 21h
- jmp hlpcmd
-
- ;line 0
- help db ' COMMAND SUMMARY - all numbers are HEX!'
- ;line 1 & 2
- db cr,lf,cr,lf,';NNNN,[;]Remark enter Remark at NNNN'
- db ' ;=append \ starts new line'
- ;line 3
- db cr,lf,';[NNNN] list Remarks Table [from NNNN] '
- db ';NNNN, delete remark at NNNN'
- ;line 4
- db cr,lf,'A (See U) attempt to find DBs '
- db 'B (See U) build Symbol Table'
- ;line 5
- db cr,lf,'C dump CTL table '
- db 'CSSSS dump CTL from SSSS on'
- ;line 6
- db cr,lf,'CNNNN,X set CTL (X=BEHISW or K) '
- db 'DSSSS dump bytes from SSSS on'
- ;line 7
- db cr,lf,'DSSSS,EEEE dump bytes over range '
- db 'D,EEEE dump thru EEEE'
- ;line 8
- db cr,lf,'D dump a page more '
- db 'D=NN bytes (not lines)/dump (HEX)'
- ;line 9
- db cr,lf,'DS dump the Symbol Table '
- db 'DS.Label dump SMB from Label on'
- ;line 10
- db cr,lf,'ENNNN,.Label enter Label at NNNN '
- db 'DSssss dump SMB from ssss on'
- ;line 11
- db cr,lf,'K.Label kill Label from Table '
- db 'U Unassemble entire pgm'
- ;line 12
- db cr,lf,'USSSS,EEEE Unasm over range '
- db 'U,EEEE Unasm to EEEE'
- ;line 13
- db cr,lf,'USSSS Unasm 20 lns from SSSS '
- db 'U=NN Set no. lines to Unasm'
- ;line 14
- db cr,lf,'O display Current ORG '
- db 'ONNNN Set new ORG'
- ;line 15
- db cr,lf
- ;line 16
- db cr,lf,'RNNNN sets, R shows para in RAM to unassemble if '
- db 'no file is loaded'
- ;line 17
- db cr,lf,'L[d:][\path\]name.COM .CTL .SMB .REM .ALL'
- db ' Load files (no .ext same as .ALL)'
- ;line 18
- db cr,lf,'F9 save .CTL, .SMB, .REM files '
- db 'N trash .CTL, .SMB, .REM files'
- ;line 19
- db cr,lf,'W enables saving as you '
- db 'Unassemble. Stops at END or Z closes'
- ;line 20
- db cr,lf,'Z close .RSM file '
- db '? print Statistics'
- ;line 21
- db cr,lf
- ;line 22
- db cr,lf,'enter Q or hit ESC, Q to exit to DOS'
- ;line 23 & 24
- db cr,lf,tab,tab,tab,196,196,196,'PgDn for next help page'
- db 196,196,196,cr,lf,'$'
-
- extnd_help db ' Commands Continued'
- db cr,lf,cr,lf,'T toggle display of label addresses as comments'
- db cr,lf
- db cr,lf,'SWWWW search for WWWW'
- db cr,lf,'S continue search for WWWW '
- db 'SWWWW,SSSS search WWWW after SSSS'
- db cr,lf,'ANY KEY stops search. WWWW is in reverse order in RAM!'
- db cr,lf,cr,lf,'P lets you edit path to save/load.'
- db cr,lf,cr,lf,'Control meanings:',cr,lf
- db ' B=Bytes in ASCII H=Bytes in hex E=END (ends Unassembly)'
- db cr,lf,' I=Instructions S=Same [DB n DUP (x)] W=Words'
- db cr,lf,' K=Kill CTL at this addr'
- db cr,lf,cr,lf,'You can enter .YourLabel in place of any address'
- db cr,lf,cr,lf,cr,lf
- db 'Run RE-SOURC [d:][\path\]filename to load filename.COM (or '
- db '.EXE or .SYS),'
- db cr,lf,' .REM, .CTL, and .SMB'
- db ' automatically. Files must all be in same directory.'
- db cr,lf,cr,lf,'PGDN works, CTRL-PGUP goes to start, '
- db 'down arrow does 1 more line',cr,lf
- db cr,lf,196,196,196,'PgUp for previous help page'
- db 22 dup (196)
- db 'PgDn for next help page',196,196,196
- db cr,lf,'$'
-
- instrs db tab,tab,tab,tab,'INSTRUCTIONS',cr,lf,cr,lf
- db 'Lfilename (or .ALL) loads target program and .SMB, .REM, .CTL'
- db cr,lf,cr,lf,'Load any file with Lfilename.ext '
- db cr,lf,cr,lf,'For unusual programs, use O to set ORG as desired.'
- db cr,lf,cr,lf,'A finds approx location of DBs.'
- db cr,lf,cr,lf,'Build .SMB (label) table with B. Some'
- db ' labels will not show until next U.'
- db cr,lf,cr,lf,'Enter or change labels with ENNNN,.Label',cr,lf
- db 'Add remarks with ;NNNN,inserted remark or '
- db ';NNNN,;appended remark'
- db cr,lf,cr,lf,'F9 saves the .SMB, .CTL, and .REM files.'
- db cr,lf,cr,lf,'To write a .RSM "source" file,'
- db ' hit W and then U.'
- db cr,lf,cr,lf,cr,lf
- db 'RE-SOURCE works only on the first 64K of a program...'
- db cr,lf,' use ? to find and R to set seg of next 64K.'
- db cr,lf
- db cr,lf,tab,tab,tab,196,196,196,'PgUp for previous help page'
- db 196,196,196,cr,lf,'$'
- ;--------------------------------
- cmtrim: mov al,trmflg
- not al
- mov trmflg,al
- or al,al
- jz LblAdrsOn
- call prtstr
- db 'Label Addresses Off',cr,lf,0
- jmp nxcmd
- LblAdrsOn:
- call prtstr
- db 'Label Addresses On',cr,lf,0
- jmp nxcmd
-
- ;--------------------------------
- cmpurg: call prtstr
- db 'purge .SMB (labels), .REM, & .CTL tables? (Y/N)',0
- call gtcmd
- mov al,byte ptr cmdbuf+2
- cmp al,'Y'
- jnz NoPurge
- call erstbl ;empty the segment tables
- mov segsho,205 ;replace seg char in prompt arrow
- mov PgmParas,0 ;size of loaded pgm
- jmp Restart
-
- NoPurge:
- jmp nxcmd
-
- ;--------------------------------
- ;all calls commented out
- sgreqs: mov bx,offset cmdbuf+4 ;check for segment prefix, e.g. UDS:1234
- mov ax,[bx] ; (remember,1st char of cmd @ cmdbuf+2)
- cmp ax,word ptr lblS ;is xS: there?
- jz updseg ;yes, find which and set
- ret ;else do nothing
- lblS db ':S' ;backwards since lo-hi in RAM
-
- updseg: dec bx
- mov al,[bx] ;first seg char, C or D or E or S
- sub ah,ah ;start at 0
- cmp al,'C'
- jz segmch
- inc ah
- cmp al,'D'
- jz segmch
- inc ah
- cmp al,'E'
- jz segmch
- inc ah
- cmp al,'S'
- jz segmch
- ret ;ignore any others
- ;segmch used only in this routine
- segmch: mov segsho,al ;for cmd. prompt display
- mov segflg,al ;seg req given
- mov al,ah ;count value
- sub ah,ah
- mov bx,ax ;in a base reg
- add bx,offset segmtb
- mov cl,cs:[bx] ;get bit pattern
- mov OprndType,cl ;init symbol select
- mov bl,12 ;size of segment record
- mul bl ;index segment records
- mov bx,offset cofset ;segment para word base
- add bx,ax ;index to right seg.
- mov ax,[bx] ;get this para value
- mov curpar,ax ;to active para holder
- mov ax,-8[bx] ;get segment length
- mov cl,4
- shl ax,cl ;convert to bytes
- mov segsiz,ax ;for ctl table limits
- mov dx,offset cmdbuf[3] ;dest
- mov bx,offset cmdbuf[6] ;source
- ;squeeze out segment chars
- l03b2: mov al,[bx] ;move cmd line
- xchg bx,dx
- mov [bx],al ;down a notch
- xchg bx,dx
- inc bx
- inc dx
- cmp al,cr
- jnz l03b2
- ret
-
- segmtb db 0Ch,04h,08h,0
-
- ;--------------------------------
- cmdump: ;call sgreqs
- mov dx,DumpStart
- mov bx,dmpcnt
- add bx,dx
- mov DumpEnd,bx
- mov bx,offset cmdbuf+3
- mov al,[bx] ;2nd cmd char
- cmp al,cr
- jz dmphdr ;continue last dump
- cmp al,'S' ;DS command, dump symbol table
- jnz l0411
- mov al,[bx+1] ;next char
- cmp al,':' ;segment req coming?
- jz l0411 ;looks like it, not DS command
- jmp DumpSym
-
- l0411: cmp al,'=' ;is this a dump length change ?
- jnz l0418
- jmp SetDumpCt
-
- l0418: cmp al,',' ;Dump to end addr only
- jz dump1
- ;Dump from DumpStart (user input DNNNN)
- dump0: call gtval ;rets w/bx>char past number, dx=addr less curorg
- jnc notneg ; and carry if DX<0
- xor dx,dx ;If Dump addr before ORG, start at ORG
- notneg: push bx
- mov bx,dmpcnt
- add bx,dx
- mov DumpEnd,bx
- pop bx
- dump1: cmp al,cr
- jz dump3
- call delim
- inc bx
- push dx
- call gtval
- xchg bx,dx
- mov DumpEnd,bx
- pop dx
- dump3: mov DumpStart,dx
- cmp al,cr
- jz dmphdr
- call cmerr
-
- dmphdr: call prtstr
- db 'Addr +0+1 +2+3 +4+5 +6+7 +8+9 +A+B +C+D +E+F'
- db tab,196,196,196,'ASCII',196,196,196,cr,lf,0
- cntdmp: mov bx,DumpStart
- mov es,curpar
- dump4: call BreakChk
- push bx ;BX is pointer to code wrt start of target pgm
- add bx,curorg
- call Print00BX_
- pop bx
- push bx
- call prspc
- dmpln: mov es,curpar
- mov al,es:[bx]
- call xo
- inc bx
- mov al,bl
- and al,1
- jnz wdspc1
- call prspc
- wdspc1: mov al,bl
- and al,3
- jnz wdspc2
- call prspc
- wdspc2: mov al,bl
- and al,7
- jnz wdspc3
- call prspc
- wdspc3: mov al,bl
- and al,0fh
- jnz dmpln
- call prspc
- pop bx
- dmpasc: mov es,curpar
- mov al,es:[bx]
- cmp al,' ' ;20h
- jb period
- cmp al,7Fh
- jb chrctr
- period: mov al,'.' ;2eh
- chrctr: call typech
- inc bx
- mov al,bl
- and al,0Fh
- jz lcmplt
- and al,7
- jnz wdspc4
- call prspc
- wdspc4: jmp dmpasc
-
- lcmplt: call prspc
- call pstg
- db cr,lf,0
- mov DumpStart,bx
- mov ax,DumpEnd
- sub ax,bx
- jnb dump4
- jmp nxcmd
-
- ;set no of bytes per dump (dmpcnt)
- SetDumpCt:
- inc bx
- call gtval
- add dx,curorg ;gtval subtracts curorg!
- inc bx
- dec dx
- xchg bx,dx
- mov dmpcnt,bx
- xchg bx,dx
- l04e8: cmp al,cr
- jnz l04ef
- jmp nxcmd
-
- l04ef: call delim
- jmp dump0
-
- ;--------------end of Dump command-------------
-
- ;DUMP THE SYMBOL TABLE
- ; Table is 2 byte addr, 1 byte Seg/Type, 1 byte length, n bytes string
-
- DumpSym:
- mov EntriesLeft,4 ;init items/line
- mov bx,offset cmdbuf+4 ;1st past the DS
- mov al,[bx]
- cmp al,cr
- jz frmbgn
- call gtval
- call symluk
- mov bx,NxtSymPtr ;> this or next higher label
- jmp frmsym
-
- frmbgn: mov bx,symbas
- frmsym: call prtstr
- db 'KEY: 1st char = CS, DS, ES, SS '
- db '2nd char = Byte, Word, Dword, Undefined',cr,lf,cr,lf,0
- NxtSym: mov dx,[bx] ;start of a SMB entry, the addr
- inc bx
- inc bx
- inc bx
- mov al,[bx] ;string length
- or al,al
- jz DSdone ;end of table reached
- l051a: push dx ;addr
- push bx ;pointer to string length
- dec bx
- add dx,curorg ;correct all addrs for ORG
- xchg bx,dx ;must be in BX to print
- call Print00BX_ ;print address in BX, + space
- pop bx ;pointer to length byte
- pop dx ;addr
- dec bx
- mov al,[bx] ;OprndType byte
- inc bx ;back to length byte
- xor ah,ah
- push ax ;save type byte
- mov bp,offset ltable
- and al,00110000b ;get bits 4 & 5
- mov cl,4
- shr al,cl ;into bits 0 & 1
- mov si,ax
- mov al,[bp+si]
- call typech ;print seg char, S D E or C
- pop ax
- and al,3 ;get bits 0 & 1
- mov si,ax
- mov al,[bp+si+4]
- call typech ;print Type char, U B W or D
- mov al,' '
- call typech ;print a space
- mov cl,[bx] ;length of label
- xor ch,ch
- inc cx ;length + 1 to
- add cx,bx ; point to next label field
- mov NxLblPtr,cx ;save pointer
- mov cl,10 ;always print 10d bytes
- inc bx ;to 1st char of label
- ;print the label, truncated or padded out to 10d characters
- spit: mov al,[bx]
- call typech
- inc bx
- dec cl ;keep count of bytes printed
- jz EntryDone
- cmp bx,NxLblPtr
- jnz spit
- PadLoop:
- call prspc
- dec cl
- jnz PadLoop
- EntryDone:
- call ChkEntryCt
- call BreakChk
- mov bx,NxLblPtr
- jmp NxtSym
-
- ltable db 'SDECUBWD'
-
- DSdone: call prtstr
- db cr,lf,0
- jmp nxcmd
-
- ;after printing entry, see if line is finished (for CTL and SYM dump)
- ChkEntryCt:
- dec EntriesLeft
- jz NotherLine
- call prspc
- call prspc
- ret
-
- ;new line of 4 entries
- NotherLine:
- call CrLf
- mov EntriesLeft,4
- ret
- ;--------------------------------
- ;SET ORG ADDRESS
- cmorg: ;call sgreqs ;any segment data?
- mov bx,offset cmdbuf+3 ;1st char after the O
- mov al,[bx]
- cmp al,cr
- jz prntos ;just show curr value
- call gtval ;new ORG (less old ORG) from user to DX
- add dx,curorg ;correct it for old curorg
- cmp al,cr ;end of entry ?
- jz l0557
- call cmerr
-
- l0557: mov curorg,dx ;this is the ORG for display
- prntos: call prtstr
- db 'ORG = ',0
- mov bx,curorg
- call Print00BX_
- call CrLf
- jmp nxcmd
-
- ;--------------------------------
- ;ATTEMPT TO FIND DBs
- cmatmt: mov AmodeFlag,1
- mov BmodeFlag,0
- jmp short list1
- ;BUILD SYMBOL TABLE
- cmbld: mov BmodeFlag,1
- mov AmodeFlag,0
- jmp short list1
-
- ;UNASSEMBLE at [pcntr] but show addr [pcntr+curorg], & A or B if reqd
- CmUnasm:
- mov BmodeFlag,0
- mov AmodeFlag,0
- list1: mov wfiflg,0 ;write to display only
- mov al,LnsPerScreen ;no. of lines to show
- mov LinesToGo,al
- mov LCountFlag,al ;show specific no of lines
- ; call sgreqs ;check cmdbuf for segment spec.
- mov bx,offset cmdbuf+3 ;1st char after the U, A, or B
- mov al,[bx]
- cmp al,cr
- jz ToTheEnd
- cmp al,','
- jz list3 ;no starting location
- cmp al,' '
- jz list3 ;no starting location
- cmp al,'='
- jnz list2
- jmp SetLineCount ;change default no of lines
-
- ToTheEnd:
- mov pcntr,0
- mov dx,0FFFFh
- jmp short list4
-
- ;U B or A from given location
- list2: call gtval ;get start pcntr=input-curorg
- mov pcntr,dx ;where to start
- cmp al,cr
- jz TwentyLines ;only start given
- call delim
- list3: inc bx ;past delimiter
- call gtval ;get ending location
- list4: mov lastwd,dx
- mov LCountFlag,0 ;not specific line count
-
- ;--------------------------------
- ;U B or A default no. of lines - always entered w/wfiflg=0
-
- TwentyLines:
- call BreakChk ;check for Ctrl-Break w/DOS func 01
- cmp LCountFlag,0
- jz contl ;end addr was input, do reqd no lines
- mov al,LinesToGo
- dec al
- jns flagck ;another line if screen not full
- jmp nxcmd
-
- contl: mov es,curpar ;para of target pgm
- mov ax,pcntr
- sub ax,lastwd
- jb flagck ;not at end
- jmp nxcmd
-
- flagck: cmp AmodeFlag,0
- jnz Attempt
- jmp morel ;not in 'Attempt find DBs' mode
-
- ;ATTEMPT TO FIND DB's WHILE UNASSEMBLING, insert CTL where found
- ;first, search for DUPs
- Attempt:
- mov di,pcntr
- mov es,curpar
- mov al,es:[di] ;get 1st byte of line
- mov cx,17 ;to find 16 DUPs
- repz scasb
- or cx,cx
- jnz ChkASCII
- ;16 DUPs in a row have been found, CX is 0
- dec cx ;to FFFFh
- dec di ;back to 1st un-scanned byte
- repz scasb
- mov bx,di
- mov Control,'S'
- call SetControl
- jmp morel
-
- ChkASCII:
- mov bx,pcntr
- mov cx,8 ;no. of ASCII chars to call it a DB line
- mov es,curpar
- loop8: mov al,es:[bx]
- call IfASCII ;test one byte for DB
- jc morel ;not a DB line
- inc bx
- loop loop8 ;must find 8 ASCII chars in a row
- ;8 ASCII chars in a row have been found
- follow: mov al,es:[bx]
- inc bx
- call IfASCII ;keep looking for ASCII
- jnc follow
- mov Control,'B'
- call SetControl
- jmp morel
- ; . . . . . . . . . . . . . . . .
- SetControl: ;insert Control if none here
- dec bx ;to 1st non-ASCII/non-DUP byte
- push bx
- mov dx,pcntr ;start addr of line
- call ctlook
- jc okchg ;if no ctl at this location
- cmp byte ptr [bx+3],'E' ;if ctl exists
- pop bx
- jz morel ;don't overwrite END ctl
- push bx
- okchg: mov dx,pcntr
- mov al,Control
- call EnterCTL ;make entry in CTL table
- ;insert I ctl where ASCII bytes/DUPs end
- pop dx ;was BX, last byte + 1
- cmp word ptr PgmBytes+2,0
- jnz NoENDp ;there is no END ctl if >64K
- cmp dx,PgmBytes
- jc NoENDp ;if not past end
- push dx
- mov dx,PgmBytes
- call ctlook ;is there a ctl at end locn ?
- pop dx
- jc NoENDp
- ;under 64K, past end, there is a ctl at end
- cmp byte ptr [bx+3],'E' ;is the ctl at end really END ?
- jz morel ;if so, no ctl past END
- NoENDp: call ctlook
- jc okchg2 ;no ctl at this location
- cmp byte ptr [bx+3],'E'
- jz morel ;don't overwrite END ctl
- okchg2: mov al,'I' ;back to 'I' at end
- jmp EnterCTL
- ; . . . . . . . . . . . . . . . .
-
- ;Jump here if not in A mode
- morel: mov bx,remtbl
- cmp bx,remend
- jz ncmt ;remark table is empty
- mov dx,pcntr
- call RemChk ;test for poss. remark at [DX]
- jc ncmt ;if none
- ;remark exists, BX points to its matching addr
- inc bx
- inc bx ;skip addr field
- mov ch,[bx] ;byte count of remark
- mov al,[bx+1] ;first remark character
- cmp al,';' ;append it?
- jnz morel1
- mov AppendPtr,bx
- jmp ncmt
-
- morel1: call DoRemark ;print the remark
- call CrLf
- jmp ncmt
- ; . . . . . . . . . . . . . . . .
- ;print remark like this on separate line(s)
- DoRemark:
- mov wfiflg,1
- call semic ;start lines with a semicolon
- or ch,ch ;check for zero-length remark
- jnz RemContinues
- ret
-
- RemContinues:
- inc bx
- mov al,[bx]
- cmp al,'\' ;multi-line remark ?
- jnz NoBkslash
- call CrLf ;break remark here
- dec ch
- jmp DoRemark
-
- NoBkslash:
- call typech
- dec ch
- jnz RemContinues
- ret
- ; . . . . . . . . . . . . . . . .
- ;Line is not remark, or remark is done. Every line goes thru here.
- ncmt: mov RelFlag,1 ;line labels not corrected for Org
- mov dx,pcntr ;get address of line
- call ctlook ;CTL entry for this addr?
- ; (rets w/BX>ctlbas+0, 4, etc)
- jc SameMode ;carry=not matched addr, use old mode
- add bx,4 ;use mode of matched addr
- SameMode:
- dec bx ;to mode byte (prev mode if no change)
- mov al,[bx] ;mode char, is at ctlbas-1, +3, +7, etc
- cmp al,'I'
- jnz not_i
- mov ColonFlag,0 ;put colon after label
- call AddrOrSmb ;print any label, or addr=pcntr+curorg
- mov RelFlag,0 ;default not relative JMP, CALL, etc
- mov SegOvrdPfx,0 ;just in case
- call dline ;disassemble one line as instruction
- mov wfiflg,0 ;write to screen only
- jmp TwentyLines ;and go to the next line.
-
- not_i: mov ColonFlag,1 ;no colon after label
- call AddrOrSmb ;print any label, or addr=pcntr+curorg
- ;RelFlag stays = 1 so symluk looks for lbls w/o correction
- cmp al,'E' ;is it the END ?
- jnz notend
- jmp cmeof ;show end & stop
-
- notend: inc bx ;to next CTL record
- mov dx,[bx+1] ;address
- mov nxtctl,dx ;save to end Hex, Byte & Space lines
- mov wfiflg,0
- cmp al,'S' ;space mode ?
- jnz ckbmd
- jmp Smode
-
- ckbmd: cmp al,'B' ;byte ASCII mode ?
- jnz ckhmd
- jmp bmode
-
- ckhmd: cmp al,'H' ;hex mode ?
- jnz ckwmd
- jmp hmode
-
- ckwmd: cmp al,'W' ;word mode ?
- jnz badmd
- jmp wmode
-
- badmd: call typech
- call prtstr
- db ' INVALID CTL ENTRY - check .CTL file at this location.',cr,lf,0
- jmp nxcmd
- ;--------------------------------
- ;SET NO OF LINES TO UNASSEMBLE
- SetLineCount:
- inc bx
- call gtval ;input less curorg to DX
- add dx,curorg ;correct it
- or dh,dh ;now check for more than a screen full
- jnz toerr ; and zero lines
- mov al,dl
- or al,al ;test if more than 0
- jz toerr
- cmp al,24
- jc linesok ;23d lines max
- toerr: call cmerr
-
- linesok:
- mov LnsPerScreen,al
- mov LinesToGo,al
- mov al,[bx] ;char in cmdbuf after input no.
- inc bx
- l0776: cmp al,cr ;just set no. of lines?
- jnz l077d
- jmp nxcmd
-
- l077d: call delim
- jmp list2
- ;--------------------------------
- ;S(ame) control, n DUP (x).
- Smode: mov wfiflg,1
- call pstg
- db 'DB',tab,0
- mov ax,NxtSymAddr
- or ax,ax ;note: * problem if >64K file *
- jz UseNxtctl ;if no next label; always is an E ctl
- mov EndSameAddr,ax
- cmp ax,nxtctl ;ESAddr - nxtctl
- jc FindNxtDif
- UseNxtctl:
- mov ax,nxtctl
- mov EndSameAddr,ax
- FindNxtDif:
- mov di,pcntr
- mov es,curpar
- mov al,es:[di] ;get 1st byte of DUPs
- xor cx,cx
- dec cx ;limit 64K REPs
- repz scasb ;1st NZ will still INC DI
- dec di ;to 1st byte past match
- cmp di,EndSameAddr ;1st different - next ctl or smb
- jnc PrintDUP
- mov EndSameAddr,di
- PrintDUP:
- push ax ;save the DUP char
- mov dx,EndSameAddr
- sub dx,pcntr ;ESAddr - pcntr, * NFG over 64K *
- call PrintDXh
- call pstg
- db ' DUP (',0
- pop ax ;the DUP char
- call PrtALasDB
- call pstg
- db ')',0
- mov dx,EndSameAddr
- mov pcntr,dx
- jmp StopLine
- ;--------------------------------
- ;'W' control, words ***** needs to chk for SMB/CTL at 2nd byte, chg to DB.
- wmode: mov wfiflg,1
- call pstg
- db 'DW',tab,0
- mov bx,pcntr
- mov es,curpar
- mov dx,es:[bx]
- call PrintDXh
- inc pcntr
- inc pcntr
- StopLine:
- call NewLine
- jmp TwentyLines
- ;--------------------------------
- ;Byte-ASCII & Hex byte modes
- hmode: mov BytesFlag,0
- jmp short bmode1
-
- bmode: mov BytesFlag,1 ;flag Bytes ASCII, not HEX
- bmode1: mov wfiflg,1 ;write to file, too
- call pstg
- db 'DB',tab,0
- mov strcnt,0 ;chars on this line, any print bumps
- mov CrLfFlag,0 ;for Bytes ASCII
- mov bx,pcntr
- mov es,curpar
- cmp BytesFlag,0
- jz PrtAsHex ;jump for sure if Hex mode
- ;CTL is Byte mode, but use Hex routine if unprintable:
- ChkHex: mov al,es:[bx]
- call ChkSpl
- jz ToDoASCII
- cmp al,' '
- jb ChkComma ;no print other ctrl codes in Byte mode
- cmp al,7Fh
- jnb ChkComma ;7Fh and over also unprintable
- ToDoASCII:
- jmp DoASCII
-
- ChkComma:
- cmp strcnt,0
- jz PrtAsHex
- call comma
- PrtAsHex:
- mov al,es:[bx]
- call PrintALh
- inc bx
- inc pcntr
- ;end Hex line if up to a CTL change
- cmp bx,nxtctl
- jnz trysym
- jmp StopLine
-
- ;end Hex line if up to a label
- trysym: cmp bx,NxtSymAddr ;set by symluk when line addr printed
- jnz NoHexSmb
- jmp StopLine
-
- ;end Hex line if up to 31d chars
- NoHexSmb:
- cmp strcnt,31
- jb NotHexMax
- jmp StopLine
-
- NotHexMax:
- cmp BytesFlag,0
- jz ChkComma ;if in Hex mode
- jmp ChkHex ;if in Bytes ASCII mode
-
- ChkSpl: xor ah,ah
- cmp al,cr
- jz CRet
- add ah,3
- cmp al,lf
- jz CRet
- add ah,3
- cmp al,tab
- jz CRet
- add ah,3
- cmp al,bel
- jz CRet
- add ah,3
- or al,al
- CRet: ret ;w/Z if match
-
- XpandTbl db 'cr.lf.tabbel0..'
-
- ;ASCII byte printing loop
- MoreASCII:
- call ChkSpl
- jnz NoXpand
- ;print expanded special characters
- cmp strcnt,0
- jz PrtSpl
- cmp byte ptr es:[bx-1],' '
- jb JusComma
- cmp byte ptr es:[bx-1],7Fh
- jnb JusComma
- call apostrophe ; ' if prev char was ASCII, not special
- JusComma:
- call comma ;comma before special chars
- PrtSpl: mov al,ah
- push bx
- mov bx,offset XpandTbl
- call Prt3FromTabl
- pop bx
- ;a Zero after anything else ends the line
- cmp ah,12d ;did we just print a '0' ?
- jnz SameByte
- cmp strcnt,1
- jz SameByte ;if it was 1st on the line
- cmp byte ptr es:[bx-1],0
- jz SameByte
- inc pcntr
- jmp StopLine ;end the line unless prev char also '0'
-
- NoXpand:
- cmp strcnt,0
- jz Apost
- cmp byte ptr es:[bx-1],' '
- jb Cmma
- cmp byte ptr es:[bx-1],7Fh
- jnb Cmma
- jmp short PrtIt
- Cmma: call comma ;if prev spl or Hex & this is not 1st
- Apost: call apostrophe ;if 1st or prev was special or Hex
- PrtIt: call typech ;print to screen and/or file buffer
- SameByte:
- mov al,es:[bx] ;get byte just printed
- cmp al,'''' ;27h, single quote
- jnz NotQuote
- call typech ;for special case of quote char only
- NotQuote:
- inc pcntr ;bump character pointer
- mov bx,pcntr
- ;end ASCII line if up to a Control location
- cmp bx,nxtctl
- jnz NoEnd
- ToEndQ: jmp EndQuote
- ;end ASCII line with any '$'
- NoEnd: cmp al,'$'
- jz ToEndQ
- ;end ASCII line if up to a label
- mov dx,pcntr
- cmp dx,NxtSymAddr ;set by symluk when line addr printed
- jz ToEndQ
- ;end ASCII line if up to 50d chars
- cmp strcnt,49
- jnb ToEndQ
- ;end the line after a space if line is 40-49 chars long
- cmp strcnt,40
- jb DoASCII
- mov bx,pcntr
- cmp byte ptr es:[bx-1],' ' ;was just-printed char a space ?
- jz ToEndQ
- ;Entry point for Byte Mode, printable codes only.
- DoASCII:
- mov bx,pcntr
- mov al,es:[bx] ;get next char
- cmp al,cr
- jz CRorLF
- cmp al,lf
- jnz ChkPrn
- CRorLF:
- cmp CrLfFlag,1
- jnz SetCL
- jmp MoreASCII ;just printed a cr or lf
-
- SetCL: mov CrLfFlag,1
- cmp strcnt,0
- jnz EndQuote ;1st CR/LF after others => new line
- jmp MoreASCII ;cr or lf is 1st on the line
-
- ;Check if next char is printable. It is not a cr or lf.
- ChkPrn: call ChkSpl
- jz ToMoreASCII
- cmp al,' ' ;20h
- jb EndQuote
- cmp al,7Fh
- jnb EndQuote
- mov CrLfFlag,0
- ToMoreASCII:
- jmp MoreASCII ;go print the char & keep going
-
- EndQuote:
- mov al,es:[bx-1]
- call ChkSpl
- jz ToStop ;no closing ' if just printed special
- call apostrophe
- ToStop: jmp StopLine
- ;--------------------------------
-
- CmStats:
- call prtstr
- db cr,lf,'RE-SOURC PSP at Segment. ',0
- mov bx,cs
- call Print00BX_
- call prtstr
- db cr,lf,'Target Pgm at Segment... ',0
- mov bx,curpar
- call Print00BX_
- call prtstr
- db cr,lf,'Loc in Pgm Now-Last+1.. ',0
- mov bx,pcntr
- add bx,curorg
- call Print00BX_
- mov bx,PgmBytes ;**64K max**
- add bx,curorg
- call Print00BX_
- call prtstr
- db cr,lf,cr,lf,'Offsets into RE-SOURCE segment:'
- db cr,lf,'CTL Table Start-End.... ',0
- mov bx,offset ctlbas
- call Print00BX_
- l0984: mov ax,1[bx]
- and al,ah
- add bx,4
- inc al
- jnz l0984
- sub bx,4
- call Print00BX_
- call prtstr
- db cr,lf,'SMB (labels) Start-End.. ',0
- mov bx,symbas
- call Print00BX_
- mov bx,symtp
- call Print00BX_
- call prtstr
- db cr,lf,'REM Table Start-End..... ',0
- mov bx,remtbl
- call Print00BX_
- mov bx,remend
- call Print00BX_
- call prtstr
- ; db cr,lf,cr,lf,'SEG. LGTH BASE SMIN SMAX PARA',0
- db cr,lf,cr,lf,0
- ; mov bx,offset cstbl
-
- ;sgplp: mov al,[bx]
- ; or al,al
- ; jz sgpends ;found end flag
- ; cmp al,' ' ;used entry?
- ; jnz usdseg
- ; add bx,12
- ; jmp short sgplp
- ;usdseg: mov ch,2 ;print 2 chars
- ; call PrtCHbytesPerBX ;(seg label & order no)
- ; call prtstr
- ; db ': ',0
- ; call prwval
- ; call prwval
- ; call prwval
- ; call prwval
- ; call prwval
- ; call CrLf
- ; jmp short sgplp
- ;sgpends:
- jmp nxcmd
-
- prwval: mov dx,[bx]
- xchg bx,dx
- call Print00BX_
- xchg bx,dx
- inc bx
- inc bx
- ret
- ;--------------------------------
- ;SEARCH FOR HEX WORD
- CmSearch:
- ;call sgreqs
- mov bx,offset cmdbuf+3 ;1st char after the S
- mov al,[bx]
- cmp al,cr
- jz ContinueSearch
- call gtval ;word to search for to DX (less curorg)
- add dx,curorg ;correct it
- mov fndadd,dx
- mov SearchPointer,0
- xor dx,dx
- cmp al,cr
- jz ContinueSearch
- call delim
- l09c6: inc bx
- call gtval ;start addr of search to DX (w.r.t. ORG)
- cmp al,cr
- jz StartSearch
- call cmerr
-
- StartSearch:
- mov es,curpar
- mov SearchPointer,dx
- ContinueSearch:
- call prtstr
- db 'Lo-Hi word found at ',0
- mov bx,fndadd
- xchg bx,dx
- ;this is the step-&-compare loop
- nyet: call BreakChk
- ;check for end of pgm
- mov ax,PgmBytes ;end of pgm **64K max**
- mov bx,SearchPointer
- cmp bx,ax
- jng NotPast
- call prtstr
- db cr,lf,'End of program reached',cr,lf,0
- jmp nxcmd
- NotPast:
- mov es,curpar
- mov al,es:[bx] ;get byte in target pgm
- inc bx
- mov SearchPointer,bx
- cmp al,dl ;match?
- jnz nyet
- mov es,curpar
- mov al,es:[bx] ;get next byte
- cmp al,dh ;match too?
- jnz nyet
- ;the word matches
- push bx
- push dx
- dec bx
- add bx,curorg ;correct the find addr for ORG
- call Print00BX_
- pop dx
- pop bx
- call prspc
- jmp nyet ;continue searching
-
- ;--------------------------------
- ;The 'Z' command, also used when Control E found while Unassembling.
- cmeof: mov al,ASMopenFlag
- or al,al
- jnz CloseRSM
- call pstg
- db 'END',cr,lf,0 ;to screen only
- jmp nxcmd
-
- CloseRSM:
- mov wfiflg,1 ;print to file, too
- call pstg
- db cr,lf,'CSEG',tab,'ends'
- db cr,lf,tab,'END',0
- cmp EXTflag,'C'
- jz DoStart
- cmp EXTflag,'E'
- jnz StartFin
- DoStart:
- call pstg
- db tab,'Start',cr,lf,0
- StartFin:
- call WriteNclose ;add 1Ah, flush buffer to disk
- mov wfiflg,0 ;no more printing to file
- mov ASMopenFlag,0
- call prtstr
- db cr,lf,'.RSM file is closed',cr,lf,0
- jmp nxcmd
-
- ;--------------------------------
- EXTtoSpec:
- mov di,DotPtr
- inc di
- ;put \path\name or .ext [BX] in FileString [DI] - stops at a '.' w/C set
- MoveField:
- mov al,[bx]
- cmp al,cr
- jz MovDone
- mov [di],al
- cmp al,'.'
- jz DotFound
- or al,al
- jz MovDone
- inc di
- inc bx
- jmp short MoveField
-
- MovDone:
- clc
- ret
-
- DotFound:
- stc
- ret
-
- ;--------------------------------
- cmload: mov al,ASMopenFlag
- or al,al
- jz OKtoLoad
- jmp ASMstillOpenErr
-
- OKtoLoad:
- mov bx,offset cmdbuf+3 ;BX > 1st char after the 'L'
- mov al,byte ptr cmdbuf+4 ;2nd char after the 'L'
- cmp al,' ' ;2nd char blank?
- jnz NameEntered
- call cmerr
-
- NameEntered:
- mov di,offset FileString
- cmp al,':' ;drive specified ?
- jnz nodriv
- mov al,byte ptr cmdbuf+3
- inc bx
- inc bx ;to 1st char after the colon
- mov byte ptr [di],al
- inc di
- mov byte ptr [di],':'
- inc di ;to area for \path\name
- nodriv: call MoveField ;get \path\name, stops at a '.'
- mov DotPtr,di ;save pointer to the '.'
- mov byte ptr [di],'.' ;in case no '.' found
- jnc SpecDone
- inc di ;to byte after the dot
- inc bx
- call MoveField ;get .EXT
- mov byte ptr [di],0 ;mark end of ASCIIZ string
- stc
- SpecDone:
- jnc wntall ;if no .EXT entered
- mov dx,offset LitALL
- mov cl,3 ;bytes to compare at [BX]
- call cmpstr
- jz wntall ;want .ALL files
- jmp ntlall ;if .EXT other than .ALL entered
- wntall: call LoadAll
- jmp nxcmd
-
- LoadAll:
- mov EXTflag,0
- ;try to load any file with name.COM, .EXE, or .SYS
- call prtstr
- db cr,lf,'Loading target file..',0
- mov EXTflag,'C' ;in case a .COM is found
- mov bx,offset LitCOM
- call EXTtoSpec ;'COM',0 to filespec
- call LoadPGM
- jnc TargetLoadDone ;if successful
- mov EXTflag,'E'
- mov bx,offset LitEXE
- call EXTtoSpec
- call LoadPGM
- jnc TargetLoadDone
- mov EXTflag,0
- mov bx,offset LitSYS
- call EXTtoSpec
- call LoadPGM
- jnc TargetLoadDone
- call prtstr
- db tab,tab,tab,'.COM, .EXE, or .SYS FILE NOT FOUND',0
- TargetLoadDone:
- mov bx,offset LitREM
- call EXTtoSpec
- call prtstr
- db cr,lf,'Loading .REM file..',0
- call LoadREM
- mov bx,offset LitCTL
- call EXTtoSpec
- call prtstr
- db cr,lf,'Loading .CTL file..',0
- call LoadCTL
- mov bx,offset LitSMB
- call EXTtoSpec
- call prtstr
- db cr,lf,'Loading .SMB file..',0
- call LoadSMB
- call crlf
- ret
-
- ntlall: mov bx,DotPtr
- inc bx
- mov cl,3
- mov dx,offset LitSMB ;LitSMB holds 'SMB'
- call cmpstr
- jnz AintSMB
- call LoadSMB
- call crlf
- jmp nxcmd
-
- AintSMB:
- mov dx,offset LitCTL
- call cmpstr
- jnz AintCTL
- call LoadCTL
- call crlf
- jmp nxcmd
-
- AintCTL:
- mov dx,offset LitREM
- call cmpstr
- jnz AintREM
- call LoadREM
- call crlf
- jmp nxcmd
-
- AintREM:
- mov dx,offset LitALL
- call cmpstr
- jnz AsTarget
- call LoadALL
- jmp nxcmd
-
- ;load any other .ext as target pgm
- AsTarget:
- mov EXTflag,0
- mov dx,offset LitCOM
- call cmpstr
- jnz TryEXE
- mov EXTflag,'C'
- jmp short NowLd
- TryEXE: mov dx,offset LitEXE
- call cmpstr
- jnz NowLd
- mov EXTflag,'E'
- NowLd: call LoadPGM
- jnc TgtMsg
- call OpenError
- call crlf
- jmp nxcmd
-
- TgtMsg: call prtstr
- db 'Loaded specified file as target program.',cr,lf,0
- jmp nxcmd
-
- ;--------------------------------
- ;LOAD pgm at curpar (end of RE-SOURC + buffers) & set pcntr to 0
-
- LoadPGM:
- call fopen ; open file. Saves BX.
- jnc cmdlds ; opened successfully
- ret
- ;this is approx 1A70 in code
- cmdlds: call erstbl ; erase seg table (presently unused)
- mov segsho,205 ; reset cmd line arrow
- call ClearTables ; reset ctl, rem, smb tables
- mov ah,42h ; move pointer, returns size in DX:AX
- mov al,2 ; move to EOF + CX:DX
- xor cx,cx
- xor dx,dx
- mov bx,Handle
- int 21h
- mov PgmBytes,ax
- mov PgmBytes+2,dx
- ;convert Pgmbytes to paras
- mov cx,4
- llll: shr dx,1
- rcr ax,1
- loop llll
- or dx,dx ;over 1 meg ?
- jnz pppp
- cmp ax,0FFFEh ;just at 1 meg ?
- jna oooo
- pppp: mov ax,0FFFEh ;1 meg max, ALLOC MEM below is more limiting
- oooo: inc ax ; for round-off
- mov PgmParas,ax ; size of Target Pgm in paragraphs
- ;reset file pointer to start of file
- mov ah,42h ;move file pointer
- xor al,al ;move to CX:DX
- xor cx,cx
- xor dx,dx
- mov bx,Handle
- int 21h
- ;Store locn of end of RE-SOURCE
- mov bx,rembas ; length of RE-SOURC program
- mov cl,4
- shr bx,cl
- add bx,600h ; 24K in paras, for remark table
- mov ax,cs
- add ax,bx ; seg of end of RE-SOURC w/buffers,
- mov curpar,ax ; = current para of target pgm
- ;change size of allocated memory
- mov bx,cs ;no math on seg registers !
- sub ax,bx ;length of RE-SOURCE in paras
- add ax,PgmParas
- jnc nnnn
- mov ax,0FFFFh ;crude trap for over 1 Meg
- nnnn: mov bx,ax ;paras requested
- push cs
- pop es ;seg of block to change
- push ax
- mov ah,4Ah ;change allocated block
- int 21h
- pop ax ;paras requested
- jnc ReadFile
- ;insufficient RAM for target program
- sub ax,bx ;shortfall
- mov bx,ax
- call prtstr ;saves BX
- db cr,lf,'Not enough memory, you need ',0
- call Print00BX_
- call prtstr
- db ' paras more...',cr,lf,0
- clc ;no '.COM, etc NOT FOUND' message
- ret
- ;Read a file with 32-bit length
- ;(this might be simpler if you can read 0 bytes)
- ReadFile:
- mov ParasRead,0
- mov cx,PgmBytes ;bytes to load, lo word
- mov dx,word ptr PgmBytes+2 ;hi word
- ReadMore:
- or dx,dx ;over 64K left ?
- jnz Read64 ;yes, read 64K bytes
- push dx ;will pop as CX so CX:DX=0 => done
- jmp short ReadSome ;read CX bytes
-
- Read64: sub cx,0FFFFh
- sbb dx,0 ;DX:CX = DX:CX - 64K
- push cx
- mov cx,0FFFFh ;read 1st 64K
- ReadSome:
- push dx
- mov bx,Handle
- push ds
- mov ax,curpar ;end of RE-SOURCE and its buffers
- add ax,ParasRead
- mov ds,ax ; is seg of target buffer
- xor dx,dx ;start target buffer on para boundary
- mov ah,3Fh ;read w/handle, 64K bytes max
- int 21h
- pop ds
- pop dx
- pop cx
- jc ReadErr
- ;are we done reading ?
- add ParasRead,1000h
- or cx,cx
- jnz ReadMore
- or dx,dx
- jnz ReadMore
- call prtstr
- db 'Size of loaded file in paragraphs = ',0
- mov bx,PgmParas
- call Print00BX_
- call CrLf
- call fclose ;reads use fclose, writes use WriteNclose
- mov pcntr,0 ;'real' addr to unassemble
- mov DumpStart,0 ;Dump command's start addr
- ;set END & ORG
- cmp word ptr PgmBytes+2,0
- jnz CantEnd
- mov dx,PgmBytes ;lo word of file length***MAX 64K !!
- mov al,'E'
- call ALtoCTLatDX
- CantEnd:
- mov curorg,0
- cmp EXTflag,'C'
- jnz OrgZero
- ;It's a .COM file, set ORG
- mov curorg,100h
- OrgZero:
- mov ChgFlag,0 ;for 'Update/Exit'
- clc ;no '.COM, .EXE, etc NOT FOUND'
- ret
-
- ReadErr:
- push ax
- call prtstr
- db cr,lf,'Error reading file: Func 3Fh, AX returned ',0
- pop bx
- call Print00BX_
- call prtstr
- db 'hex',cr,lf,0
- ret
-
- ;--------------------------------
- LoadSMB:
- mov bx,symbas ;table start
- mov REMflag,0 ;do SMB, not REM file
- call LoadREMorSMB
- jc gggg
- mov symtp,bx
- mov byte ptr [bx+3],0 ;zero count = end flag
- clc
- gggg: ret ;w/C set if not found
-
- LoadREM:
- mov bx,remtbl
- mov REMflag,1
- call LoadREMorSMB
- jnc MarkRemEnd
- ret
-
- MarkRemEnd:
- mov remend,bx
- mov word ptr [bx],0FFFFh
- ret
-
- LoadREMorSMB:
- call fopen ;C set if file not found
- jnc RemSmbCharLoop
- call OpenError ;print 'File Not Found'
- ret
-
- RemSmbCharLoop:
- call GetByte ;get 1 byte from buffer, read if req'd
- cmp al,1Ah
- jnz l0b6c
- call fclose
- ret
-
- l0b6c: cmp al,' '
- jb RemSmbCharLoop ;eat CR, LF, ctrl chars
- call hexbin ;hex to binary, variable, space ends
- mov [bx],dx
- inc bx
- inc bx
- test byte ptr REMflag,1 ;DAMN MASM requires BYTE PTR
- jnz drdsk1
- ;for SMB file only:
- call GetByte
- mov [bx],al ;OprndType byte
- inc bx
- call GetByte ;eat delim space
- drdsk1: push bx ;save locn for count
- inc bx
- xor ch,ch
- lpasld: call GetByte
- cmp al,tab
- jz FoundDelim
- cmp al,cr
- jz FoundDelim
- mov [bx],al
- inc bx
- inc ch ;char count
- jmp lpasld
-
- FoundDelim:
- pop si
- xchg bx,si
- push si
- mov [bx],ch ;store byte count
- pop bx
- jmp RemSmbCharLoop
-
- hexbin: xor dx,dx
- l0ba3: cmp al,' '
- jnz l0ba8
- ret
-
- l0ba8: cmp al,1Ah
- jnz l0baf
- jmp UnexpEOF
-
- l0baf: call DigitToDX
- call GetByte
- cmp al,1Ah
- jnz l0ba3
- jmp UnexpEOF
-
- DigitToDX:
- cmp al,'9'+1 ;can it be decimal digit ?
- jb l0bb5
- sub al,7 ;alpha to hex
- l0bb5: sub al,'0' ;30h, to binary
- add dx,dx
- add dx,dx
- add dx,dx
- add dx,dx ;now DX times 16d
- add al,dl
- mov dl,al
- ret
-
- ;--------------------------------
- ;put d:\path\name entered in GTCMD into FileString
- CmPath: mov bx,offset cmdbuf+3 ;1st byte past the 'P'
- mov di,offset FileString
- call MoveField ;stops at CR or '.'
- mov byte ptr [di],'.'
- mov DotPtr,di
- jmp nxcmd
- ;--------------------------------
- CmRAMpara:
- mov bx,offset cmdbuf+3 ;1st char after the R
- mov al,[bx]
- cmp al,cr
- jnz NewPara
- call ShowAddr ;just show curr value
- jmp nxcmd
- NewPara:
- mov EXTflag,0 ;in case a .SMB file is to be loaded
- call gtval ;hex no. entered - curorg to DX
- add dx,curorg
- cmp al,cr ;end of entry ?
- jz RAMparaOK
- call cmerr
- RAMparaOK:
- mov curpar,dx
- mov DotPtr,0 ;to flag .RSM header routine
- mov curorg,0 ;ORG = 0 for RAM unassemblies
- call ShowAddr
- jmp cmpurg ;Dump .REM, .CTL, .SMB tables ?
-
- ShowAddr:
- call prtstr
- db 'ORG = 0 at ',0
- mov bx,curpar
- call Print00BX_
- call prtstr
- db ': 0000',0
- call CrLf
- ret
-
- ;--------------------------------
-
- ;erase the seg tables - called by Load .COM file, cmpurg
- erstbl: mov bx,offset cstbl
- mov nrsegs,0
- mov ch,8
- etlp1: mov cl,5
- mov ax,' '
- etlp2: mov [bx],ax
- xor ax,ax
- inc bx
- inc bx
- dec cl
- jnz etlp2
- inc bx
- inc bx
- dec ch
- jnz etlp1
- ret
-
- ;--------------------------------
- SaveAll:
- mov ChgFlag,0 ;for 'Update/Exit' in CmExit
- mov dx,remend
- mov bx,remtbl
- cmp bx,dx
- jz nosrem
- mov bx,offset LitREM
- call EXTtoSpec
- call prtstr
- db cr,lf,'Saving .REM file..',0
- call SaveREM
- nosrem: mov dx,symtp
- mov bx,symbas
- cmp bx,dx
- jz nossym
- mov bx,offset LitSMB
- call EXTtoSpec
- call prtstr
- db cr,lf,'Saving .SMB file..',0
- call SaveSMB
- nossym: mov dx,ctltop
- mov bx,offset ctlbas
- cmp bx,dx
- jnz havctl
- jmp nxcmd
- havctl: mov bx,offset LitCTL
- call EXTtoSpec
- call prtstr
- db cr,lf,'Saving .CTL file..',0
- call prtstr
- db cr,lf,0
- jmp SaveCTL
-
- ;--------------------------------
- ;save labels (routine at l0bf4 also used to save remark table)
- SaveSMB:
- mov bx,symbas
- mov REMflag,0 ;saving .SMB, not .REM
-
- l0bf4: call creatf
- l0bf7: mov dx,[bx] ;address in rem or smb table
- inc bx ;to 2nd addr byte
- test byte ptr REMflag,1
- jnz sdskp1 ;if .REM, no type byte
- inc bx
- mov ah,[bx] ;OprndType byte
- sdskp1: inc bx
- mov al,[bx] ;string length
- inc bx ;to 1st byte of string
- mov ch,al
- or al,al
- jz oufend ;end of table found
- push ax ;save OprndType byte
- call outadr ;convert to hex & write 4 char number
- mov al,' '
- call WriteChar
- pop ax
- test byte ptr REMflag,1
- jnz StringLoop ;if doing REM, not SMB
- mov al,ah ;get OprndType byte
- call WriteChar
- mov al,' '
- call WriteChar
- StringLoop:
- mov al,[bx]
- call WriteChar
- inc bx
- dec ch
- jnz StringLoop
- mov al,cr
- call WriteChar
- mov al,lf
- call WriteChar
- jmp l0bf7
-
- oufend: call WriteNclose ;flush buffer to disk
- ret
-
- outadr: mov al,dh
- call hexl
- call WriteChar
- mov al,dh
- call hexr
- call WriteChar
- mov al,dl
- call hexl
- call WriteChar
- mov al,dl
- call hexr
- jmp WriteChar
-
- ;--------------------------------
- ChkNoFSpec:
- cmp DotPtr,0 ;any filespec been entered ?
- jz PutRAMaddr
- ret
- ;R command has been used, or no file has been loaded
- PutRAMaddr:
- mov di,offset FileString
- mov bx,offset SEG_string
- call MoveField
- mov bx,di
- mov ax,curpar
- xchg al,ah
- call StoreHex ;AL to 2 hex bytes [BX] & inc BX
- xchg al,ah
- call StoreHex
- mov byte ptr [bx],'.'
- mov DotPtr,bx
- ret
-
- ;Enable saving .RSM file as you Unasm
- CmWriteRSM:
- mov ASMopenFlag,1
- mov wfiflg,0 ;don't write message to file
- call ChkNoFSpec ;save as 'SEG_nnnn.RSM' if doing RAM
- mov bx,offset LitRSM
- call EXTtoSpec
- call creatf
- call prtstr
- db ' Writing .RSM is enabled... '
- db 'use Z command to close file before END',cr,lf,cr,lf,0
- ;create .RSM header (title, org addr, equ's for labels outside the pgm)
- mov wfiflg,1 ;write to both screen & file
- call pstg
- db ';Re-Source Disassembly of ',0
- mov bx,offset FileString
- FileNameLoop:
- mov al,[bx]
- cmp al,'.' ;don't print '.RSM'
- jz PrintHeader
- or al,al ;end of string ?
- jz PrintHeader
- call typech
- inc bx
- jmp short FileNameLoop
-
- PrintHeader:
- test Direc286Flag,1
- jz NoDirec
- call pstg
- db cr,lf,'.286P',0 ;file has '186+ instr's
- ;note: .386P calls MOV wr,OFFSET H001234 "illegal size for operand"
- NoDirec:
- call pstg
- db cr,lf,cr,lf,'cr',tab,'EQU',tab,'0Dh'
- db cr,lf,'lf',tab,'EQU',tab,'0Ah'
- db cr,lf,'tab',tab,'EQU',tab,'9'
- db cr,lf,'bel',tab,'EQU',tab,'7'
- db cr,lf,cr,lf,'CSEG',tab,'segment',tab,'byte public',0
- cmp EXTflag,'E'
- jz SegsDone
- call pstg
- db cr,lf,tab,'assume',tab,'CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG',0
- SegsDone:
- mov OutsideFlag,0 ;don't print header if none outside
- xor cx,cx ;start at beginning of pgm
- mov bx,symbas
- FarLabelLoop:
- inc bx
- inc bx
- inc bx ;>length byte
- mov al,[bx]
- or al,al ;0 marks end of table
- jnz l032c ;not table end, check for more labels
- cmp EXTflag,'E'
- jz OrgDone
- call pstg
- db cr,lf,cr,lf,tab,'ORG',tab,0
- mov dx,curorg
- call PrintDXh
- OrgDone:
- call CrLf
- call CrLf
- jmp nxcmd
-
- l032c: dec bx
- dec bx
- dec bx ;>addr @ 1st of entry
- push bx
- push cx ;pointer to code
- inc bx
- inc bx
- inc bx
- ;only print labels outside the pgm
- push bx ;>length byte
- dec bx
- dec bx
- dec bx
- mov dx,[bx] ;label's addr
- cmp dx,PgmBytes ;1st after pgm, locn of END**64K max**
- jb nodisp
- pop bx
- ;print the label
- cmp OutsideFlag,0
- jnz NoOutsideHdr
- call pstg
- db cr,lf,cr,lf,';Labels outside the program:',cr,lf,0
- mov OutsideFlag,1 ;flag it's been printed
- NoOutsideHdr:
- mov ch,[bx] ;length of label
- l0362: inc bx
- mov al,[bx]
- call typech
- dec ch
- jnz l0362
- call pstg
- db tab,'EQU',tab,'$+',0
- pop cx ;pointer to code
- pop bx ;>addr @ 1st of entry
- push bx
- mov dx,[bx]
- inc bx
- inc bx ;to type byte
- add dx,curorg ;correct all addrs for ORG
- mov al,dh
- call xo0
- mov al,dl
- call xo
- call pstg
- db 'h',cr,lf,0
- pop bx ;>addr @ 1st of entry
- l0394: inc bx
- inc bx
- inc bx ;to 4th (length) byte
- mov al,[bx]
- xor ah,ah
- add bx,ax
- inc bx ;to 1st of next label entry
- call BreakChk ;test for Ctrl-Break
- jmp FarLabelLoop ;loop to next entry in symbol table
-
- nodisp: pop bx
- pop cx
- pop bx
- jmp l0394
- ;--------------------------------
-
- SaveREM:
- mov REMflag,1
- mov bx,remend
- inc bx
- inc bx ;2 bytes past end
- mov byte ptr [bx],0 ;mark length byte so end will be found
- mov bx,remtbl
- jmp l0bf4
-
- ;--------------------------------
- ASMstillOpenErr:
- call prtstr
- db 'NO FILE ACCESSES UNTIL .RSM CLOSED',cr,lf,0
- jmp nxcmd
-
- ;an EOF has been found in the middle of a number, jumped to 2 places
- UnexpEOF:
- call prtstr
- db 'Unexpected EOF',cr,lf,0
- jmp nxcmd
- ;--------------------------------
- ;SET CONTROL or dump CTL table
-
- ;control table structure:
- ; cfence is ctltbl-1, holds mode char for 1st line
- ; each entry 4 bytes: 1 byte segment char,
- ; 2 byte address, 1 byte mode char (BEHISW).
- ; Table terminated by 0FFFFh in address bytes
-
- cmctl: ;call sgreqs
- mov bx,offset cmdbuf+3 ;1st byte after the C in the command
- mov al,[bx]
- cmp al,cr ;C alone ?
- jnz ChkNnList ;command has more than C
- jmp ShowCTLtable
-
- ChkNnList:
- call gtval
- cmp al,cr ;C and just a no.
- jnz setctl ;more follows the number
- jmp ListCtl ;list .CTL from NNNN
-
- setctl: call delim
- l0d5a: inc bx
- mov al,[bx] ;BEHISW to use
- call ALtoCTLatDX ;make a manual entry in .CTL table
- jmp nxcmd
-
- ;called by A command only. Enter w/new char in AL, DX=locn
- EnterCTL:
- push bx
- push dx ;pcntr
- push ax ;save CTL char in AL
- call ctlook ;search ctl table
- jc OldEntry ;if table end or past right addr
- add bx,4 ;point to curr entry
- OldEntry:
- pop ax ;the CTL char
- pop dx ; and pcntr location
- dec bx ;to mode char at this or last locn
- cmp al,[bx] ;compare to current mode char
- pop bx
- jnz ALtoCTLatDX ;if different from CTL at this or last
- ret
-
- ;make manual entry in .CTL table - AL=ctl char, DX=addr
- ALtoCTLatDX:
- mov typndx,al ;save CTL char (BEHIS or W)
- call ctlook ;if found, BX points to entry in ctltbl
- jnc ChgExist ;if matches an existing entry
- jmp NewCtl ;make a new entry
-
- ChgExist:
- mov al,typndx ;recover the char
- call cltrck ;test all legal values
- mov ChgFlag,1 ;for 'Update/Exit'
- cmp al,'K'
- jz KillIt
- jmp ChgCtl ;modify existing entry
-
- KillIt: mov ax,[bx+1] ;addr field of entry
- cmp ax,0FFFFh
- jz l0bf5 ;if at table end
- mov cx,4 ;entry length
- KillLoop:
- mov al,[bx+4] ;move from higher rec
- mov [bx],al ;down to lower rec
- inc bx
- loop KillLoop
- jmp KillIt ;repeat for rest of recs
-
- ;entries past kill are all moved down
- l0bf5: sub bx,4 ;base of last valid entry
- jmp nxcmd
-
- cltrck: cmp al,'K'
- jz cltrrt
- ChkValidCtl:
- cmp al,'E'
- jz cltrrt
- cmp al,'B'
- jz cltrrt
- cmp al,'H'
- jz cltrrt
- cmp al,'W'
- jz cltrrt
- cmp al,'I'
- jz cltrrt
- cmp al,'S'
- jz cltrrt
- call cmerr
- cltrrt: ret
-
- ;make a new entry in the .CTL table - AL=type, DX=addr.
- ; ctlook returned C set, BX > entry for next higher addr.
- NewCtl: mov al,typndx ;the BEHIS or W
- call ChkValidCtl ;to cmerr if not valid
- mov ChgFlag,1 ;for 'Update/Exit'
- push dx ;addr of the entered control
- push bx ;location for new entry
- mov bx,offset ctlbas
- FindEndLoop:
- mov ax,[bx+1] ;addr of this entry
- add bx,4 ;to start next entry
- cmp ax,0FFFFh ;end of table ?
- jnz FindEndLoop
- ;now BX points to the end-marker 0FFFFh entry
- mov dx,bx
- add dx,4 ;make space for new FFFF entry
- pop cx ;was BX, > next higher entry
- entrc8: dec bx ;to seg (1st) char first
- dec dx ;dest
- mov al,[bx] ;old entry byte
- xchg bx,dx
- mov [bx],al ;to new place higher
- xchg bx,dx
- cmp dx,cx ;at insert location yet?
- jnz entrc8 ;no, loop
- ;make the entry
- mov bx,cx ;restore table pointer
- pop dx ;pcntr value to store
- mov ch,segsho ;segment char (now always 205d)
- mov [bx],ch
- mov [bx+1],dx ;store address
- mov al,typndx
- mov [bx+3],al ;store CTL code
- add bx,4
- ret
-
- ;modify existing entry
- ChgCtl: mov ah,segsho ;segment char (now always 205d)
- mov [bx],ah
- mov [bx+3],al ;modify existing entry (the BEHIS or W)
- ret
-
- ;--------------------------------
- ;Check the .CTL table for entry @DX. 4 bytes/entry. Rets w/BX pointing
- ;to ctlbas+0, +4 etc of entry for addr just past DX. Uses AX, BX, CX; saves DX
-
- ctlook: mov bx,offset ctlbas ;point BX at table's start
- mov ch,segsho ;(presently always 205d)
- LookLoop:
- mov ax,[bx+1] ;addr value
- cmp ax,0FFFFh ;end of table ?
- stc
- jnz l0e4s ;wasn't the end
- ret ;w/carry set if no match below end
-
- l0e4s: cmp ch,[bx] ;(presently always 205d)
- jz l0e48 ; in right segment
- l0e5c: jnb ctlk4 ;still too low in table
- ret ;too far, stop w/carry set
-
- l0e48: cmp dx,[bx+1]
- jnz l0e5c
- ret ;found exact match
-
- ctlk4: add bx,4 ;to next entry
- jmp short LookLoop
- ;--------------------------------
-
- ListCtl:
- mov EntriesLeft,4
- call ctlook ;find starting entry
- jmp clist
- ;--------------------------------
- ;display the .CTL table in 4 columns
- ShowCTLtable:
- mov EntriesLeft,4
- mov bx,offset ctlbas ;start with first CTL entry
- clist: call BreakChk ;test for user break
- mov dx,1[bx] ;addr of entry
- add bx,3 ;last of this entry, the BESHI or W
- cmp dx,0FFFFh
- jnz clist2 ;not at table end
- call CrLf
- jmp nxcmd
-
- clist2: mov al,-3[bx] ;1st of this entry, the seg char
- cmp al,segsho ;is special seg char showing?
- jnz skclis ;if so, skip this entry
- push bx
- mov bx,dx
- add bx,curorg ;correct for ORG
- call Print00BX_ ;print location
- call prtstr
- db '= ',0
- pop bx
- mov al,[bx]
- call typech ;ctl char from table (BEHIS or W)
- call prspc
- push dx
- push bx
- call symluk ;symbol at this address?
- jc NoLblCtl
- ;locn has label, CH is length, BX points to start ot text
- mov EntriesLeft,1 ;signal no more entries on this line
- call prtstr
- db '= ',0
- call PrtCHbytesPerBX
- NoLblCtl:
- pop bx
- pop dx
- call prspc
- call prspc
- call ChkEntryCt
- skclis: inc bx
- jmp clist
-
- ;--------------------------------
- SaveCTL:
- call creatf ;make a new file
- mov bx,offset ctlbas ;start of CTL table
- NxtEntry:
- mov dx,1[bx] ;address value
- cmp dx,0FFFFh
- jz HitEnd ;0FFFFh is flag for end of table
- mov al,[bx] ;seg char
- call WriteChar
- call outadr ;convert to hex & write 4 chars
- mov al,','
- call WriteChar
- mov al,3[bx]
- call WriteChar
- mov al,cr
- call WriteChar
- mov al,lf
- call WriteChar
- add bx,4
- jmp NxtEntry
-
- HitEnd: jmp WriteNclose
-
- ;--------------------------------
- ;.CTL file format: 1 line/entry, seg byte, variable length hex address
- ; (always 4 chars now), a comma, and the Ctl byte (BEHISW). E.g., ═0123,B
-
- LoadCTL:
- call fopen ;C set if file not found
- jnc FoundCTL
- call OpenError
- ret
-
- FoundCTL:
- mov bx,offset ctlbas
- CtlLineLoop:
- call GetByte ;get byte from buffer, read another 128 if empty
- cmp al,1Ah
- jz IsEOF
- cmp al,' '+1
- jb CtlLineLoop ;eat space, CR, LF, ctrl chars
- mov [bx],al ;segment char (now always 205d)
- call GetByte ;1st byte of hex address
- xor dx,dx ;clear addr accumulator
- CtlDigitLoop:
- cmp al,1Ah
- jz IsEOF
- cmp al,',' ;comma marks end of addr field
- jz ItsComma
- call DigitToDX
- call GetByte
- jmp CtlDigitLoop
-
- ItsComma:
- mov 1[bx],dx
- call GetByte
- mov 3[bx],al
- add bx,4
- jmp CtlLineLoop
-
- IsEOF: mov word ptr 1[bx],0FFFFh
- add bx,4
- call fclose
- ret
- ;--------------------------------
- ; ADD REMARKS
-
- ; remark table structure, variable length records:
- ; 2 byte address, 1 byte string count, n byte string
- ; table terminated by 0ffffh in address field
- ; if 1st char = ; remark appended to instruction
- ; else remark on separate line before instruction
-
- cmrem: ;call sgreqs
- mov bx,offset cmdbuf+3 ;1st char after the ';'
- mov al,[bx]
- cmp al,cr
- jnz cmnt1
- jmp DumpRem ;dump the remark table
-
- cmnt1: call gtval ;addr of remark to DX, corrected for ORG
- inc bx
- cmp al,cr
- jnz l0f52
- jmp adr_dmp ;user entered ;NNNN (dump remarks from NNNN)
-
- l0f52: call delim
- push bx
- ;at this point, a Rem will be added or deleted
- mov ChgFlag,1 ;for 'Update/Exit'
- call RemChk ;point BX at entry for addr user has input
- jc AddRem ;jump if at end of table, no remark here
- call delrem ;delete any existing remark
- pop bx ;pointer to cmdbuf
- push bx
- mov al,[bx]
- cmp al,cr ;input was ;NNNN, (delete remark at NNNN)
- jnz AddRem
- jmp nxcmd
- ;make new entry at end of table
- AddRem: mov bx,remend
- mov [bx],dx ;addr for the new last entry
- inc bx
- inc bx ;to String Count byte
- pop si ;points in cmdbuf
- xor ch,ch ;clear string count
- mov di,bx ;bx still holds pointer to String Count
- inc di ;point to first char for remark string
- push cs
- pop es ;just to be sure
- RemCharCopy:
- lodsb ;get char from cmdbuf & inc SI
- cmp al,cr ;is it CR ?
- jz EndRemStr
- stosb ;put it in rem table & inc DI
- inc ch
- jmp short RemCharCopy
- EndRemStr:
- mov remend,di
- mov word ptr [di],0FFFFh
- mov [bx],ch ;string count
- jmp nxcmd
-
- ;--------------------------------
- ;point BX to entry at addr in DX. C set if not found.
- RemChk: mov bx,remtbl ;points to rembas
- NxtRem: cmp word ptr [bx],0FFFFh ;check for end-of-table
- jnz RemsGoOn
- stc
- ret ;w/carry if at end of table
-
- RemsGoOn:
- cmp dx,[bx]
- jnz l0fc3
- ret ;w/BX > matching addr and no carry
-
- l0fc3: inc bx
- inc bx
- mov al,[bx] ;length of remark
- call AddALtoBX
- inc bx
- jmp NxtRem
- ;--------------------------------
- adr_dmp:
- call RemChk ;point BX at entry user has input
- jmp l0fd8
-
- ;dump the remarks table to the screen
- DumpRem:
- mov bx,remtbl ;point BX at start of table
- l0fd8: call BreakChk ;check for CTRL-BREAK
- mov dl,[bx]
- inc bx
- mov dh,[bx]
- inc bx
- mov al,dh
- and al,dl
- inc al
- jnz l0fec
- jmp nxcmd
-
- l0fec: xchg bx,dx
- push bx
- add bx,curorg ;correct printed address for ORG
- call Print00BX_
- pop bx
- xchg bx,dx
- mov al,';'
- call typech
- mov ch,[bx] ;length of remark
- l0ffa: inc bx
- mov al,[bx]
- call typech
- dec ch
- jnz l0ffa
- call CrLf
- inc bx
- jmp l0fd8
- ;--------------------------------
- ;enter w/BX > entry for addr in DX that user has input. Saves DX.
- delrem: cmp word ptr [bx],0FFFFh
- jnz l1015
- ret ;if at end of table
-
- l1015: push dx
- mov dx,bx ;now DX > start of entry to overwrite
- inc bx
- inc bx
- mov al,[bx]
- call AddALtoBX
- inc bx ;to start of next entry's string
- xor ch,ch
- l1023: mov al,[bx]
- xchg bx,dx
- mov [bx],al
- xchg bx,dx
- inc bx
- inc dx
- mov cl,al ;char just moved
- and al,ch ;AND previous char moved
- inc al ;if both were 0FFh, gives Z
- mov ch,cl ;save char just moved
- jnz l1023 ;loop if not at end of table
- xchg bx,dx
- dec bx
- dec bx
- mov remend,bx
- pop dx
- ret
-
- ;==============================================================================
- ;Start of actual disassembly routines.
-
- LitStart db 'Start'
-
- ;Print any label to screen and file, space & addr at start of line to scrn only
- AddrOrSmb:
- push ax
- push dx
- push bx
- mov wfiflg,1 ;print to output file, too
- mov dx,pcntr
- ;insert 'Start' in B mode if .COM file at 100h, for MASM
- cmp BmodeFlag,0
- jz NoStart
- or dx,dx
- jnz NoStart
- cmp EXTflag,'C'
- jnz NoStart
- mov bx,offset LitStart
- mov ch,5 ;length of 'Start'. DX is already 0000.
- call symtch ;inserts sym if not already present
- NoStart:
- mov dx,pcntr
- call symluk ;BX>label, CH=label length, carry if no label
- jc NoLblHere
- ;print the label
- push cx ;save label's length
- call PrtCHbytesPerBX
- pop cx
- ;check for non-Instruction
- cmp ColonFlag,0
- jz ItsAnInstr
- ;no addr as comment for DB, DW, DS lines, MASM req label on SAME LINE !
- cmp ch,7
- jna TabExit
- mov wfiflg,1 ;now print to file, too
- call prspc
- jmp JusExit
-
- ItsAnInstr:
- mov al,':'
- call typech ;saves CX
- inc ch ;length of label determines no. of Tabs
- cmp trmflg,0
- jz AddrAsComment
- ;trim is on, check for label over 7 chars long
- cmp ch,7
- jna TabExit
- call CrLf
- jmp TabExit
-
- AddrAsComment:
- call PrtTab
- call PrtTab
- cmp ch,8
- jae NoMoreTab
- call PrtTab ;extra tab to keep label addr's aligned
- NoMoreTab:
- call semic ;print a semicolon
- mov bx,pcntr
- add bx,curorg ;correct for ORG
- call Print00BX_ ;print address
- call CrLf
- jmp TabExit
-
- ;line has no label, just print address
- NoLblHere:
- mov wfiflg,0 ;don't print to .RSM file, just screen
- call prspc ;print the space at start of line
- mov bx,pcntr
- add bx,curorg ;correct for ORG
- call Print00BX_ ;print address
- TabExit:
- mov wfiflg,1 ;now print to file, too
- call PrtTab
- JusExit:
- pop bx
- pop dx
- pop ax
- ret
-
- ;--------------------------------
- ;UNASSEMBLE A LINE OF CODE at [curpar:pcntr] - always called w/wfiflg=0
-
- dline: mov es,curpar
- mov OprndType,10h ;DS unless changed, do correct for ORG
- mov bx,pcntr
- mov curadr,bx
- inc pcntr
- ;Find Op Code in opct table
- mov ch,es:[bx] ;first byte of code for this line
- mov CurInstr,ch ;also signals blank line if req'd
- mov bx,offset opct-7
- mov dx,7 ;size of table entry -1
-
- OpLineLoop:
- add bx,dx
- mov al,cs:[bx] ;starts at beginning of opct table
- or al,al
- jnz KeepLooking
- jmp PrtDBandByte ;end of table
-
- KeepLooking:
- and al,ch
- mov cl,al ;masked opcode
- inc bx
- mov al,cs:[bx]
- cmp al,cl ;nxt byte in opct match masked opcode?
- jnz OpLineLoop
- inc bx ;to 3rd byte of line in opct,
- mov al,cs:[bx] ; the instr's Kind no.
- mov typndx,al ;typndx also holds the BEHISW later
-
- ;PRINT THE OP CODE (the instruction)
- mov ch,5 ;every entry is 5 bytes incl the ...
- OpLoop: inc bx
- mov al,cs:[bx]
- cmp al,'.' ;dot is ignored
- jz nodot
- call typech ;print opcode char
- nodot: dec ch
- jnz OpLoop
-
- mov dl, typndx
- and dl,3Fh
- xor dh,dh
- mov bx,offset jmptbl
- add bx,dx
- add bx,dx
- mov dx,cs:[bx]
- mov bx,curadr
- mov al,es:[bx]
- ;pick out the '186+ op codes. 0F, C0 and C1 done in kindXX routines.
- ;The codes are 60-63, 68-6F, C8 and C9
- cmp al,0C8h
- jz Is186
- cmp al,0C9h
- jz Is186
- cmp al,60h
- jb GoJmp
- cmp al,6Fh
- ja GoJmp
- cmp al,68h
- ja Is186
- cmp al,64h
- ja GoJmp
- Is186: mov Direc286Flag,1 ;this is a '186+ instr
- GoJmp: jmp dx ;with AL, CurInstr, BX and curadr set
-
- ;Jump table is indexed by typndx.
- ;See list of which codes are which KIND at opct table.
-
- jmptbl dw offset kind00
- dw offset kind01
- dw offset kind02
- dw offset kind03
- dw offset kind04
- dw offset kind05
- dw offset kind06
- dw offset kind07
- dw offset kind08
- dw offset kind09
- dw offset kind10 ;'186 PUSH nnnn
- dw offset kind11
- dw offset kind12
- dw offset kind13
- dw 0 ;kind14 unused
- dw offset kind15
- dw offset kind16
- dw offset kind17
- dw offset kind18
- dw offset kind19
- dw offset kind20
- dw offset kind21
- dw offset kind22 ;'286 protected mode instrs
- dw offset kind23
- dw offset kind24
- dw offset kind25
- dw offset kind26
- dw offset kind27
- dw offset kind28
- dw offset kind29
- dw offset kind30
- dw offset kind31
- dw offset kind32
- dw offset kind33
- dw offset kind34
- dw offset kind35
- dw offset kind36
- dw offset kind37
- dw offset kind38
- ; - - - - - - - - - - - - - - - -
- ;Routines to print the operands. On entry:
- ;BX = curadr, points to the 1st op code byte. CurInstr holds op code.
-
- kind00: jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind01: call PrtTab ;IN AL or AX,DX and OUT DX,AL or AX
- mov al,es:[bx]
- test al,2
- jnz k01out
- test al,1
- jnz k01iw
- call pstg
- db 'AL,DX',0
- jmp NewLine
-
- k01iw: call pstg
- db 'AX,DX',0
- jmp NewLine
-
- k01out: test al,1
- jnz k01ow
- call pstg
- db 'DX,AL',0
- jmp NewLine
-
- k01ow: call pstg
- db 'DX,AX',0
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind02: ;IN AX,nn and OUT nn,AX
- mov al,es:[bx+1]
- mov CurModRegRM,al ;use for immed data
- inc pcntr
- inc curadr
- call PrtTab
- test byte ptr CurInstr,2 ; AND it w/2 to check bit 1
- jnz OutnnAX
- call pstg
- db 'AX,',0
- mov al,CurModRegRM
- call PrintALh
- jmp NewLine
-
- OutnnAX:
- mov al,CurModRegRM
- call PrintALh ;print port no.
- call pstg
- db ',AX',0
- jmp NewLine
-
- ; - - - - - - - - - - - - - - - -
- kind37: ;IN AL,nn and OUT nn,AL
- ;same as kind02 above, except AL
- mov al,es:[bx+1]
- mov CurModRegRM,al ;use for immed data
- inc pcntr
- inc curadr
- call PrtTab
- test byte ptr CurInstr,2 ; AND it w/2 to check bit 1
- jnz OutnnAL
- call pstg
- db 'AL,',0
- mov al,CurModRegRM
- call PrintALh
- jmp NewLine
-
- OutnnAL:
- mov al,CurModRegRM
- call PrintALh ;print port no.
- call pstg
- db ',AL',0
- jmp NewLine
-
- ; - - - - - - - - - - - - - - - -
- kind03: call PrtTab ;MOV immed data to reg
- mov al,es:[bx] ;get the op code
- inc pcntr
- inc curadr
- test al,8
- jnz k03Word
- and al,7
- call namrg8
- call comma
- call bytopd
- jmp NewLine
-
- k03Word:
- inc pcntr
- and al,7
- call namr16
- call comma
- jmp ImmedWord
-
- ; - - - - - - - - - - - - - - - -
- kind04: ;byte arith, logic, CMP, TEST to AL
- inc pcntr
- call PrtTab
- call pstg
- db 'AL,',0
- mov al,CurInstr
- inc curadr
- jmp OldArith
- ; - - - - - - - - - - - - - - - -
-
- ;ONE-BYTE operand shown as ASCII if so
- bytopd: mov bx,curadr ;has been inc'd
- mov al,es:[bx] ;get data byte
- push ax
- call PrtALasDB ;C set => don't show comment hex
- pop ax
- jnc ShAsCm
- ret
-
- ShAsCm: push ax
- call PrtTab
- call PrtTab
- call semic ;print semicolon
- pop ax
- jmp PrintALh ;print actual code byte
-
- PrtALasDB:
- cmp al,cr
- jnz cccc
- call pstg
- db 'cr',0
- clc ;show as comment hex
- ret
-
- cccc: cmp al,lf
- jnz dddd
- call pstg
- db 'lf',0
- clc
- ret
-
- dddd: cmp al,' '
- jb JustPrtNumber
- cmp al,'z'+1
- jnb JustPrtNumber
- ;print AL in quotes
- call apostrophe
- cmp al,''''
- jnz Normal
- call apostrophe ;print an extra '
- Normal: call typech
- call apostrophe ;print ending quote
- clc ;show as comment hex
- ret
-
- JustPrtNumber:
- call PrintALh
- stc ;don't show as comment hex
- ret
-
- ; - - - - - - - - - - - - - - - -
- kind05: call PrtTab ;CALL/long JMP to relative address - word displ
- inc pcntr
- inc pcntr
- inc bx
- mov dx,es:[bx] ;displacement from 1st byte past instr
- inc bx
- inc bx ;to 1st byte past instr
- add bx,dx
- mov dx,bx ;now DX = pcntr + displ
- mov RelFlag,1
- or OprndType,2 ; word
- call PrtNoOrSmb ;print DX + org, and ;ADDR if label, add SMB if in B
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind06: call PrtTab ;16-bit immediate data arith to AX
- inc pcntr
- inc pcntr
- inc curadr
- call pstg
- db 'AX,',0
- ImmedWord: ;used by kind10, PUSH immed & kind03, MOV immed
- mov bx,curadr ;has been inc'd
- mov dx,es:[bx]
- ImSE: call symluk ;saves DX
- jnc hvsym3 ;jmp if label
- call PrintDXh ;print word in DX, followed by 'h'
- jmp NewLine
-
- hvsym3: call pstg
- db 'OFFSET ',0
- call HaveSmb
- jmp NewLine
-
- ; - - - - - - - - - - - - - - - -
- ;print operand words following 'WORD PTR' (AddrOrSmb does line addrs)
- ; and Rel JMPs and CALLs. Adds symbols if in B mode.
- PrtNoOrSmb:
- mov al,OprndType
- and al,00110000b ;look at seg override for this line
- cmp al,10h ;is it DS:, the default set at Dline ?
- jnz NoDS
- cmp RelFlag,0
- jnz NoDS ;no 'DS:' for JZ, LOOP, etc.
- call pstg
- db 'DS:',0 ;req'd by dumb MASM for [addr] !
- NoDS: push dx ;holds the addr or data to print
- call symluk ;check for symbol
- pop dx
- jnc HaveSmb ;print it
- mkopds: cmp BmodeFlag,0 ;building symbols?
- jz PrtAdr ;just print addr if not
- push dx
- call addsym ;this is the only call to addsym
- pop dx
- jmp PrtAdr ;it's too late to print new label (is it ??)
-
- HaveSmb:
- call PrtCHbytesPerBX
- cmp NoCommentAddr,1
- jz JustLabel
- test byte ptr trmflg,0FFh
- jnz JustLabel
- call PrtTab
- call semic
- mov bx,dx ;the address
- cmp RelFlag,0
- jz NoCorr
- add bx,curorg ;correct for ORG
- NoCorr: jmp Print00BX_
-
- JustLabel:
- mov NoCommentAddr,0
- ret
-
- ;print operand addr pushed on stack (line addrs done by Print00BX_)
- ;called only by mkopds
- PrtAdr: cmp RelFlag,0
- jz PrintDXh ;Jump for hard-coded addrs
- add dx,curorg ;correct relative addrs for ORG,
- PrintDXh: ;leading zeros only where MASM requires,
- ; EXCEPT, e.g., 400h shows as 0400h
- mov al,'0'
- or dx,dx
- jz l147d
- mov al,dh
- or al,al
- jz PrintDLh
- call xo0
- mov al,dl
- call xo
- phxsfx: mov al,'h'
- l147d: jmp typech
-
- PrintDLh:
- mov al,dl
- PrintALh:
- cmp al,0Ah
- jb padigt
- call xo0
- jmp phxsfx
-
- padigt: add al,'0' ;30h
- jmp typech
- ; - - - - - - - - - - - - - - - -
- kind07: call PrtTab ;INT is the only kind07 opcode
- inc pcntr
- mov al,es:[bx+1]
- call PrintALh
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind08: inc pcntr ;AAM, AAD. Doesn't check 2nd byte (0Ah)
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind09: call PrtTab ;lock/rep/repnz prefixes
- jmp dline ;to continue instr
- ; - - - - - - - - - - - - - - - -
- kind10: call PrtTab ;'186 PUSH nnnn
- mov al,CurInstr
- inc pcntr
- inc curadr
- cmp al,6Ah ;is the Sign-Extend bit set ?
- jz SExt
- inc pcntr
- jmp ImmedWord ;print no. or 'OFFSET label'
-
- SExt: xor dh,dh
- mov bx,curadr
- mov dl,es:[bx]
- or dl,dl
- jns ExDone
- dec dh ;to 0FFh
- ExDone: jmp ImSE ;last part of ImmedWord routine
-
- ; - - - - - - - - - - - - - - - -
- kind11: call pcndop ;conditional jumps. 'J' has been printed.
- kind21: call PrtTab ;JCXZ, JMP SHORT
- mov al,CurInstr ;get op code byte again
- cmp al,0EBh ;was it JMP SHORT, not JCXZ ?
- jnz NoShort
- call pstg
- db 'SHORT ',0
- NoShort:
- inc pcntr
- mov bx,curadr
- inc bx
- mov al,es:[bx] ;get displacement byte
- test al,80h ;get sign
- jnz k21neg
- inc bx
- call AddALtoBX
- jmp k21add
-
- k21neg: inc bx
- not al
- inc al
- xor ah,ah
- sub bx,ax
- k21add: mov dx,bx
- mov RelFlag,1 ;flag rel-displ for
- call PrtNoOrSmb ; print DX + curorg, add SMB if in B mode
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind12: ;movs, cmps, lods, stos, scas
- mov al,CurInstr
- and al,1
- jnz k12wrd
- call pstg
- db 'B',0
- jmp NewLine
-
- k12wrd: call pstg
- db 'W',0
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind13: call pstg ;xchg ax,
- db tab,'AX,',0
- mov al,CurInstr
- and al,7
- call namr16
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind15: call PrtTab ;PUSH, POP, INC, DEC one 16 bit register
- mov al,CurInstr
- and al,7
- call namr16
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- PrtRegOfRM:
- mov bx,curadr
- inc bx
- mov al,es:[bx] ;get ModRegR/M byte
- and al,00000111b ;look at R/M field only
- jmp l156d
-
- PrtReg: mov bx,curadr
- inc bx
- mov al,es:[bx]
- and al,38h ;look at reg field only
- shr al,1
- shr al,1
- shr al,1
- l156d: push ax
- ;'286 LAR, etc are WORD reg's, must filter out
- cmp LongFlag,0
- jnz WordReg
- mov bx,curadr
- mov al,es:[bx] ;get current op code
- test al,1
- jnz WordReg
- pop ax
- jmp namrg8
- WordReg:
- pop ax
- jmp namr16
-
- ;used for TEST, MOV, XCHG, kind18 arith, and '286 ARPL, LSL, LAR
- ModRegRM:
- mov bx,curadr
- inc bx
- mov al,es:[bx] ;get modregr/m byte
- and al,11000000b ;the MOD field
- or al,al
- jz ChkQuirk ;no displacement unless [BP]
- cmp al,11000000b
- jz RMisReg
- jmp Displacement
-
- RMisReg: ;mod = 11
- inc pcntr
- mov bx,curadr
- mov al,es:[bx] ;get op code again
- cmp al,63h ;ARPL ?
- jz RegLast
- cmp al,69h ;'186 IMUL immed ?
- jz RegFirst
- test al,2 ;the D bit. Never set for TEST
- ; **** ignored for '286 long instrs ??
- jnz RegFirst
- RegLast:
- call PrtRegOfRM
- call comma
- jmp PrtReg
-
- RegFirst:
- call PrtReg
- call comma
- jmp PrtRegOfRM
-
- ChkQuirk: ; the MOD field is 00
- inc pcntr
- mov bx,curadr
- mov al,es:[bx] ;get the op code again
- cmp al,63h ;ARPL ?
- jz QuirkRegLast
- test al,2
- jnz QuirkReg1st
- QuirkRegLast:
- call l1606
- call comma
- jmp PrtReg
-
- QuirkReg1st:
- call PrtReg
- call comma
- jmp l1606
-
- Displacement: ;mod = 01 or 10, [XX+YY+disp]
- inc pcntr
- mov bx,curadr
- mov al,es:[bx] ;get op code again
- cmp al,63h ;ARPL ?
- jz DisplFirst
- cmp al,69h ;'186 IMUL ?
- jz DisplLast
- test al,2 ;set, 1st operand is displ, 2nd is reg
- jnz DisplLast
- DisplFirst:
- call PrtPTRandDisplPerReg ;print XS:XXXX PTR nn[XX+YY]
- call comma
- jmp PrtReg
-
- DisplLast:
- call PrtReg
- call comma
- jmp PrtPTRandDisplPerReg
-
- ;This is a CALL from above ModRegRM routine - - - - -
- l1606: cmp LongFlag,0
- jnz DoWORD ;'286 0F-prefix instrs are WORD
- mov bx,curadr
- mov al,es:[bx]
- test al,1
- jnz DoWORD
- call pstg
- db 'BYTE PTR ',0
- or OprndType,1 ;byte size
- jmp l1630
-
- DoWORD: call pstg
- db 'WORD PTR ',0
- or OprndType,2 ;word size
- l1630: call psgprf ;show segment override prefix if any
- ;if mod=00, and r/m=110 then addr word is present
- mov bx,curadr
- inc bx
- mov al,es:[bx] ;the modregr/m byte of the instr
- and al,7 ;bits 0, 1, 2 only, the r/m field
- cmp al,6 ;r/m = [BP]+disp ?
- jnz NotDoingBP
- ;it's addr word, not [BP]
- inc pcntr
- inc pcntr
- inc bx
- mov dx,es:[bx] ;the 'displ' word
- mov NoCommentAddr,1 ;don't show addr as a comment
- call PrtNoOrSmb ;add SMB if in B mode
- ret
-
- NotDoingBP:
- call PrtIndxedOprd ;print [BP+SI], etc
- ret
-
- PrtPTRandDisplPerReg:
- cmp LongFlag,0
- jnz PrtWordPtr ;'286 0F-prefix instrs are WORD
- mov bx,curadr
- mov al,es:[bx]
- test al,1 ;check the W bit
- jnz PrtWordPtr
- call pstg
- db 'BYTE PTR ',0
- or OprndType,1 ;byte size
- jmp PrtDisplPerReg
-
- PrtWordPtr:
- call pstg
- db 'WORD PTR ',0
- or OprndType,2 ;word size
- ;print reg or reg+displ (like 3[BP+SI], etc)
- PrtDisplPerReg:
- call psgprf
- ;at this point, the line looks like 0123 MOV WORD PTR CS:
- inc pcntr
- mov bx,curadr
- inc bx
- mov al,es:[bx] ;the modregr/m byte
- inc bx ;points DISP byte
- and al,11000000b
- cmp al,01000000b ;is DISP 1 byte ?
- jnz Not1ByteDisp
- mov al,es:[bx] ;get 1-byte disp
- ;CONVERT NEG NOS TO -nn form
- test al,80h ;is disp negative ?
- jz PosNo
- push ax
- call pstg
- db '-',0
- pop ax
- neg al
- PosNo: call PrintALh
- call PrtIndxedOprd ;print [BP+SI], etc
- ret
-
- Not1ByteDisp:
- inc pcntr
- mov dx,es:[bx] ;get disp word, just past modregr/m
- call PrintDXh
- call PrtIndxedOprd ;print [BP+SI], etc
- ret
- ;--------------------------------
- psgprf: push ax
- mov al,SegOvrdPfx
- or al,al
- jz NoPrefix
- and al,18h
- call PrtaSegReg
- call colon
- mov al,SegOvrdPfx
- shl al,1 ;get the 2 REG bits into the hi nibble
- and al,00110000b ;look at only those bits
- xor al,00100000b ;invert hi bit, now S D E C - why??
- mov OprndType,al
- mov SegOvrdPfx,0
- NoPrefix:
- pop ax
- ret
-
- namr16: mov bx,offset rtb16
- add al,al
- call AddALtoBX
- mov al,cs:[bx]
- call typech
- inc bx
- mov al,cs:[bx]
- jmp typech
-
- rtb16 db 'AX','CX','DX','BX','SP','BP','SI','DI'
-
- namrg8: mov bx,offset rtb08
- add al,al
- call AddALtoBX
- mov al,cs:[bx]
- call typech
- inc bx
- mov al,cs:[bx]
- jmp typech
-
- rtb08 db 'AL','CL','DL','BL','AH','CH','DH','BH'
- ; - - - - - - - - - - - - - - - -
- kind22: ;80286, 386 Protected mode instrs begin w/0Fh
- ror Direc286Flag,1 ;move present status to hi bit
- or Direc286Flag,1 ;and set flag (invalid codes will restore)
- mov LongFlag,1 ;'long' 2-byte op codes with ModRegR/M ex CLTS
- inc curadr
- inc pcntr
- mov bx,curadr ;to 2nd byte of opcode, now curadr
- mov al,es:[bx+1]
- mov CurModRegRM,al
- mov al,es:[bx]
- mov CurInstr,al
- test al,11111100b ;look at all but lo 2 bits of instr
- jnz BetterBeCLTS
- cmp al,3
- jz ItsLSL
- cmp al,2
- jnz xxyy
- jmp ItsLAR
- xxyy: or al,al ;AL has lo 2 bits of opcode
- jz ItsLD_TR_VER
- ;2nd byte is 01, instr is LGDT, SGDT, LIDT, SIDT, LMSW, or SMSW
- mov bl,CurModRegRM
- and bl,00111000b
- cmp bl,00111000b
- jz NotAny
- cmp bl,00101000b
- jz NotAny
- mov bx,offset DTandSWtbl
- call PrtLongInstrs
- call PrtTab
- mov al,CurModRegRM
- and al,00111000b
- cmp al,00100000b
- jae ItsMSW
- call pstg
- db 'F',0 ;MASM 5.0 bug requires Q here
- call PrtMoprnd
- jmp NewLine
-
- ;2nd byte is 00, instr is LLDT, SLDT, LTR, STR, VERR, or VERW
- ItsLD_TR_VER:
- mov bl,CurModRegRM
- and bl,00111000b
- cmp bl,00110000b
- jae NotAny
- mov bx,offset LongZeroTbl
- call PrtLongInstrs
- call PrtTab
- ItsMSW: call PrtWhatsShifted
- jmp NewLine
-
- BetterBeCLTS:
- cmp al,6
- jnz NotAny
- call pstg
- db 'CLTS',0
- jmp NewLine
-
- NotAny: call pstg
- db 'DB',tab,'0Fh,',0
- mov al,CurInstr
- call PrintALh
- rol Direc286Flag,1 ;restore bit 0 to previous status
- jmp NewLine
-
- ItsLSL: call pstg
- db 'LSL',tab,0
- call ModRegRM
- jmp NewLine
-
- ItsLAR: call pstg
- db 'LAR',tab,0
- call ModRegRM
- jmp NewLine
-
- ; - - - - - - - - - - - - - - - -
- kind23: mov al,CurInstr ;segment override prefix
- mov SegOvrdPfx,al
- jmp dline ;to continue instr
- ; - - - - - - - - - - - - - - - -
- kind24: call PrtTab ;push/pop seg regs
- mov al,CurInstr
- and al,18h
- call PrtaSegReg
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind25: call PrtTab ;MOV AL or AX <-> mem, codes A0h - A3h
- inc pcntr
- inc pcntr
- mov al,CurInstr
- test al,2
- jz MemToAccum
- call PrtMemory
- call comma
- call paccum
- jmp NewLine
-
- MemToAccum:
- call paccum
- call comma
- call PrtMemory
- jmp NewLine
-
- paccum: mov al,CurInstr
- test al,1 ;the W bit
- jnz acc16b
- call pstg
- db 'AL',0
- ret
-
- acc16b: call pstg
- db 'AX',0
- ret
-
- PrtMemory:
- mov al,CurInstr
- test al,1
- jnz TisWord
- call pstg
- db 'BYTE PTR ',0
- or OprndType,1 ;byte size
- jmp l17b3
-
- TisWord:
- call pstg
- db 'WORD PTR ',0
- or OprndType,2 ;word size
- l17b3: call psgprf
- mov bx,curadr
- inc bx
- mov dx,es:[bx]
- mov NoCommentAddr,1 ;don't show addr as a comment
- call PrtNoOrSmb
- ret
- ; - - - - - - - - - - - - - - - -
- kind26: ;shift/rotate instr's
- mov al,es:[bx+1] ;get byte after op code, modTTTr/m
- mov CurModRegRM,al
- and al,00111000b ;get the TTT field
- cmp al,00110000b ;TTT=110 ?
- jnz ValidTTT
- jmp PrtDBandByte ;it's not a valid Op code
-
- ValidTTT:
- call PrtShiftOpds
- call PrtTab
- call PrtWhatsShifted ;does single-operand Extnd Addrs
- call comma
- mov al,CurInstr ;get the Op code again
- and al,0FEh ;look at all but last bit
- cmp al,0C0h ;is it '286 sh/rotate by count ?
- jnz NotByCount
- mov Direc286Flag,1
- mov bx,pcntr ;because length of instr is variable
- mov al,es:[bx] ;the count byte
- call PrintALh
- inc pcntr ;these are 1 byte longer
- jmp NewLine
-
- NotByCount:
- and al,2 ;bit 1 signals 'by CL'
- jz Shift1
- call pstg
- db 'CL',0
- jmp NewLine
-
- Shift1: mov al,'1'
- call typech
- jmp NewLine
-
- PrtWhatsShifted:
- inc pcntr
- mov al,CurModRegRM
- and al,11000000b ;look at 'mod' field
- cmp al,11000000b
- jz ItsaReg
- or al,al
- jz NoDispl
- jmp PrtPTRandDisplPerReg
-
- ItsaReg:
- jmp PrtRegOfRM
-
- NoDispl:
- jmp l1606
-
- ; - - - - - - - - - - - - - - - -
- kind27: inc bx ;POP to memory
- mov al,es:[bx]
- mov CurModRegRM,al
- and al,38h
- jz YesPOPmem
- jmp PrtDBandByte
-
- YesPOPmem:
- call pstg
- db 'POP',0
- call PrtTab
- call PrtWhatsShifted
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind28: ;MOV to or from segment reg
- mov al,es:[bx+1] ;get 2nd byte of instr
- mov CurModRegRM,al
- test al,20h ;nondest AND AL, 0010000
- jz YesMOVsegreg
- jmp PrtDBandByte
-
- YesMOVsegreg:
- call pstg
- db 'MOV',0
- call PrtTab
- mov al,CurInstr
- test al,2
- jnz l1865
- call l187d
- call comma
- call l1871
- jmp NewLine
-
- l1865: call l1871
- call comma
- call l187d
- jmp NewLine
-
- l1871: mov al,CurModRegRM
- and al,18h
- jmp PrtaSegReg
-
- l187d: inc pcntr
- mov al,CurModRegRM
- and al,11000000b
- cmp al,11000000b
- jz RMisaReg
- or al,al
- jnz l18ba
- jmp DoWORD
-
- RMisaReg:
- mov al,CurModRegRM
- and al,7
- jmp namr16
-
- l18ba: call pstg
- db 'WORD PTR ',0
- or OprndType,2 ;word type
- jmp PrtDisplPerReg ;prints Seg Ovrd Pfx, if any
- ; - - - - - - - - - - - - - - - -
- kind29: ;MOV immed to r/m
- inc bx
- mov al,es:[bx] ;modregr/m byte
- mov CurModRegRM,al
- and al,38h
- jz ItsMov
- jmp PrtDBandByte ;not a valid code
-
- ItsMov: call pstg
- db 'MOV',0
- call PrtTab
- jmp l1c19
- ; - - - - - - - - - - - - - - - -
- kind30: ;LEA, ModRegR/M, but no Reg
- ;MASM always assumes DS:, but old code may have Seg Ovrd Pfx
- mov al,SegOvrdPfx
- or al,al
- jz NoLEApfx
- and al,18h
- cmp al,00011000b ;DS:
- jz NoLEApfx
- call pstg
- db 'DB',tab,0
- mov al,SegOvrdPfx
- call PrintALh
- call PrtTab
- call semic
- call pstg
- db 'Seg Prefix for code length, MASM will use DS:',cr,lf,tab,0
- NoLEApfx:
- call pstg
- db 'LEA',0
- call PrtTab
- mov al,es:[bx+1]
- mov CurModRegRM,al
- and al,38h
- shr al,1
- shr al,1
- shr al,1 ;which register in list
- call namr16 ;print register (AX, BX, etc)
- call comma
- call PrtMoprnd
- jmp NewLine
-
- PrtMoprnd:
- inc pcntr
- mov al,CurModRegRM
- and al,0C0h ;the mod field
- or al,al
- jnz Tol18ba ;print 'WORD PTR' and addr
- jmp DoWORD
- Tol18ba:
- jmp l18ba ;print 'WORD PTR' and [XX+nn]
-
- ; - - - - - - - - - - - - - - - -
- kind31: ;NOT r/m
- inc bx
- mov al,es:[bx]
- mov CurModRegRM,al
- and al,38h
- cmp al,8
- jnz YesNOT
- jmp PrtDBandByte
-
- YesNOT: call pmisci
- call PrtTab
- mov al,CurModRegRM
- and al,38h
- jz Tol1c19
- call PrtWhatsShifted
- jmp NewLine
-
- Tol1c19:
- jmp l1c19
- ; - - - - - - - - - - - - - - - -
- kind32: inc bx ;INC, DEC reg/mem
- mov al,es:[bx]
- mov CurModRegRM,al
- and al,38h
- or al,al
- jz l1971
- cmp al,8
- jz l197f
- jmp PrtDBandByte
-
- l1971: call pstg
- db 'INC',0
- jmp l1986
-
- l197f: call pstg
- db 'DEC',0
- l1986: call PrtTab
- call PrtWhatsShifted
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind33: inc bx ;code FFh. Many: INC, DEC, CALLs, JMP, PUSH mem
- mov al,es:[bx] ;2nd byte, mod sub-opcode r/m
- mov CurModRegRM,al
- and al,38h ;sub-opcode
- cmp al,38h
- jnz OK33
- jmp PrtDBandByte ;db, not valid instr
-
- OK33: or al,al ;inc reg/mem word
- jz ItsINC
- cmp al,8 ;dec reg/mem word
- jz ItsDEC
- cmp al,30h ;push reg/mem
- jz ItsPUSHrm
- cmp al,00011000b ;indir interseg call
- jz ItsCallDword
- cmp al,00101000b ;indir interseg jmp
- jz ItsJmpDword
- cmp al,00010000b ;reg/mem indir intraseg call
- jz ItsCallPER
- jmp ItsJmpPER ;reg/mem indir intraseg jmp (AL must be 20h)
-
- ItsINC: call pstg
- db 'INC',0
- jmp l19d1
-
- ItsDEC: call pstg
- db 'DEC',0
- l19d1: call PrtTab
- call PrtMoprnd
- jmp NewLine
-
- ItsPUSHrm:
- call pstg
- db 'PUSH',0
- jmp l19d1
-
- ItsCallPER:
- call pstg
- db 'CALL',tab,0
- call PrtWhatsShifted
- jmp NewLine
-
- ItsJmpPER:
- call pstg
- db 'JMP',tab,0
- call PrtWhatsShifted
- mov CurInstr,0E9h ;signal to put blank line after this
- jmp NewLine
-
- ItsCallDword:
- call pstg
- db 'CALL',tab,0
- jmp DoDWORD
-
- ItsJmpDword:
- call pstg
- db 'JMP',tab,0
- mov CurInstr,0E9h ;signal to put blank line after this
- DoDWORD:
- call pstg
- db 'DWORD PTR ',0
- or OprndType,3 ;dword type
- inc pcntr
- mov al,CurModRegRM ;for BOUND, LDS & LES
- and al,11000000b ;the Mode field
- or al,al
- jz NoDis
- ;register or reg+displ
- call PrtDisplPerReg
- jmp NewLine
-
- ;Mod = 0, no displacement unless R/M = 110 then is word addr
- NoDis: call l1630
- jmp NewLine
-
- ; - - - - - - - - - - - - - - - -
- kind34: ;call far ptr, 9Ah & jmp far ptr, EAh
- ;MASM req SEGMENT AT to generate these
- call PrtTab
- add pcntr,4
- mov dx,es:[bx+3] ;get segment
- call PrintDXh
- call colon
- mov dx,es:[bx+1] ;get offset
- call PrintDXh
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind35: ;'186 ENTER nnnn,nn
- call PrtTab
- mov dx,es:[bx+1]
- call PrintDXh
- call comma
- mov al,es:[bx+3]
- call PrintALh
- add pcntr,3
- jmp NewLine
-
- ; - - - - - - - - - - - - - - - -
- kind36: ;RET nnnn, RET FAR nnnn
- call PrtTab
- mov dx,es:[bx+1]
- call PrintDXh
- inc pcntr
- inc pcntr
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind16: call PrtTab ;ESC nn,reg for 80x87
- ; *** not right, do the FLoating instr's ***
- mov al,CurInstr
- and al,7 ;get the TTT field
- mov cl,3
- shl al,cl
- mov ah,al
- mov al,es:[bx+1]
- mov CurModRegRM,al
- and al,38h ;the LLL field
- mov cl,3
- shr al,cl
- add al,ah ;now AL = 00 TTT LLL
- call PrintALh
- call comma
- call l187d
- jmp NewLine
- ; - - - - - - - - - - - - - - - -
- kind17: mov al,CurInstr ;LOOPZ and LOOPNZ
- and al,3
- cmp al,0
- jnz ItsLOOPZ
- call pstg
- db 'NZ',0
- jmp kind21
-
- ItsLOOPZ:
- cmp al,1
- jnz l1b55
- call pstg
- db 'Z',0
- l1b55: jmp kind21
- ; - - - - - - - - - - - - - - - -
- kind18: ;arith, r/m & reg to either
- call PrtArithInstr ; (opcode bits 00111011 only)
- kind19: call PrtTab ;TEST, XCHG, MOV, IMUL186, ARPL reg w/reg/mem
- mov bx,curadr
- mov al,CurInstr
- call ModRegRM
- mov al,CurInstr
- cmp al,69h ;is it '186 IMUL immed word ?
- jz ItsIMUL
- cmp al,6Bh ;is it IMUL immed Sign-Ext byte ?
- jz ItsIMUL
- jmp NewLine
-
- ItsIMUL:
- mov bx,pcntr ;ModRegRM routine has variable bytes
- inc pcntr
- call comma
- mov al,CurInstr
- cmp al,6Bh
- jnz IMULword
- jmp SignExtend
-
- IMULword:
- mov dx,es:[bx]
- inc pcntr
- call PrintDXh
- jmp NewLine
-
- ; - - - - - - - - - - - - - - - -
- ;LES, LDS, BOUND. Enter w/BX=curadr, points 1st byte of op code
- kind38: call PrtTab ;the instr has just been printed
- mov al,es:[bx+1] ;get modregr/m byte
- mov CurModRegRM,al
- and al,00111000b ;the Reg field
- shr al,1
- shr al,1
- shr al,1 ;AL=which register in list
- call namr16 ;print the register
- call comma
- jmp DoDWORD
- ; - - - - - - - - - - - - - - - -
- kind20: ;Arith immed to reg/mem, code 80,1,2,3h
- mov al,CurInstr ;NOTE: Intel book is WRONG, uses d bit
- L1c0c: inc bx ;to ModRegRM, has actual instr
- call PrtArithInstr
- call PrtTab
- ;print the ModRegR/M and immed data for arith & mov immed.
- ; PrtModRegRM does similar, but no immed data
- l1c19: mov bx,curadr
- inc bx
- mov al,es:[bx] ;get the modregr/m byte
- mov CurModRegRM,al
- and al,0C0h ;look at the mod field
- or al,al
- jnz ModNotZero
- jmp ModIsZero
- ModNotZero:
- cmp al,0C0h
- jz ModIs11
- ;mod is 01 or 10, disp is present
- inc pcntr
- call PrtPTRandDisplPerReg ;no use BX
- call comma
- mov al,CurModRegRM
- mov bx,curadr
- inc bx
- inc bx
- inc bx
- test al,80h ;word disp ?
- jz bbbb
- inc bx ;curadr + 3 or 4 to get past DISP
- bbbb: inc pcntr
- jmp PrtImmedData
-
- ModIs11:
- inc pcntr
- call PrtRegOfRM ;no use BX
- call comma
- inc pcntr
- mov al,CurInstr
- mov bx,curadr
- inc bx ;ought to use Curadr, not BX
- inc bx
- PrtImmedData:
- push bx ;must save BX, locn diff if DISP present
- mov bx,curadr
- mov al,es:[bx]
- cmp al,83h ;is the sign-extend bit set ?
- pop bx
- jz SignExtend ;doesn't use AX, DOES use BX
- test al,1
- jnz WordData
- ;it is Byte Data
- mov curadr,bx
- cmp al,0C6h ;is it MOV ea,ib ?
- jz OKtoShowASCII
- mov al,CurModRegRM
- OldArith: ;used by kind04, arith/logic to AL
- ; - the 3 bits in the op code are same as REG
- and al,00111000b ;get the sub-opcode field
- cmp al,00111000b ;is it CMP ?
- jnz ChkLogic
- OKtoShowASCII:
- call bytopd ;print [curadr] as ASCII if so
- jmp NewLine
-
- ChkLogic:
- cmp al,00100000b ;AND
- jz ItsLogic
- cmp al,00001000b ;OR
- jz ItsLogic
- cmp al,00110000b ;XOR
- jz ItsLogic
- mov bx,curadr
- mov al,es:[bx]
- ForZero:
- call PrintALh
- jmp NewLine
-
- ItsLogic: ;print the byte as Binary
- mov bx,curadr
- mov al,es:[bx]
- or al,al
- jz ForZero
- mov dl,al
- push es
- push cs
- pop es
- mov di,offset Bits
- mov cx,8
- BitLoop:
- mov al,'0'
- shl dl,1
- jnc StoreBit
- inc al
- StoreBit:
- stosb
- loop BitLoop
-
- pop es
- call pstg
- Bits db 8 dup('0'),'b',0
- jmp NewLine
-
- WordData:
- inc pcntr
- mov dx,es:[bx]
- call PrintDXh
- jmp NewLine
-
- SignExtend:
- xor dh,dh
- mov dl,es:[bx]
- or dl,dl
- jns PosExtend
- dec dh ;to 0FFh
- PosExtend:
- call PrintDXh
- jmp NewLine
-
- ModIsZero:
- inc pcntr
- call l1606
- call comma
- mov bx,curadr
- inc bx
- mov al,es:[bx] ;get the modregr/m byte
- and al,7 ;look at the r/m field
- cmp al,6 ;check the [BP] quirk
- jnz l1c93
- ;mod=00 and r/m=110, so word disp, not [BP]
- inc bx
- inc bx
- l1c93: inc bx
- inc pcntr
- jmp PrtImmedData
- ;--------------------------------
- comma: push ax
- mov al,','
- call typech
- pop ax
- ret
-
- apostrophe:
- push ax
- mov al,''''
- call typech
- pop ax
- ret
-
- PrtTab: mov al,tab
- jmp typech
-
- semic: mov al,';'
- jmp typech
-
- colon: mov al,':'
- jmp typech
-
- PrtDBandByte:
- call pstg
- db 'DB',tab,0
- call bytopd
- jmp NewLine
-
- ;--------------------------------
- PrtaSegReg:
- shr al,1
- shr al,1
- mov bx,offset segtbl
- mov ch,2
- call AddALtoBX
- jmp PrtFromTabl
-
- PrtIndxedOprd:
- mov bx,offset indtbl ;holds [BP+SI][BX]...[BX+SI], etc
- push bx ; (only ref to indtbl)
- mov bx,curadr
- inc bx
- mov al,es:[bx] ;get the modregr/m byte
- and al,7 ;the r/m field, it's a reg
- shl al,1
- shl al,1
- shl al,1 ;multiply by eight
- pop bx
- mov ch,8 ;each entry is 8 bytes
- call AddALtoBX
- jmp PrtFromTabl ;print the entry in the table
-
- PrtLongInstrs:
- push bx
- jmp Prt4ByteTbl
-
- pmisci: mov bx,offset msctbl
- push bx
- Prt4ByteTbl:
- mov bx,curadr
- inc bx
- mov al,es:[bx] ;get the ModREgR/M byte
- and al,38h
- shr al,1
- pop bx
- mov ch,4 ;each entry is 4 bytes
- call AddALtoBX
- jmp PrtFromTabl ;print the entry in msctbl
-
- PrtShiftOpds:
- mov bx,curadr
- inc bx
- mov al,es:[bx]
- and al,38h ;00111000b, just look at the TTT field
- shr al,1
- shr al,1
- mov ah,al
- shr al,1
- add al,ah
- mov bx,offset shftbl
- jmp Prt3FromTabl
-
- PrtArithInstr:
- mov al,es:[bx]
- and al,38h
- shr al,1
- shr al,1
- mov ah,al
- shr al,1
- add al,ah
- mov bx,offset aritbl
- jmp Prt3FromTabl
-
- pcndop: mov bx,curadr ;print Conditional ops (JC, JNZ, etc)
- mov al,es:[bx] ;get op code
- and al,0Fh ;just look at low nibble
- mov ch,al
- add al,al
- add al,ch ;lo nibble X 3
- mov bx,offset cndtbl
- Prt3FromTabl:
- mov ch,3
- call AddALtoBX
- PrtFromTabl:
- mov al,cs:[bx]
- cmp al,'.'
- jz PrtSkip
- call typech
- PrtSkip:
- inc bx
- dec ch
- jnz PrtFromTabl
- ret
-
- AddALtoBX:
- push ax
- xor ah,ah
- add bx,ax
- pop ax
- ret
- ;--------------------------------
- ;PRINT [BX] until CH=0
- PrtCHbytesPerBX:
- mov al,[bx]
- call typech
- inc bx
- dec ch
- jnz PrtCHbytesPerBX
- ret
- ;--------------------------------
- segtbl db 'ES','CS','SS','DS'
-
- cndtbl db 'O..','NO.','C..','NC.'
- db 'Z..','NZ.','NA.','A..'
- db 'S..','NS.','PE.','PO.'
- db 'NGE','GE.','NG.','G..'
-
- shftbl db 'ROL','ROR','RCL','RCR'
- db 'SHL','SHR','...','SAR'
-
- msctbl db 'TEST','....','NOT.','NEG.'
- db 'MUL.','IMUL','DIV.','IDIV'
-
- aritbl db 'ADD','OR.','ADC','SBB'
- db 'AND','SUB','XOR','CMP'
-
- ;this table entries 8 char for ease of math
- indtbl db '[BX+SI].','[BX+DI].','[BP+SI].','[BP+DI].'
- db '[SI]....','[DI]....','[BP]....','[BX]....'
-
- DTandSWtbl db 'SGDT','SIDT','LGDT','LIDT','SMSW','....','LMSW'
-
- LongZeroTbl db 'SLDT','STR.','LLDT','LTR.','VERR','VERW'
-
- ;--------------------------------
- ; Opcode mask, Opcode pattern, Kind, Literal
- ; Each line is 8 bytes. Opcode ANDED 1st byte must=2nd byte
- ; 3rd byte is Kind - see 'kindNN:' routines
- ; Most of these lines can be in any order, see last line.
- ; Don't print instr if do additional chk for valid instr first.
-
- opct db 0ffh,098h,00,'CBW..' ;Kind00 have no operands
- db 0ffh,027h,00,'DAA..'
- db 0ffh,02fh,00,'DAS..'
- db 0ffh,037h,00,'AAA..'
- db 0ffh,0c3h,00,'RET..'
- db 0ffh,0cbh,00,'RETF.' ;MASM 5.0+ takes this
- db 0ffh,099h,00,'CWD..'
- db 0ffh,09bh,00,'FWAIT'
- db 0ffh,09ch,00,'PUSHF'
- db 0ffh,09dh,00,'POPF.'
- db 0ffh,09eh,00,'SAHF.'
- db 0ffh,09fh,00,'LAHF.'
- db 0ffh,0ceh,00,'INTO.'
- db 0ffh,0cfh,00,'IRET.'
- db 0ffh,0f4h,00,'HLT..'
- db 0ffh,0f5h,00,'CMC..'
- db 0ffh,0f8h,00,'CLC..'
- db 0ffh,0f9h,00,'STC..'
- db 0ffh,0fah,00,'CLI..'
- db 0ffh,0fbh,00,'STI..'
- db 0ffh,0fch,00,'CLD..'
- db 0ffh,0fdh,00,'STD..'
- db 0ffh,090h,00,'NOP..'
- db 0ffh,03fh,00,'AAS..'
- db 0ffh,0d7h,00,'XLAT.'
- db 0ffh,060h,00,'PUSHA' ;186
- db 0ffh,061h,00,'POPA.' ;186
- db 0ffh,0c9h,00,'LEAVE' ;186
- db 0ffh,0cch,00,'INT 3'
- db 0feh,0ech,01,'IN...' ;AL or AX,DX
- db 0feh,0eeh,01,'OUT..' ;DX, AL or AX
- db 0ffh,0e5h,02,'IN...' ;AX,nn
- db 0ffh,0e7h,02,'OUT..' ;nn,AX
- db 0f0h,0b0h,03,'MOV..' ;immed to reg
- db 0ffh,004h,04,'ADD..' ; Kind 4 are arith & logic to AL
- db 0ffh,00ch,04,'OR...'
- db 0ffh,014h,04,'ADC..'
- db 0ffh,01ch,04,'SBB..'
- db 0ffh,024h,04,'AND..'
- db 0ffh,02ch,04,'SUB..'
- db 0ffh,034h,04,'XOR..'
- db 0ffh,03ch,04,'CMP..' ;immed w/AL, byte
- db 0ffh,0a8h,04,'TEST.'
- db 0ffh,005h,06,'ADD..' ;Kind 6 are arith & logic to AX
- db 0ffh,00dh,06,'OR...'
- db 0ffh,015h,06,'ADC..'
- db 0ffh,01dh,06,'SBB..'
- db 0ffh,025h,06,'AND..'
- db 0ffh,02dh,06,'SUB..'
- db 0ffh,035h,06,'XOR..'
- db 0ffh,03dh,06,'CMP..' ;immed w/AX, word
- db 0ffh,0a9h,06,'TEST.'
- db 0ffh,0cdh,07,'INT..'
- db 0ffh,0d4h,08,'AAM..'
- db 0ffh,0d5h,08,'AAD..' ;Kind 08 are 2-bytes, 2nd is 0Ah
- db 0ffh,0f3h,09,'REP..' ;Kind 09 are prefix instrs...
- db 0ffh,0f2h,09,'REPNZ' ; REPZ, REPE same as REP
- db 0ffh,0f0h,09,'LOCK.'
- db 0fdh,068h,10,'PUSH.' ;186 PUSH nnnn
- db 0feh,0a4h,12,'MOVS.' ;Kind 12 are String instructions
- db 0feh,0a6h,12,'CMPS.'
- db 0feh,0aah,12,'STOS.'
- db 0feh,0ach,12,'LODS.'
- db 0feh,0aeh,12,'SCAS.'
- db 0feh,06ch,12,'INS..' ;186 ins [dx]
- db 0feh,06eh,12,'OUTS.' ;186 outs [dx]
- db 0f8h,090h,13,'XCHG.' ;with AX
- db 0f8h,040h,15,'INC..' ;Kind 15 are one 16 bit reg
- db 0f8h,048h,15,'DEC..'
- db 0f8h,050h,15,'PUSH.'
- db 0f8h,058h,15,'POP..' ;non-seg register
- db 0f8h,0d8h,16,'Fxxxx' ;80x87 codes, not done yet
- db 0f0h,070h,11,'J....' ;Jxx are 70h-7Fh [DISPL]
- db 0ffh,0e3h,21,'JCXZ.' ; [DISPL]
- db 0ffh,0ebh,21,'JMP..' ;(SHORT jump) [DISPL]
- db 0ffh,0e8h,05,'CALL.' ; [DISPL]
- db 0ffh,0e9h,05,'JMP..' ;word relative [DISPL]
- db 0feh,0e0h,17,'LOOP.' ;LOOPNZ (E0h) and LOOPZ (E1h) [DISPL]
- db 0ffh,0e2h,17,'LOOP.' ;plain LOOP short-label [DISPL]
- db 0c4h,000h,18,'.....' ;arith, r/m & r to ModRegR/M
- db 0feh,084h,19,'TEST.' ;ModRegR/M
- db 0feh,086h,19,'XCHG.' ;except with AX
- db 0fch,088h,19,'MOV..' ;MOV reg <-> reg/mem
- db 0fdh,069h,19,'IMUL.' ;186 ModRegR/M,nnnn
- db 0ffh,063h,19,'ARPL.' ;286
- db 0fch,080h,20,'.....' ;arith & logic immed to reg/mem
- db 0ffh,00fh,22,'.....' ;286 prot control & CLTS prefix
- db 0ffh,026h,23,'.....' ;Kind23 is seg override prefix only
- db 0ffh,02eh,23,'.....'
- db 0ffh,036h,23,'.....'
- db 0ffh,03eh,23,'.....'
- db 0ffh,006h,24,'PUSH.' ;Kind24 are push/pop SEG REG
- db 0ffh,00eh,24,'PUSH.'
- db 0ffh,016h,24,'PUSH.'
- db 0ffh,01eh,24,'PUSH.'
- db 0ffh,007h,24,'POP..' ;ES
- db 0ffh,017h,24,'POP..' ;SS
- db 0ffh,01Fh,24,'POP..' ;DS
- ;note: POP CS (0Fh) works on 8088,6 only, used as prefix on '186+ !
- db 0fch,0a0h,25,'MOV..' ;MOV AL or AX <-> mem
- db 0fch,0d0h,26,'.....' ;shift/rotate
- db 0feh,0C0h,26,'.....' ;186 shift by count
- db 0ffh,08fh,27,'.....' ;POP memory
- db 0ffh,08ch,28,'.....' ;MOV mem-or-reg, seg reg
- db 0ffh,08eh,28,'.....' ;MOV seg reg, mem-or-reg
- db 0feh,0c6h,29,'.....' ;MOV immed to reg/mem
- db 0ffh,08dh,30,'.....' ;LEA ModRegR/M, but no Reg
- db 0feh,0f6h,31,'.....' ;NOT reg/mem
- db 0ffh,0feh,32,'.....' ;INC, DEC ModRegR/M
- db 0ffh,0ffh,33,'.....' ;many: call/jmp DWORD PTR, PUSH mem. etc
- db 0ffh,09ah,34,'CALL.' ;OOOO:SSSS
- db 0ffh,0eah,34,'JMP..' ;OOOO:SSSS
- db 0ffh,0C8h,35,'ENTER' ;'186 ENTER nnnn,nn
- db 0ffh,0c2h,36,'RET..' ;RET nnnn
- db 0ffh,0cah,36,'RETF.' ;RETF nnnn
- db 0ffh,0e4h,37,'IN...' ;IN AL,nn
- db 0ffh,0e6h,37,'OUT..' ;OUT nn,AL
- db 0ffh,062h,38,'BOUND' ;'186 BOUND wr,dw[nnnn]
- db 0ffh,0c4h,38,'LES..' ;ModRegR/M mod not 11
- db 0ffh,0c5h,38,'LDS..' ;ModRegR/M mod not 11
- db 0
- ;--------------------------------
-
- ; .SMB (label) table structure, variable length records:
-
- ; 2 bytes address, 1 byte seg/type, 1 byte string length, n bytes string
- ; table end defined by length byte = 0
- ; first byte past end pointed to by symtp
- ; type bits 1-0: 0=instr, 1=byte, 2=word, 3=dword
- ; type bits 5-4: 0=ss, 1=ds, 2=es, 3=cs (bit 3 inverted from REG code)
-
- ;ADDSYM called only in B cmd, creates H0[DX] (or [DX-ORG] for hard coded).
- ;Generates text of H0NNNN (same form as DASM).
- addsym: mov bx,offset lblbuf ;use to build up label string
- mov byte ptr [bx],'H'
- inc bx
- mov byte ptr [bx],'0'
- inc bx
- push dx ;label's pcntr addr
- cmp RelFlag,0
- jz hardcod
- add dx,curorg ;correct text for ORG, rel-displ only
- hardcod:
- mov al,dh ;put DX into string
- call StoreHex ;AL to 2 hex bytes [BX] & inc bx
- mov al,dl
- call StoreHex
- pop dx ;restore pcntr addr of label
- mov bx,offset lblbuf ;point beginning of string
- mov ch,6 ;string length of H0nnnn
- ;SYMTCH also used by E command & to enter 'Start:'.
- symtch: push cx
- push bx
- call symluk ;is there a label for addr=DX ?
- pop bx
- pop cx
- jc entsym ;jump if no label at addr
- ret
-
- ;first, open up space for new entry
- entsym: mov ChgFlag,1 ;for 'Update/Exit'
- push bx ;pointer to string to insert
- push cx ;CH = string length
- mov bx,symtp
- mov si,bx ;save old symtp
- mov al,ch ;length of label
- xor ah,ah
- add al,4
- add si,ax
- mov symtp,si ;new '1-past-end' pointer
- mov byte ptr [si+3],0 ;zero length byte marks end
-
- ;now SI = new symtp, BX = old symtp (used SI not DI so no change to ES)
- l22a5: cmp bx,NxtSymPtr ;set by symluk
- jz inssym
- dec bx
- dec si
- mov al,[bx] ;start w/1st byte below old symtp
- mov [si],al ;move to 1st below new sympt
- jmp l22a5
-
- ;put new entry in hole just made, DX = addr of label
- inssym: pop cx ;CH is length byte
- cmp RelFlag,0 ;rel-displ ?
- jnz notchg
- cmp byte ptr cmdbuf+2,'E' ;in E command? [BYTE PTR reqd]
- jz notchg
- sub dx,curorg ;hard-coded oprnds in B command only
- notchg: mov [bx],dx
- inc bx
- inc bx
- mov al,OprndType
- mov [bx],al
- inc bx
- mov [bx],ch ;length of label
- pop si ;was BX, pointer to string to insert
- l22cb: inc bx
- mov al,[si]
- mov [bx],al
- inc si
- dec ch
- jnz l22cb
- ret
-
- ;--------------------------------
- ;locate symbol. BX > start of string to match, CH = length of string.
- ; Returns w/C set and BX unchanged if not found.
- locsym: push dx
- push bx ;string start
- mov bx,symbas
- NxSym: pop dx
- push dx ;string start
- inc bx
- inc bx
- inc bx
- push bx
- mov al,[bx] ;entry's length
- or al,al
- jz NotFoundExit ;table end
- inc bx
- cmp al,ch ;entry length - string length
- jnz PointNext
- ;length matches
- mov cl,al ;bytes to compare
- call cmpstr
- jz symfnd ;found right entry
- PointNext:
- pop bx ;points length byte of same entry
- mov al,[bx]
- inc bx ;string start
- call AddALtoBX
- jmp NxSym
-
- symfnd: pop bx ;points length byte of same entry
- dec bx
- dec bx
- dec bx ;back to entry start
- pop dx ;adj stack
- pop dx
- clc
- ret
-
- NotFoundExit:
- pop bx
- pop bx
- pop dx
- stc ;not found flag
- ret
-
- ;--------------------------------
- ;Check for symbol/label at [DX] (or [DX-ORG] for hard coded addrs)
- ;Struc: 2 bytes address, 1 byte Oprndtype, 1 byte string length, n bytes string
- ;saves DX, BX lost - no carry & BX > start of string, CH=length if found.
- symluk: mov bx,symbas
- mov NxtSymAddr,0 ;changed if exist lbl at or past DX addr
- push dx
- cmp RelFlag,0 ;rel-displ instr ?
- jnz SymlookLoop ;yes, jump
- cmp byte ptr cmdbuf+2,'E' ;are we entering a label?
- jz SymlookLoop
- cmp word ptr cmdbuf+2,'SD' ;are we Dumping Symbol table ?
- jz SymlookLoop
- cmp word ptr cmdbuf+2,0D43h ;cr,'C' - are we dumping the CTL table ?
- jz SymlookLoop
- sub dx,curorg
- SymlookLoop:
- mov ax,[bx] ;get address
- add bx,3 ;to length byte
- cmp ax,dx ;this lbl's addr - one we want
- jz SmbFound
- jc ChkForEnd
- ;this is 1st label is for addr higher than DX
- sub bx,3 ;back to addr
- mov NxtSymPtr,bx
- mov dx,[bx]
- mov NxtSymAddr,dx
- stc ;signal not found
- jmp EndSymLook
-
- ;this label addr is less than the one we're looking for
- ChkForEnd:
- mov al,[bx]
- or al,al ;end of table ?
- stc
- jnz l2348 ;not end
- mov bx,symtp
- mov NxtSymPtr,bx
- jmp EndSymlook ;addr past highest in table, ret w/C
-
- l2348: inc bx ;to 1st of string
- call AddALtoBX ;adj for string length
- jmp short SymlookLoop
-
- SmbFound: ;(segment scheme req chk seg here)
- mov ch,[bx] ;string length to return
- mov NxtSymPtr,bx
- sub NxtSymPtr,3 ;point to start of entry, the addr
- inc bx ;string pointer to return
- or ch,ch ;clears carry flag, too
- jz EOT ;ret w/carry if end of table
- push bx
- mov al,ch
- call AddALtoBX ;point to next label's address
- mov dx,[bx]
- mov NxtSymAddr,dx
- pop bx
- clc
- jmp short EndSymlook
-
- EOT: stc
- EndSymlook:
- pop dx
- ret ;with carry if end of table
- ;--------------------------------
-
- ;ENTER A LABEL (SYMBOL)
- cmentr: mov bx,offset cmdbuf+3 ;1st byte after the E
- call gtval ;label (pcntr, not ORG) address to DX
- mov al,[bx]
- call delim ;comma or space must exist
- inc bx
- mov al,[bx]
- cmp al,'.'
- jz DotIsThere ;dot must prefix label text
- call cmerr
-
- DotIsThere:
- push dx ;label pcntr address
- push bx ;cmdbuf pointer to '.'
- call LblChk ;checks permissible characters
- ;be sure label doesn't exist
- call locsym
- jb nohit
- call prtstr
- db 'Label already exists...',cr,lf,0
- jmp nxcmd
-
- nohit: mov ChgFlag,1 ;for 'Update/Exit'
- pop bx ;cmdbuf pointer to '.'
- pop dx ;label pcntr address
- push dx
- push bx
- call symluk ;is there a label at this addr?
- jc symnf ;jmp if not
- push bx
- call CrLf
- call PrtCHbytesPerBX
- call prtstr
- db ' was killed',7,cr,lf,0
- pop bx ;from symluk, >1st of text
- dec bx
- dec bx
- mov al,[bx] ;type byte of found label
- mov OprndType,al ;to be same for replacement label
- dec bx
- dec bx
- call lkill
- symnf: pop bx ;orig cmdbuf pointer
- call LblChk ;BX > 1st char in label, CH = chars
- pop dx ;label address
- call symtch ;puts label in table at DX
- jmp nxcmd
- ;--------------------------------
-
- cmkill: mov bx,offset cmdbuf+3 ;1st byte after the K in command
- mov al,[bx]
- cmp al,'.'
- jz l2396
- call cmerr
-
- l2396: call LblChk
- call locsym
- jnc l23a1 ;found it
- call cmerr
-
- l23a1: call lkill
- jmp nxcmd
-
- lkill: mov cx,bx
- inc bx
- inc bx
- inc bx
- mov al,[bx]
- sub ah,ah
- add bx,ax
- inc bx
- xchg bx,dx ;hold in dx
- mov bx,symtp
- l23b8: cmp dx,bx ;at top yet?
- jz l23d5
- xchg bx,dx
- mov al,[bx] ;from [dx]
- xchg bx,dx
- xchg bx,cx
- mov [bx],al ;to [cx]
- xchg bx,cx
- inc cx
- inc dx
- jmp l23b8
-
- l23d5: mov bx,cx
- mov symtp,bx ;new top
- mov byte ptr [bx+3],0
- ret
- ;--------------------------------
- ;enter with BX > dot before label. Exit CH = chars in label
- ;returns BX > 1st char of label, DX > 1st char after label
- LblChk: inc bx ;skip dot symbol flag
- xor ch,ch ;clear length counter
- push bx ;save string start pntr
- mov al,[bx] ;get first char
- ;for 1st char only:
- cmp al,cr
- jz LblErr
- cmp al,'.' ;period allowed only as 1st char
- jz nxtcnt
- cmp al,'$' ;weed
- jz nxtcnt ; out
- cmp al,'9'+1 ; digits in 1st char
- jc LblErr
- nxtcnt: inc bx ;starts with 2nd char
- inc ch ;bump the count
- mov al,[bx]
- cmp al,cr ;label ends at a CR,
- jz endcnt
- cmp al,',' ; or a comma
- jz endcnt
- cmp al,'$'
- jz nxtcnt
- cmp al,'_'
- jz nxtcnt
- cmp al,'0'
- jb LblErr
- cmp al,'9'+1
- jb nxtcnt
- cmp al,'?'
- jae nxtcnt
- cmp al,'Z'+1
- jb nxtcnt
- LblErr: call prtstr
- db 7,cr,lf,'Period only as 1st character'
- db cr,lf,'0-9 must not be 1st character'
- db cr,lf,'Also allowed are $ ? _ @',cr,lf,0
- jmp nxcmd
-
- endcnt: mov dx,bx ;delimiter ptr to DX
- pop bx ;string start pointer
- ret
- ;--------------------------------
- StoreHex:
- push ax ;AL to 2 hex chars [BX]
- call hexl
- mov [bx],al
- inc bx
- pop ax
- call hexr
- mov [bx],al
- inc bx
- ret
-
- hexl: shr al,1 ;move hi nibble to lo nibble
- shr al,1
- shr al,1
- shr al,1
- hexr: and al,0Fh
- cmp al,0Ah
- jb hexrn
- add al,7
- hexrn: add al,'0' ;30h, make ASCII
- ret
-
- ;print AL with leading zero if 0Ah or above
- xo0: cmp al,0A0h
- jnb Leading0
- jmp xo
-
- Leading0:
- push ax
- mov al,'0'
- call typech
- pop ax
- xo: push ax
- call hexl
- call typech
- pop ax
- call hexr
- jmp typech
-
- Print00BX_: ;with leading zeros and trailing space
- mov al,bh
- call xo
- mov al,bl
- call xo
- prspc: mov al,' '
- jmp typech
-
- ;--------------------------------
- ;GET USER INPUT NUMBERS (or no. equiv of label) from cmdbuf to DX
- gtval: mov al,[bx]
- cmp al,'.'
- jz GetSmbAddr
- mov dx,0
- hexbi: mov al,[bx]
- cmp al,'0' ;30h
- jnb NumContinues
- ;it's a punctuation mark, the no. has ended
- sub dx,curorg ;correct address for ORG (pcntr always wrt 0)
- ret ;w/carry set if DX less than 0
-
- NumContinues:
- cmp al,'9'+1 ;3ah
- jb cvnum
- cmp al,'A' ;41h
- jnb l2468
- ret
-
- l2468: cmp al,'G'
- jb l246d ;thru F it's a Hex character
- ret
-
- l246d: sub al,7
- cvnum: sub al,'0' ;30h
- xchg bx,dx
- add bx,bx
- add bx,bx
- add bx,bx
- add bx,bx
- add al,bl
- mov bl,al
- xchg bx,dx
- inc bx ;point to next char
- jmp hexbi ;back near start of this routine
-
- GetSmbAddr: ;now BX > the dot before the label
- call LblChk ;rets w/DX > delimiter (CR or comma after lbl),
- push dx ; BX > 1st char of label and CH = bytes in lbl
- call locsym
- jnc l2491 ;it exists
- pop dx
- call prtstr
- db cr,lf,'Label not found',7,cr,lf,0
- jmp nxcmd
-
- l2491: mov dx,[bx] ;symbol value
- pop bx ;was DX
- mov al,[bx] ;string terminator
- ret
- ;--------------------------------
- fopen: push bx
- mov ah,3Dh ;open file w/handle to AX
- mov al,2 ;read/write
- mov dx,offset FileString
- int 21h
- mov Handle,ax
- mov DTAptr,100h ;so GetByte will first fill buffer
- pop bx
- ret ;w/no carry if successful
-
- OpenError:
- call prtstr
- db tab,tab,tab,'FILE NOT FOUND',0
- stc
- ret
- ;--------------------------------
- ;read a byte from the buffer at old DTA, read in 128 bytes if empty
- GetByte:
- push bx
- mov bx,DTAptr ;was set to 100h at fopen
- test bh,1 ;AND, tests bit 0, so NZ 1st pass
- jz StillGotSome ;DTAptr has NOT passed 0100h, end of buffer
- ;refill the 'DTA'
- push cx
- push dx
- mov cx,128 ;bytes to read
- mov bx,Handle
- mov dx,DefaultDTA ;equ 80h, in the PSP
- mov ah,3Fh ;read w/handle
- int 21h
- jnc CtuXX
- jmp ReadErr
- CtuXX: or ax,ax
- jz mrkeof ;EOF has been read
- pop dx
- pop cx
- mov bx,DefaultDTA ;equ 80h
-
- StillGotSome:
- mov al,[bx]
- inc bx
- mov DTAptr,bx
- pop bx
- ret
-
- mrkeof: mov bx,DefaultDTA
- mov al,1Ah
- mov [bx],al
- jmp StillGotSome ;now will RET w/AL=1Ah
-
- ;--------------------------------
- creatf: push bx
- mov ah,3Ch ;create file w/handle
- push cs
- pop ds ;just to be sure
- mov dx,offset FileString ;DS:DX points to ASCIIZ string
- xor cx,cx ;attribute = normal file
- int 21h
- jc CreateErr
- mov Handle,ax
- mov DTAptr,DefaultDTA ;equ 80h
- pop bx
- ret
-
- CreateErr:
- push ax
- call prtstr
- db cr,lf,'Error creating file: Func 3Ch, AX returned ',0
- pop bx
- call Print00BX_
- call prtstr
- db 'hex',cr,lf,0
- jmp nxcmd
-
- ;--------------------------------
- WriteNclose:
- mov al,1Ah
- call WriteChar ;add EOF to file
- mov cx,DTAptr ;points 1 past the EOF char
- sub cx,DefaultDTA ;now cx = bytes to write
- call DumpDTA
- fclose: push bx
- mov ah,3Eh ;close file w/handle
- mov bx,Handle
- int 21h
- pop bx
- ret
-
- CloseErr:
- call prtstr
- db 'ERROR closing file (DOS func 3Eh)',cr,lf,0
- jmp nxcmd
-
- DiskFull:
- call prtstr
- db 'Oh, phooey the disk is full !!',cr,lf,0
- jmp nxcmd
-
- WriteChar:
- push cx
- push bx
- mov bx,DTAptr
- mov [bx],al
- inc bl
- mov DTAptr,bx
- pop bx
- mov cx,128 ;bytes to write
- jnz WrChRet
- call DumpDTA ;DTAptr just rolled past 0FFh
- WrChRet:
- pop cx
- ret
-
- DumpDTA: ;called by WriteNclose, too
- push dx
- push bx
- mov bx,Handle
- mov dx,DefaultDTA ;equ 80h, in the PSP
- mov ah,40h ;write to file w/handle
- int 21h
- jc WriteErr ;stack is reset by NXCMD, don't worry
- cmp ax,cx ;bytes written - bytes requested
- jnz DiskFull
- mov bx,DefaultDTA ;equ 80h
- mov DTAptr,bx ;reset pointer to start of DTA
- pop bx
- pop dx
- ret
-
- WriteErr:
- push ax
- call prtstr
- db cr,lf,'Error writing file: Func 40h, AX returned ',0
- pop bx
- call Print00BX_
- call prtstr
- db 'hex',cr,lf,0
- jmp nxcmd
-
- ;--------------------------------
- ;called after every line
- NewLine:
- mov LongFlag,0
- mov bx,AppendPtr
- or bx,bx
- jz NewLine2
- call PrtTab
- mov ch,[bx]
- or ch,ch ;zero-length remark ?
- jz NewLine2 ;if so, do nothing
- PrtAppendedRem:
- inc bx
- mov al,[bx]
- call typech
- dec ch
- jnz PrtAppendedRem
- NewLine2:
- mov AppendPtr,0
- UnasmCrLf:
- mov al,CurInstr ;check opcode for JMP, RET, etc for blank line
- cmp al,0C3h
- jz SkipAline
- cmp al,0E9h ;2-byte jmp in segment, also used by
- ; CALL, etc to force blank line.
- jz SkipAline
- cmp al,0EBh ;jmp short
- jz SkipAline
- cmp al,0C2h ;ret in seg, add immed to SP
- jz SkipAline
- cmp al,0CAh ;ret far, add immed to SP
- jz SkipAline
- cmp al,0CBh ;ret far
- jz SkipAline
- cmp al,0CFh ;iret
- jz SkipAline
- cmp al,0EAh ;jmp far
- jz SkipAline
- cmp al,0E2h ;LOOP
- jz SkipAline
- CrLf: mov al,cr
- call typech
- mov al,lf
- jmp typech
-
- SkipAline:
- call CrLf
- mov al,' '
- mov CurInstr,al ;why ??
- jmp CrLf
-
- ;--------------------------------
- ;GET COMMAND from the keyboard
- gtcmd: mov UpCaseFlag,1 ;assume command is not ; or E
- mov bx,offset segsho ;prompt string
- mov ch,3 ;no. of characters
- call PrtCHbytesPerBX
- xor dh,dh ;clear the byte count
- mov bx, offset cmdbuf
- inc bx
- inc bx ;for compatibility, start @ cmdbuf+2
- nexkey: mov ah,0 ;read next kbd char into AL
- int 16h
- or al,al ;check for non-ASCII key
- jnz NoSpl
- jmp splkey
- ;now change lower to upper-case if reqd. First, check for ';', comma, or '.'
- NoSpl: cmp al,','
- jz LoCaseOK
- cmp al,'e'
- jz LoCaseOK
- cmp al,'E'
- jz LoCaseOK
- cmp al,';'
- jz LoCaseOK
- UpCaseIt:
- cmp UpCaseFlag,0
- jz uc2cmd
- call CapitalizeAL
- uc2cmd: cmp al,' '
- jnz NotSpace
- cmp byte ptr cmdbuf+2,';'
- jz NotSpace
- jmp BeepBeep ;space allowed only in Remarks
- NotSpace:
- mov [bx],al ;put char in cmdbuf
- mov ah,0Eh ;show on screen and move cursor
- int 10h
- cmp al,cr ;ENTER hit?
- jnz noentr
- mov byte ptr ds:[cmdbuf+1],dh ;like func 0A, byte count to 2nd byte
- jmp CrLf ;vector to command routines
-
- CapitalizeAL:
- cmp al,'a'
- jb Nope
- cmp al,'z'+1
- jnb Nope
- and al,5Fh ;converts to Upper-case
- Nope: ret
-
- LoCaseOK: ;char is ; or e or E or comma
- cmp al,','
- jz DoComma
- or dh,dh ;first char E or ; ?
- jnz UpCaseIt
- mov UpCaseFlag,2 ;flag next comma turn off upper case
- jmp short UpCaseIt
-
- DoComma:
- cmp UpCaseFlag,2
- jnz UpCaseIt
- mov UpCaseFlag,0
- jmp short UpCaseIt
-
- noentr: cmp al,8 ;check for backspace
- jnz nobksp
- or dh,dh ;is cursor at left end of field?
- jnz goback
- mov al,segsho[2] ;bksp put cursor on last of arrow
- mov ah,0Eh ;so replace it & move cursor back up
- int 10h
- jmp nexkey
-
- goback: dec dh
- jnz NotTheFirst
- mov UpCaseFlag,1 ;must have erased 1st char
- NotTheFirst:
- dec bx
- mov al,' '
- mov ah,9 ;write char at cursor, no move cursor
- mov cx,1 ;no of reps
- push bx ;must save BX
- mov bx,7 ;page=0, attrib=normal wht on blk
- int 10h
- pop bx
- jmp nexkey
-
- nobksp: cmp al,'Q' ;Quit ?
- jnz NotQ
- cmp byte ptr [bx-1],1Bh ;was previous char ESC ?
- jnz NotQ
- jmp cmexit ;Update/Exit w/Errorlevel 0
- NotQ: or dh,dh ;is this the 1st char entered ?
- jnz NotP
- cmp al,'P'
- jnz NotP
- ;set new d:\path\name to save to
- mov si,offset FileString
- PathLoop:
- inc dh
- inc bx
- lodsb
- cmp al,'.'
- jz ToNexKey
- or al,al
- jz ToNexKey
- mov [bx],al
- mov ah,0Eh
- int 10h ;show on screen and move cursor
- jmp short PathLoop
-
- ToNexKey:
- jmp nexkey
-
- NotP: cmp al,'='
- jnz NotEqSign
- cmp byte ptr [bx-1],'U' ;doing U= (set lines to Unasm) ?
- jnz NotEqSign
- call prtstr
- db '(hex)',0
- NotEqSign:
- inc dh ;bump byte counter
- inc bx ;bump cmdbuf pointer
- jmp nexkey
-
- ;key was non-ASCII (AL was 0, so AH holds special scan code)
- splkey: cmp ah,51h
- jz PgDn
- cmp ah,50h ;down arrow
- jnz nodnar
- jmp downar
- nodnar: cmp ah,49h
- jz PgUp
- cmp ah,84h ;ctrl-pgup
- jz ctlpup
- cmp ah,43h ;F9 key
- jnz notF9
- call sav_em
- jmp nxcmd
-
- notF9: cmp ah,3Bh ;F1 key
- jnz ToNexKey
- jmp cmhelp
-
- PgDn: cmp hlpflg,0 ;are we in Help?
- jnz yeshlp
- ;what did we do last ?
- cmp byte ptr cmdbuf+2,'D' ;are we in Dump or DS ?
- jnz to_Udown
- cmp byte ptr cmdbuf+3,'S' ;did we just dump sym table ?
- jz to_Udown
- mov byte ptr cmdbuf+3,cr ;set up cmdump to continue last dump
- call prtstr ;start header at beginning of line!
- db cr,0
- jmp cmdump
-
- to_Udown:
- jmp Udown
-
- yeshlp: mov al,helpno
- inc al
- cmp al,3 ;3 screens, no 2 is last
- hlpend: jz BeepBeep
- mov helpno,al
- call CrLf ;keeps cmd line off display
- jmp cmhelp
-
- BeepBeep:
- call prtstr
- db 7,0 ;BEL, makes a beep
- ToNexKey2:
- jmp nexkey
-
- PgUp: cmp hlpflg,0
- jnz helpup
- jmp nexkey
-
- helpup: mov al,helpno
- dec al
- cmp al,0FFh ;AL was 0
- jmp short hlpend
-
- ctlpup: cmp byte ptr cmdbuf+2,'D' ;are we in Dump?
- jnz Ustart
- cmp byte ptr cmdbuf+3,'S' ;did we just DS (dump sym table) ?
- jz Ustart
- mov bx,dmpcnt
- mov DumpEnd,bx ;dump a full page
- mov DumpStart,0 ;start at 0 + ORG
- jmp dmphdr
-
- downar: mov ah,byte ptr cmdbuf+2 ;find out what we last did
- cmp ah,'A'
- jz onelin
- cmp ah,'B'
- jz onelin
- cmp ah,'U'
- jz onelin
- cmp ah,'D'
- jnz ToNexKey2
- cmp byte ptr cmdbuf+3,'S'
- jz ToNexKey2
- ;cmdbuf holds D but not DS, so Dump one more line of hex code
- add DumpEnd,16
- call prtstr
- db cr,0
- jmp cntdmp
-
- onelin: mov al,1
- jmp short DoALlines
-
- Ustart: call CrLf
- mov pcntr,0
- mov AmodeFlag,0 ;turn off A and
- mov BmodeFlag,0 ; B mode
- Udown: mov byte ptr cmdbuf+2,'U' ;for down arrow
- mov al,LnsPerScreen
- DoALlines:
- mov wfiflg,0 ;no write file, default for TwentyLines
- mov LinesToGo,al
- mov LCountFlag,al ;do specific line count
- call prtstr
- db cr,0 ;so will overwrite the '══'
- jmp TwentyLines
-
- ;F9 has been hit, save the .REM, .SMB, and .CTL files
- sav_em: call ChkNoFSpec ;save as 'SEG_nnnn.xxx' if doing RAM
- cmp ASMopenFlag,0
- jz ok2sav
- jmp ASMstillOpenErr
- ok2sav: jmp SaveAll ;resets ChgFlag
-
- ;--------------------------------
- ;Print ASCIIZ string (ends in 0) following call, to screen/both. Saves AX,BX,DX.
- prtstr: mov wfiflg,0 ;output to screen only, not file
- pstg: pop si ;get RET addr (of byte past call)
- xchg bx,si
- push si ;now BX points to byte after call
- push ax
- ostrlp: mov al,cs:[bx]
- call typech ;print at least one char - saves DX
- inc bx
- mov al,cs:[bx]
- or al,al
- jnz ostrlp ;loop if not 0
- pop ax
- inc bx
- pop si
- xchg bx,si ;BX & DX saved
- push si ;make RET addr the byte after the 0
- ret
-
- ;--------------------------------
- ;Print [AL] to screen and/or output file buffer as req'd
-
- typech: inc strcnt ;for ASCII lines
- push ax
- push cx
- push dx
- push bx
- mov dl,al ;the character to print
- push dx
- push es
- mov ah,2 ;display the character in DL
- int 21h
- pop es
- pop dx
- mov al,ASMopenFlag
- and al,wfiflg
- mov al,dl
- jz l25d8 ;jump if both wfiflg and ASMopenFlag are 0
- call WriteChar ;write to file buffer
- l25d8: mov al,dl
- cmp al,lf
- jnz notlf
- ;character was Line Feed
- cmp LCountFlag,0
- jz notlf
- dec LinesToGo
- notlf: pop bx
- pop dx
- pop cx
- pop ax
- ret
- ;--------------------------------
-
- ClearTables:
- mov bx,symbas
- mov byte ptr [bx+3],0 ;zero size byte
- mov symtp,bx ;top = bottom
- mov byte ptr cmdbuf+3,0Dh ;null command [shouldn't this be +2 ???]
- mov cfence,'I' ;initial mode=Instrs (cfence=ctlbas-1)
- mov al,segsho
- mov byte ptr ctlbas,al ;1st byte of prompt arrow initially
- mov word ptr ctlbas+1,0FFFFh ;end flag for addr's in .CTL table
- mov bx,offset ctlbas+0C00h
- mov ctltop,bx ;max length of ctl table 3K bytes
- mov bx,remtbl ;set at start of pgm to REMBAS
- mov remend,bx ;end = start
- mov word ptr [bx],0FFFFh ;end marker
- mov Direc286Flag,0
- ret
-
- ;--------------------------------
- ;case-INsensitive string compare, [BX] & [DX], CL=length. Z set => match.
- cmpstr: push bx
- push cx
- CmpStrLoop:
- xchg bx,dx
- mov al,[bx] ;get [DX] byte
- call CapitalizeAL
- mov ah,al
- xchg bx,dx
- mov al,[bx]
- call CapitalizeAL
- cmp al,ah ;compare w/[BX] byte
- jz Match
- jmp short CmpEnd ;w/NZ
-
- Match: inc dx
- inc bx
- dec cl ;bytes to compare
- jnz CmpStrLoop
- CmpEnd: pop cx
- pop bx
- ret ;w/Z set if match
-
- ;--------------------------------
- BreakChk:
- push cx
- push dx
- push bx
- mov ah,0Bh ;check for kbd input
- int 21h
- or al,al
- jz NeverMind ;if no character is available, ret
- mov ah,1 ;kbd input w/echo to screen
- int 21h
- cmp al,3 ;ctrl-C
- jz abort
- call CrLf
- jmp nxcmd
-
- abort: call prtstr
- db cr,lf,'ABORT Y/N ',0
- mov ah,1 ;kbd input w/echo to screen
- int 21h
- and al,5Fh ;make Upper-Case
- cmp al,'Y'
- jnz NotExit
- mov ah,4Ch
- mov al,1 ;Errorlevel = 1
- int 21h ;normal terminate
-
- NotExit:
- jmp nxcmd
-
- NeverMind:
- pop bx
- pop dx
- pop cx
- ret
- ;--------------------------------
- ;test for DB (cr, lf, 0, tab, bel, space thru 7Fh) - no carry if ASCII
- ;called twice, with al=es:[bx]
- IfASCII:
- cmp al,cr
- jnz Not0Da
- ret
-
- Not0Da: cmp al,lf
- jnz Not0Aa
- ret
-
- Not0Aa: or al,al
- jnz Not0a
- ret
-
- Not0a: cmp al,tab
- jnz NotTa
- ret
-
- NotTa: cmp al,bel
- jnz NotBel
- ret
-
- NotBel: cmp al,' ' ;20h
- jnb SpaceOrAbove
- ret
-
- SpaceOrAbove:
- cmp al,3Ch ;code for CMP AL
- jnz NotCMP
- mov ah,es:[bx+2]
- cmp ah,70h ;Jxx lowest code
- jb NotCMP
- cmp ah,7Ah ;Jxx highest code
- ja NotCMP
- ;char is 3Ch and 2nd char following is a Jxx instr
- stc
- ret
-
- NotCMP: push di
- mov ah,al
- and ah,11110000b
- cmp ah,01010000b
- jnz NotPushOrPop
- ;are next 4 chars also PUSH or also POP ?
- mov ah,al
- and ah,11111000b ;mask for all PUSH and POP instr's
- mov di,4
- PPloop: push ax
- mov al,es:[bx+di]
- and al,11111000b
- cmp ah,al
- pop ax
- jnz NotPushOrPop
- dec di
- jnz PPloop
- stc
- pop di
- ret
-
- NotPushOrPop:
- cmp al,7Fh ;thru 7Eh is ASCII
- cmc
- pop di
- ret
- ;--------------------------------
-
- curorg dw 0 ;ORG address
- curpar dw 0 ;para (segment) of target pgm loaded
- segsiz dw 0 ;bytes in current segment (not used now)
- DumpStart dw 0 ;dump start addr
- DumpEnd dw 0100h ;dump end addr
- symtbl dw symbas ;addr of symbol table start
- symtp dw symbas ;addr of symbol table end+1 (ie, 1st free byte)
- pcntr dw 0 ;true program counter for Unassemble, etc.
- lastwd dw 0100h ;end addr for U, input by user
- curadr dw 0 ;pgm pointer during disassy
- ctltbl dw offset ctlbas ;control (BEHIS or W) table start addr
- ctltop dw 0 ; and end addr
- SearchPointer dw 0
- fndadd dw 0
- dmpcnt dw 0FFh
- lblbuf db 'H0XXXX' ;used to build up label in Build Symbol Table
- PgmParas dw 0 ;size of loaded pgm in paras
- PgmBytes dw 0,0 ;doubleword, lo-hi
- ParasRead dw 0 ;for loading files > 64K, points buffer para
-
- ;This table erased by erstbl in LoadPGM (load .COM file)
- cstbl db ' '
- dw 0,0,0,0
- cofset dw 0 ;default
- db ' '
- dw 0,0,0,0
- dw 0 ;default
- db ' '
- dw 0,0,0,0
- dw 0 ;default
- db ' '
- dw 0,0,0,0
- dw 0 ;default
- db ' '
- dw 0,0,0,0
- dw 0
- db ' '
- dw 0,0,0,0
- dw 0
- db ' '
- dw 0,0,0,0
- dw 0
- db ' '
- dw 0,0,0,0
- dw 0
- db 0 ;table end flag
- ;end of table erased by erstbl
-
- segnam dw 5343h ; 'SC' for CS, etc
- dw 5344h ; 'SD'
- dw 5345h ; 'SE'
- dw 5353h ; 'SS'
- dw 5831h ; 'X1'
- dw 5832h ; 'X2'
- dw 5833h ; 'X3'
- dw 5834h ; 'X4'
-
- FileString db 'D:'
- db 81 dup(0)
- DotPtr dw 0 ;pointer to the . before the EXT
- Handle dw 0 ;File Handle for load & save routines
- LitRSM db 'RSM',0 ;literals for file types
- LitCOM db 'COM',0
- LitEXE db 'EXE',0
- LitSYS db 'SYS',0
- LitCTL db 'CTL',0
- LitSMB db 'SMB',0
- LitREM db 'REM',0
- LitALL db 'ALL',0
- SEG_string db 'SEG_',cr ;for name of saved files doing RAM
-
- EXTflag db 0 ;.EXT of loaded file, C=.COM, E=.EXE
- hlpflg db 0
- helptr dw offset help
- dw offset extnd_help
- dw offset instrs
- helpno db 0 ;which help screen to display
- NxLblPtr dw 0 ;stores BX in Dump Symbol table
- AppendPtr dw 0 ;temp pointer to Appended remark while Unasm'ing line
- Control db 0 ;temp CTL char to insert when Attempting to find DB's
- nxtctl dw 0 ;addr of next CTL change, to end Byte & Hex lines
- NxtSymAddr dw 0 ;when not at end of table, addr of next label and
- NxtSymPtr dw 0 ; pointer to 1st byte of next entry in SYM table
- EndSameAddr dw 0 ;in S mode, next non-Same or CTL or SMB addr
- DTAptr dw 0 ;pointer in buffer for disk read/writes
- segsho db 205,205,16 ;command prompt string '══'
- UpCaseFlag db 1 ;zero permits lower-case for remarks & labels
- nrsegs db 0 ;number of segments loaded
- trmflg db 0 ;trim flag, 1= don't show ;addrs for labels
- SegOvrdPfx db 0 ;segment override prefix
-
- segflg db 0 ;segment req in current command (not now used)
-
- OprndType db 0 ;upper nibble = seg type, S D E C = 0 1 2 3,
- ; lower = Undefined, Byte, Word, Dword(Qword, Spaces)
- RelFlag db 0 ;line addr or rel disp instr, don't correct for CurOrg
- Direc286Flag db 0 ;1 = put '.386P' in .RSM, '186+ instrs in file
- LnsPerScreen db 22 ;lines per screen of Unassembly
- LinesToGo db 10 ;lines left to Unassemble on this screen
- LCountFlag db 1 ;0 for U B or A,EEEE to end addr, not line count
- wfiflg db 0 ;0 means don't print to file, just screen
- ASMopenFlag db 0 ;.RSM file still open, close it before writes
- REMflag db 0 ;1 => doing REM, not SMB file operation
- CurInstr db 0 ;current op code during unassembly
- CurModRegRM db 0 ;current Extended Address byte of instr
- LongFlag db 0 ;current instr is a long '286
- strcnt db 0 ;no of chars on ASCII Byte or Hex lines
- EntriesLeft db 0 ;count of displayed labels in DS and Ctl list
- BytesFlag db 0 ;flag line is Bytes ASCII, not Hex
- ChgFlag db 0 ;flag change made for 'Update/Exit' in CmExit
- OutsideFlag db 0 ;in .RSM hdr, flag 'Labels Outside Pgm' printed
- CrLfFlag db 0 ;in ASCII strings, last byte was cr, lf, or 0
- ColonFlag db 0 ;flag for colon after labels
- NoCommentAddr db 0 ;flag no ;0123 after label in oprnd
- AmodeFlag db 0 ; 1 => Attempt find DB's mode
- BmodeFlag db 0 ; 1 => Build symbol table mode
- typndx db 0,0,0
- cmdbuf: org offset $+336
- stak dw 0 ;machine stack top
- remtbl dw 0 ;loaded w/remark table start addr
- remend dw 0 ; and end addr
- cfence db 0 ;this is ctlbas-1, holds BEHISW for 1st line
- ctlbas db 0 ;start of enough room for 768 items, 4 bytes each
-
- start endp
- cseg ends
- end start