📄 asm.asm
字号:
lodsb ;consume the bracket
mov al,[di+asmop.areg1] ;see if any segment reg
cmp al,0ffh
jz brklp ; none
mov [di + asmop.areg1],0ffh ; set it back
sub ah,ah
bts [PrefixBitmapWord],ax ; set the prefix bit
brklp:
call wadespace ;get next string
jz brackerr ;found CR before closing bracket
cmp al,'+' ;see if plus sign
jne brnp ;might mean bracket-not-plus
inc si ;else move past plus sign
call wadespace ;and find next
jz brackerr ;oops, no closing bracket
;We have ignored any plus sign if it was there
brnp:
cmp al,'-' ;is it a minus sign?
je brmem ;if so, must be a value?
cmp al,']' ;if not, closing bracket already?
je brackx ;if so, go exit
push di ;save pointer to buffer
mov di,offset arg4 ;point to arg4 for base-mode reg gathering
call parsereg ;see if a register?
pop di ;restore buffer pointer
;parsereg cannot return CY, and does no bracket check anyway. No idea why
;this line is even here
jc brackerr ; if invalid fp or CRDRTR reg num
jz brreg ;ZF means we found a register
brmem:
call parseval ;glom a number into EBX
jc brackerr ;get out if no number
add [di+asmop.addrx],ebx ;stick in as offset or segment
call WadeSpace ;get next
jz brackerr ;still no closing bracket
jmp brklp ;else get next bracket value
;We get here if we found a named register inside the brackets, like [bx
brreg:
mov [di+asmop.mode],AM_BASED ;say base reg involved
mov ah,[arg4.areg1] ;get which register it is
mov bl,[arg4.asize] ;and width of register
test [di+asmop.msize],0FFh ;see if anything assigned yet
jz notszyet ;nope, not yet
cmp [di+asmop.msize],bl ;ok, bl is the size
jnz brackerr ;mismatch, I guess???
notszyet:
mov [di+asmop.msize],bl ;else set the size
call WadeSpace
cmp al,'*' ;multiply operation
jne notscale ;nope, no scaling
cmp bl,DWORDSIZE ;else dword scaling?
jne brackerr ;must be dword reg for multiply?
inc si ;move past *
call WadeSpace ;find next
sub al,'0' ;last char returned, cvt to decimal?
cmp al,TIMES1 ;*1 is OK
je brackok1
cmp al,TIMES2 ;*2 is OK
je brackok1
cmp al,TIMES4 ;*4 is OK
je brackok1
cmp al,TIMES8 ;*8 is OK
jne brackerr ;else, can't do it
brackok1:
inc si ;bump SI past scaling factor
mov byte ptr [di+asmop.ascale],al ;and set factor in struct
reg2x:
test [di+asmop.areg2],0FFh ;initialized to FF
jns brackerr ;so bit 7 better be set
mov [di+asmop.areg2],ah ;if so stick areg1=reg into it
jmp brklp ;get next thing inside brackets
;Found a register that was NOT followed by a scaling factor. The magic code
;for the found register is in AH. We stick this register into areg1 unless
;areg1 is already in use, in which case we stick it in areg2.
notscale:
test [di+asmop.areg1],0FFh ;has reg been assigned yet?
jns reg2x ;if not, stick reg into areg2
mov [di+asmop.areg1],ah ;else, stick reg into areg1
jmp brklp
;OK, we found the closing bracket. Presumably everything between brackets
;was kosher. We also get here with the construct [], with nothing in there.
brackx:
cmp [di+asmop.msize],DWORDMODE ;addressing mode size=32?
jne brackn32 ;if not, skip
or [PrefixBitmapWord],AS_ADDRSIZE ;else set addrsize prefix flag
brackn32:
inc si ;move past ]
cmp [di+asmop.mode],AM_NONE ;see if empty
Jne gaxc ;if not, cool
mov [di+asmop.mode],AM_MEM ;else set mode to memory
mov [di+asmop.msize],WORDMODE ;see if word mode
test [di+asmop.addrx],NOT 0FFFFH ;see if any address
jz gaxc ;if not, skip out
or [PrefixBitmapWord],AS_ADDRSIZE ;else set for ???
mov [di+asmop.msize],DWORDMODE ;and say dword assumed??
jmp gaxc ;and jmp
brackerr:
stc
ret
parsearg ENDP
; Parse possible control register reference
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: For this arg, the mode and areg1 fields of the structure are
; filled in.
; NZ if we can't recognize the register
; CY if index for register is out of range
; PROCESSING: Look for any control reg, debug reg, FP reg or TR reg. The
; TR regs are the Appendix H test registers.
; Beyond this, we allow up to 8 of each of the ST, CR and DR
; even though there is no DR1 or DR2, nor any CR4,5,6 or 7. I guess
; these exist in opcode space, just not in the CPU!
;
parsecontrol PROC
mov ax,word ptr [si]
mov cl,AM_CR
cmp ax,"rc" ;Control register CRx
je gotcontrol
mov cl,AM_DR
cmp ax,"rd" ;Debug register DRx
je gotcontrol
mov cl,AM_TR
cmp ax,"rt" ;Test registers, Appendix H
je gotcontrol
cmp ax,"ts" ;ST(x for FP
je gotfpreg
or al,1
ret
;Um. There are 8 each of the debug registers and FP stack registers, although
;DR1 and DR2 don't exist. There are only 4 control registers, and I can't
;find any reference at all to any TRx registers.
gotcontrol:
lodsw ;grab control reg 1st 2 chars
lodsb ;and number
sub al,'0' ;convert to binary
jc gcerrx ;oops, below 0
cmp al,8 ;see if register 8 or above
jae gcerrx ;error if so
mov [di+asmop.mode],cl ;save CL
mov [di+asmop.areg1],al ;save which one
sub ax,ax ;set ZF
ret
gcerrx:
stc
ret
gotfpreg:
lodsw ;consume the 'ST'
call wadespace ;find next
cmp al,'(' ;is it (
jne asmgotch ;if not, check for NASM syntax
inc si ;bump past (
call wadespace ;find next
push ax ;stack the char found
inc si ;move past it
call wadespace ;find the next
cmp al,')' ;end of stack reference?
pop ax ;restore char between ()
jne badfpreg ;no close, so bitch
;We get here in two cases: we found (x), or we didn't find (
;In the first case, x is in AL, in the second, AL has what we found instead
;By implication, we accept either ST(x) or STx
asmgotch:
inc si ;move to next position anyway
sub al,'0' ;convert to binary
jc badfpreg ;must be some number
cmp al,8 ;else see if in range
jae badfpreg ;if >=8, out of range
mov [di+asmop.mode],AM_FPREG ;set flag for FP
mov [di+asmop.areg1],al ;save binary value of this reg
sub ax,ax ;and return ZF
ret
badfpreg:
stc
ret
parsecontrol ENDP
;
; parse a size attribute. the PTR keyword is optional.
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: bl has size
; CY set if error ins size
parsesize PROC
mov ax,[PrefixBitmapWord] ;get bitmap into AX
call isbyte ;chk buffer for 'byte'
mov bl,BYTESIZE ;assume byte size
jz gotsize ;if match, fine
call isword ;else chk for word
mov bl,WORDSIZE ;assume it was
jz gotsize ;if so, fine
inc si ;go past first char (could be t)
call isbyte ;and check if it was 'tbyte'
jnz notbyte ;if not, really not a byte
cmp byte ptr [si-1],'t' ;else, was it a t
mov bl,TBYTESIZE ;assume it was a tbyte
jz gotsize ;yes, it was
or bl,bl ;else return NZ
ret
;OK, it's not 'byte', 'word' or 'tbyte'. Maybe it's 'dword'. To get here,
;SI has been moved past the first char, so see if it is dword, qword'or fword
notbyte:
call isword ;check for xword
jnz notsize ;nope, not it
mov al,[si-1] ;else get that x
cmp al,'d' ;was it dword
mov bl,DWORDSIZE ;assume it was
je gotsize ;yep, got it
cmp al,'q' ;was it qword
mov bl,QWORDSIZE ;assume it was
je gotsize ;yep, that's it
cmp al,'f' ;how about fword
mov bl,FWORDSIZE ;assume that
je gotsize ;yes
notsize:
dec si ;back to beginning of string
or bl,1 ;set NZ
ret
gotsize:
mov [di+asmop.asize],bl ;set requested size
add si,4 ;move past string in buffer
;By implication here, it is legal to type 'ptr' as many times as you want.
;You can say mov word ptr ptr ptr ptr ptr [44],5
gs2:
call wadespace ;find next nonspace
jz operrx ;didn't find, so error
cmp al,'[' ;'ptr' is optional, so chk bracket
je opok ;if so, fine
push si ;else look for 'ptr'
push di
mov cx,3
mov di,offset say_ptr
repe cmpsb
pop di
pop si
clc
jnz opok ;if not, we're ok
add si,3 ;else skip wasted 'ptr'
jmp gs2 ;
operrx:
stc
opok:
ret
parsesize ENDP
; compare input string with 'byte'
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: ZF if the argument is 'byte' NZ otherwise
; PROCESSING: Simply compare
; NOTE: AX must be preserved
;
isbyte PROC
push si
push di
mov cx,4
mov di, offset say_byte
repe cmpsb
pop di
pop si
ret
isbyte endp
;
; compare input string with 'word'
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: ZF if we matched 'word', else NZ
; PROCESSING: just compare
; AX cannot be modified
;
isword PROC
push si
push di
mov cx,4
mov di, offset say_word
repe cmpsb
pop di
pop si
ret
isword endp
;
; INPUT: SI points to buffer containing this argument (a string)
; OUTPUT: CY if bad segment argument
; ZF if good segment argument on its own
; In this case, mode and size are set
; SF if valid segment is followed by [
; PROCESSING:
; 1) See if string matches list of seg names, return NZ if not
; 2) See if segment is only arg (like mov ax,cs. If so, return ZF
; 3) Else, see if it is seg:[ and if so, return SF
; 4) Else return carry, bad segment argument
;
parseseg PROC
mov cx,6 ;6 possible segments by name
push di ;save ptr to struct
mov di,offset psegs ;names of registers
lodsw ;get what user entered
repne scasw ;find it in the strings list
pop di ;restore struct ptr
jz gotseg ;found a match
sub si,2 ;not a seg, undo the lodsw
ret ;return NZ
;Here we have a significant departure from debug.exe syntax. If you want
;a segment override in debug, you must put the override like CS: or ES:
;on a separate line, and the remainder on the next line. Debug requires you
;to say:
;xxxx:xxxx cs:
;xxxx:xxxx mov al,[44]
;
;Here you are NOT allowed to do this. Instead, you must enter:
;xxxx:xxxx mov al,cs:[44]
;
;an earlier part of the program also accepted:
;
;xxxx:xxxx cs:mov al,[44]
;
gotseg:
sub cx,6 ;sub starting value
not cx ;convert to index
mov [di+asmop.areg1],cl ;save that index in areg1
call wadespace ;find next non-0
jz segalone ;if nothing, fine, just seg
cmp al,':' ;else chk for colon
jne segalone ;if not, we just got the segment
inc si ;bump past colon
call wadespace ;find next stuff
jz segerr ;nothing else is error
cmp al,'[' ;do we have a fixed address next?
jne segerr ;if not, real trouble
or al,80h ;else return SF
ret
segalone:
mov [di+asmop.mode],AM_SEG ;say mode is just a segment
mov [di+asmop.asize],WORDSIZE ;so size is 2 (all segregs are word)
sub ax,ax ;return ZF
ret
segerr:
stc ;error so return CY
ret
parseseg ENDP
;
; parse a register name
;
; INPUT: SI points to input being parsed
; DI points to structure for this argument, or to arg4 if we are
; inside brackets.
; OUTPUT: ZF if reg found, and mode and size set
; NZ if not a name
; PROCESSING: parse for all register names, set size and mode if found any,
; else return NZ if not found
;NOTES:
; 1) If a register name was found, SI was bumped past it, else SI
; remained unmodified
; 2) At least one caller to this routine checks the carry. I can't
; find anything in here that would set or clear the carry as a
; return value...
;
parsereg PROC
mov bl,2 ;set word size
cmp byte ptr [si],'e' ;is first char an e
jne nextreg ;if not, fine
mov bl,4 ;else set dword size
inc si ;and move past the e
nextreg:
lodsw ;get next 2 bytes
mov cx,16 ;there are 16 2-char strings for regs
push di ;save di
mov di,offset regs ;to scan list of reg names
repne scasw
pop di
jz gotreg ;if ZF, we hit a match
sub si,2 ;else back to beginning of input
cmp bl,4 ;unless we moved past an e
jnz nextreg2 ;if bl=4, we did
dec si ;so back up to first char
nextreg2:
or si,si ;set NZ
ret ;since not a reg
;It just so happens that the regs string has 16 2-char entries, the first 8
;are byte registers and the last 8 are word registers
gotreg:
xor cl,15 ;really, how about 0Fh?
mov [di+asmop.asize],BYTESIZE ;say byte arg
cmp cx,8 ;if found in positions 0-7
jb gr1 ;then it was a byte
mov [di+asmop.asize],bl ;else word or dword depending on e
gr1:
and cl,7 ;get mod8 for index
mov [di+asmop.areg1],cl ;and save that
mov [di+asmop.mode],AM_REG ;say a reg asked for by name
sub ax,ax ;return ZF
ret
parsereg ENDP
;
; Make sure that the next string is a number, and return in EBX if so
;
; INPUT: SI points to string to be parsed
; OUTPUT: NC if we find a number
; EBX contains that number (0=extended if required)
; CY if not a number, or not found???
; PROCESSING: DI points to the argument structure being built, and must
; be preserved.
;NOTES: ReadNumber simply assumes that all bytes in the input buffer are
; hex values up to some special character like space, comma, colon
; or CR. So ReadNumber cannot return an error. In this case, we
; already know that we have no named register at [si], which is
; a good thing, because if we did, ReadNumber would return the
; current contents of that logical register.
;
parseval PROC
call wadespace ;find arg string
jz noval ;oops, not there
push di ;else save location
call ReadNumber ;read a number into eax
pop di ;restore pointer
mov ebx,eax ;return number in ebx
ret
noval:
stc
ret
parseval ENDP
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -