home *** CD-ROM | disk | FTP | other *** search
- ;
- ; GRDB
- ;
- ; Copyright(c) LADsoft
- ;
- ; David Lindauer, camille@bluegrass.net
- ;
- ;
- ; ASMOPS.ASM
- ;
- ; Function: Assembler operand parsers
- ;
- ;MASM MODE
- .MODEL SMALL
- .386
-
- include iasm.inc
- include easm.inc
- include iopcodes.inc
- include eopcodes.inc
- include eopcom.inc
- include eprints.inc
- include einput.inc
- include emtrap.inc
- include edispatc.inc
- include eoperand.inc
- include eoptions.inc
-
- PUBLIC AOP0, AOP1, AOP2, AOP3, AOP4, AOP5, AOP6, AOP7
- PUBLIC AOP8, AOP9, AOP10, AOP11, AOP12, AOP13, AOP14, AOP15
- PUBLIC AOP16, AOP17, AOP18, AOP19, AOP20, AOP21, AOP22, AOP23
- PUBLIC AOP24, AOP25, AOP26, AOP27, AOP28, AOP29, AOP30, AOP31
- PUBLIC AOP32, AOP33, AOP34, AOP35, AOP36, AOP37, AOP38, AOP39
- PUBLIC AOP40, AOP41, AOP42, AOP43, AOP44, AOP45, AOP46, AOP47
- PUBLIC AOP48, AOP49, AOP50, AOP51, aop52, AOP53, AOP54, AOP55
- PUBLIC AOP56, AOP57, AOP58
-
- .data
- base16c dw 0ff03h,0ff05h,0ff07h,0ff06h,0705h,0605h, 0703h,0603h
- dw 0ffffh,0ffffh,0ffffh,0ffffh,0507h,0506h, 0307h,0306h
-
- .code
-
- ;Check if arg1.asize is 4 or less. If greater, return error to caller's
- ;caller by mucking with the stack.
-
- intsize PROC
- cmp [arg1.asize],DWORDSIZE ;maybe this means the first argument
- ja rtnDirectlyToDispatcherWithCY ;can't exceed dword size
- ret
- intsize ENDP
-
- ;See if the mode field for this structure references a memory operand
- ;and return error to caller's caller if not
-
- chkmem PROC
- cmp [bx+asmop.mode],AM_MEM ;this is 3
- jne rtnDirectlyToDispatcherWithCY ;bomb if not memory operand
- ret
- chkmem ENDP
-
- ;See if the mode field for this structure references an immediate operand
- ;and return error to caller's caller if not
-
- chkimm PROC
- cmp [bx+asmop.mode],AM_IMM ;check if immediate
- jne rtnDirectlyToDispatcherWithCY ;if not, bomb
- ret
- chkimm ENDP
-
- ;See if the mode field for this structure references a segment
- ;and return error to caller's caller if not
-
- chkseg PROC
- cmp [bx+asmop.mode],AM_SEG
- jne rtnDirectlyToDispatcherWithCY
- ret
- chkseg ENDP
-
- ;This is a little more complicated. Let's hypothesize that chkregw is
- ;shorthand for checking a 16-bit register type opcode. In this case,maybe the
- ;opcode must contain more than a single byte. So before we check if it
- ;is a register-type opcode, we must make sure it has extra byte(s). So
- ;we stop here first, and if the length makes us happy, then we check mode
- ; Next guess - if this is a byte argument, we bomb since a word register
- ;requires a word operand.
-
- chkregw PROC
- cmp [bx+asmop.asize],BYTESIZE ;is this a byte opcode
- je rtnDirectlyToDispatcherWithCY ;if so, bomb
- jmp chkreg ;else check mode for register type
- chkregw ENDP
-
- ;Possibly this is used for in and out, where DX is the only register
- ;allowed?
-
- chkdx PROC
- cmp [bx+asmop.asize],WORDSIZE ;if not a word register
- jne rtnDirectlyToDispatcherWithCY ;then bomb
- cmp [bx+asmop.areg1],isEDX ;else see if DX register
- jne rtnDirectlyToDispatcherWithCY ;if not, bomb
- jmp chkreg
- chkdx ENDP
-
- ;Not sure about the AX part of this, since all that is being checked is
- ;a size of byte
-
- chkaxw PROC
- cmp [bx+asmop.asize],BYTESIZE ;if a byte register
- je rtnDirectlyToDispatcherWithCY ;then bomb
- chkaxw ENDP
-
- ;This IS a check for AX (actually, 0 is EAX)
-
- chkax PROC
- cmp [bx+asmop.areg1],0 ;if not EAX (maybe AX or AL)
- jne rtnDirectlyToDispatcherWithCY ;then bomb
- chkax ENDP
-
- ;Check for a register? As opposed to ??
-
- chkreg PROC
- cmp [bx+asmop.mode],AM_REG ;is this flag set?
- jne rtnDirectlyToDispatcherWithCY ;if not, bomb
- ret
- chkreg ENDP
-
- ;We bomb if arg3.mode isn't none, and if it is, we still bomb if arg2.mode
- ;is none. So arg3 is required to have a 'mode', whatever that is, I guess
-
- noarg3 PROC
- cmp [arg3.mode],AM_NONE
- jne rtnDirectlyToDispatcherWithCY
- cmp [arg2.mode],AM_NONE
- je rtnDirectlyToDispatcherWithCY
- ret
- noarg3 ENDP
-
- ;Same as above, except it applies to arg2
-
- noarg2 PROC
- cmp [arg2.mode],AM_NONE
- jne rtnDirectlyToDispatcherWithCY
- cmp [arg1.mode],AM_NONE
- je rtnDirectlyToDispatcherWithCY
- ret
- noarg2 ENDP
-
- ;Whoa, lets see here. If arg1.mode, whatever that is, is NOT 0, we jnz to
- ;rtnDirectlyToDispatcherWithCY. Since this routine was called, the return
- ;address is on the stack. Which means rtnDirectlyToDispatcherWithCY strips
- ;off the return address, and returns to the caller's caller.
-
- noarg1 PROC
- cmp [arg1.mode],AM_NONE
- jne rtnDirectlyToDispatcherWithCY
- ret
- noarg1 ENDP
- ;
- ; pops the ret address from the AOP caller
- ; and goes directly back to the parser with a mismatch error
- ;
- rtnDirectlyToDispatcherWithCY PROC
- pop ax
- stc
- ret
- rtnDirectlyToDispatcherWithCY ENDP
-
-
- ;see if size of this opcode is 1. If not, we are returning NZ and AL=1. I
- ;assume that 1 is important, since without the OR line, we would also be
- ;returning NZ if the size was not 1. In fact, several callers immediately
- ;do a stosb, so at the very least we are ensuring an odd number???
- ; Next guess: AL will eventually be used as part of the stored, assembled
- ;byte. So apparently the purpose of this routine is to set bit 0 of the
- ;untimate assembled value if this is NOT a byte operand.
-
- sizeb0 PROC
- cmp [bx+asmop.asize],BYTESIZE
- je szb0x
- or al,1
- szb0x:
- ret
- sizeb0 ENDP
-
- ;In which case, the purpose of this routine is to set bit 3 of AL if the
- ;operand is NOT a byte operand.
-
- sizeb3 PROC
- cmp [bx+asmop.asize],BYTESIZE
- je szb3x
- or al,8
- szb3x:
- ret
- sizeb3 ENDP
- ;
- ; main RM handler
- ;
- ; within this routine, CX = pointer to mod/RM byte and DX = flag for
- ; <e>bp based indexing
- ;
- ; all MOD/RM fields are set up assuming no offset and updated
- ; later...
- ;
- asmfrm PROC
- cmp [bx+asmop.mode],AM_FPREG ; check for register direct mode
- jne asmrm2
- or al,0c0h ; modrm = 0c0+al+regval
- or al,[bx+asmop.areg1]
- stosb
- ret
-
- asmfrm ENDP
-
-
-
- asmrm PROC
- shl al,3 ; shift reg val into place
- asmrm ENDP
-
-
- asmrm2 PROC
- ;
- ; registers are the same in both 16 & 32-bit
- ;
- cmp [bx+asmop.mode],AM_REG ; 1check for register direct mode
- jne rmnreg
- or al,0c0h ; modrm = 0c0+al+regval
- or al,[bx+asmop.areg1]
- stosb
- ret
- rmnreg:
- cmp [bx+asmop.msize],DWORDMODE ; see which style of addressing
- je asmrm32
- ;
- ; 16-bit MEM handler
- ;
- cmp [bx+asmop.mode],AM_MEM ; 16 bit, check for mem
- jne rm16nmem
- or al,6 ; MODRM = 6+al
- stosb
- jmp rmwoffs
- rm16nmem:
- cmp [bx+asmop.mode],AM_BASED ; check for 16 bit based
- jne rtnDirectlyToDispatcherWithCY
- ;
- ; 16-bit base handler, restricted combos and no scaling
- ;
- push ax ; yes, get the reg vals
- sub ax,ax
- mov al,[bx+asmop.areg1]
- mov ah,[bx+asmop.areg2]
- mov dx,ax
- push di ; scan for a match and to get index
- mov di,offset base16c
- mov cx,16
- repne scasw
- pop di
- pop ax
- jnz rtnDirectlyToDispatcherWithCY ; scan failed, exit
- bt cx,3
- jc rm16nswap
- xchg dl,dh
- rm16nswap:
- and cl,7
- or al,cl
- mov cx,di ; cx points at modrm byte
- stosb
- jmp rmanyoffs ; check for offs
- ;
- ; 32-bit modes start here
- ;
- asmrm32:
- cmp [bx+asmop.mode],AM_MEM ; 32 bit, check for mem
- jne rm32nmem
- ;
- ; generic mem handler
- ;
- or al,5 ; MODRM = 5+al
- stosb
- jmp rmwoffs
- rm32nmem:
- cmp [bx+asmop.mode],AM_BASED ; check for based
- jne rtnDirectlyToDispatcherWithCY ; not legal if not
- cmp [bx+asmop.areg2],0FFh ; else see if second reg defined
- je rm32bbonly
- cmp [bx+asmop.areg1],0FFh ; else see if first reg defined
- je rm32bionly
- ;
- ; both a base AND an index
- ;
- ; the parser should have checked that ESP is not the scond arg
- ; and that we don't have two EBP args
- ;
- cmp [bx+asmop.areg1],isEBP ; check for BP based
- je rm32bbsebp
- or al,4 ; flag MOD for SIB
- mov cx,di
- stosb
- bsf ax,[bx+asmop.ascale] ; calculate SIB byte
- shl ax,3
- or al,[bx +asmop.areg2]
- shl ax,3
- or al,[bx+asmop.areg1]
- stosb
- sub dx,dx
- jmp rmanyoffs
- ;
- ; base and index, base is ebp
- rm32bbsebp:
- or al,4
- mov cx,di
- stosb
- bsf ax,[bx+asmop.ascale] ; calculate SIB byte
- shl ax,3
- or al,[bx+asmop.areg2]
- shl ax,3
- or al,5 ; bp based
- stosb
- mov dx,0ff05h
- jmp rmanyoffs
- ;
- ; index only
- rm32bionly:
- or al,4 ; select SIB byte
- stosb
- bsf ax,word ptr [bx+asmop.ascale] ; calculate scale factor
- shl ax,3 ; shift over
- or ax,word ptr [bx+asmop.areg2] ; add in index
- shl ax,3 ; shift over
- or ax,5 ; base = 5, that is none since mod = 0
- stosb
- mov eax,[bx+asmop.addrx] ; always 32-bit ofs in this mode
- stosd
- ret
- ;
- ; only a base reg
- ;
- rm32bbonly:
- ; shouldn't get here if no regs
- cmp [ebx+asmop.areg1],isESP ; only one reg, check for ESP
- je rm32besp
- cmp [ebx+asmop.areg1],isEBP ; only one reg, check for EBP
- je rm32bebp
- or al,[ebx+asmop.areg1] ; no, normal MODRM byte with no SIB
- mov cx,di
- stosb
- mov dh,0FFh ; pretend 16 bit
- mov dl,al
- and dl,7
- jmp rmanyoffs
- ;
- ; based ESP, no index
- ;
- rm32besp:
- or al,4 ; select SIB byte (sib needed
- mov cx,di ; for indexing off ESP)
- stosb
- mov al,24h ; sib byte for [esp] mode
- stosb
- sub dx,dx
- jmp rmanyoffs
- ;
- ; based ebp, no index
- ;
- rm32bebp:
- or al,5
- mov cx,di ; so we can adjust mod later
- stosb
- mov dx,0ff05h ; MUST have offset, this is BP base reg
- jmp rmanyoffs
- ;
- ; now the auto offset routine.
- ; if (E)BP, we ALWAYS have an offset
- ; otherwise we see if the offset is zero before encoding anything
-
- asmrm2 ENDP
- rmanyoffs PROC
- mov eax,[bx+asmop.addrx] ; get offs
- cmp dx,0ff05h ; BP reg ALWAYS has offs
- je rmaomho
-
- or eax,eax ; else no offs if offs = 0
- jz rmaook
- ;
- ; if we get here we have an offset, fix the RM field and embed the
- ; offset
- ;
- rmaomho:
- xchg cx,bx
- add byte ptr [bx],40h ; else set MOD field = 1
- xchg cx,bx
- and eax,NOT 7FH ; else see if fits in a byte
- jz rmboffs
- cmp eax,NOT 7fh
- je rmboffs ; yep, go do it
- xchg cx,bx
- add byte ptr [bx],40h ; else MOD field = 2
- xchg cx,bx
- jmp rmwoffs ; and go do it
-
- rmboffs:
- mov eax,[bx+asmop.addrx] ; get offs
- stosb ; store a byte offs
- rmaook:
- clc
- ret
- rmanyoffs ENDP
- rmszoffs PROC
- mov eax,[bx+asmop.addrx]
- cmp [bx+asmop.msize],WORDMODE
- jae rmwoffs
- stosb
- clc
- ret
- rmszoffs ENDP
- rmwoffs PROC
- mov eax,[bx+asmop.addrx] ; check size
- cmp [bx+asmop.msize],WORDMODE
- ja rmdwoffs
- stosw ; word offs
- clc
- ret
- rmdwoffs:
- test [Disassemble32Bit],1
- jz rtnDirectlyToDispatcherWithCY
- stosd ; dword offs
- clc
- ret
- rmwoffs ENDP
- rmszimm PROC
- mov eax,[bx+asmop.addrx] ; check size
- cmp [bx+asmop.asize],WORDSIZE
- jae rmszimmw
- stosb
- clc
- ret
- rmszimmw:
- jne rmszimmd
- stosw
- ret
- rmszimmd:
- cmp [bx+asmop.asize],DWORDSIZE
- jne rtnDirectlyToDispatcherWithCY
- test [Disassemble32Bit],1
- jz rtnDirectlyToDispatcherWithCY
- stosd
- ret
- rmszimm ENDP
- ;
- ; no operands. In this case, the opcode length is 1, so we go through this
- ; weird locution to rep mov a single byte out of the structure and
- ; into [di], wherever that points. Apparently it points into an opcode
- ; buffer somewhere. If the opcode length is greater than one, what
- ; happens?
- ;
- AOP0 PROC
- call noarg1 ;see if arg1.mode=0, whatever that means
- push si ;only return here if it IS 0
- movzx cx,[si+opcode.oclength] ;so get the length of the opcode
- lea si,[si+opcode.compare] ;find the opcode in the structure
- rep movsb ;copy from structure to buffer
- pop si ;restore pointer to structure
- clc ;say no problem
- ret
- AOP0 ENDP
- ;
- ; word reg, bits 0-2 of opcode = reg num
- ;
- AOP1 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkregw
- mov al,byte ptr [si+OPCODE.COMPARE]
- or al,[arg1.areg1]
- stosb
- clc
- ret
- AOP1 ENDP
- ;
- ; word acc,reg... reg = bits 0-2 of opcode
- ;
- AOP2 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- call chkaxw
- mov bx,offset arg2
- call chkregw
- mov al,byte ptr [si+opcode.compare]
- or al,[arg2.areg1]
- stosb
- ret
- AOP2 ENDP
- ;
- ; one arg, seg goes in b3-4 of opcode
- ;
- AOP3 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkseg
- mov ah,byte ptr [si+OPCODE.COMPARE]
- mov al,[arg1.areg1]
- cmp ah,8
- jae aop3ext
- cmp al,4
- jae aop3errx
- aop3c:
- shl al,3
- or al,ah
- stosb
- ret
- aop3ext:
- sub al,4
- jnc aop3c
- aop3errx:
- stc
- ret
-
- AOP3 ENDP
- ;
- ; either combo of a reg & rm... bit 1 of opcode set if reg is dest
- ; bit 0 set if size = word
- ;
- AOP4 PROC
- call noarg3
- call intsize
- sub al,al
- mov bx,offset arg1
- call sizeb0
- cmp [arg1.mode],AM_REG
- jne aop4rs
- or al,2
- mov bx,offset arg2
- mov ah,[arg1.areg1]
- jmp aop4j
-
- aop4rs:
- cmp [arg2.mode],AM_REG
- jne aop4err
- mov bx,offset arg1
- mov ah,[arg2.areg1]
- aop4j:
- or al,byte ptr [si+OPCODE.COMPARE]
- stosb
- mov al,ah
- call asmrm
- ret
- aop4err:
- stc
- ret
- AOP4 ENDP
- ;
- ; use only rm, bit 0 = size (exception : jmp/call)
- ;
- AOP5 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- mov ax,[si+OPCODE.COMPARE]
- test al,1
- jz aop5cansize
- cmp [arg1.asize],DWORDSIZE ; special sizing for jump
- jne aop5jn4
- and [PrefixBitmapWord],NOT AS_OPSIZE
- or ah,8
- aop5jn4:
- cmp [bx+asmop.asize],WORDSIZE
- je aop5unsized
- cmp [bx+asmop.asize],NOSIZE
- je aop5unsized
- stc
- ret
- aop5cansize:
- call sizeb0
- aop5unsized:
- stosb
- xchg al,ah
- and al,38h
- mov bx,offset arg1
- call asmrm2
- ret
- AOP5 ENDP
- ;
- ; rm,count or rm,cl (shifts) bit 0 = size
- ; bit 1 set if size = 1, bit 4 set if size = cl, otherwise follow rm with
- ; a count byte
- ;
- AOP6 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- mov ax,[si+opcode.compare]
- call sizeb0
- cmp [arg2.mode],AM_REG
- je aop6cl
- cmp [arg2.mode],AM_IMM
- je aop6imm
- aop6b:
- stc
- ret
- aop6cl:
- cmp [arg2.asize],BYTESIZE
- jne aop6b
- cmp [arg2.areg1],isECX
- jne aop6b
- or al,12h
- stosb
- jmp aop6rm
- aop6imm:
- cmp [arg2.addrx],1
- je aop6shift1
- stosb
- xchg al,ah
- call asmrm2
- mov al,byte ptr [arg2.addrx]
- stosb
- ret
- aop6shift1:
- or al,10h
- stosb
- aop6rm:
- xchg al,ah
- call asmrm2
- ret
- AOP6 ENDP
- ;
- ; unordered version of AOP4. (any combo of reg and RM)
- ; This is XCHG instructions,
- ; this is unordered, so, it doesn't
- ; need to know which comes first
- ;
- ; bit 0 = size
- ;
- AOP7 PROC
- call noarg3
- call intsize
- sub al,al
- mov bx,offset arg1
- call sizeb0
- cmp [arg1.mode],AM_REG
- jne aop7rs
- mov bx,offset arg2
- mov ah,[arg1.areg1]
- jmp aop7j
-
- aop7rs:
- cmp [arg2.mode],AM_REG
- jne aop7err
- mov bx,offset arg1
- mov ah,[arg2.areg1]
- aop7j:
- or al,byte ptr [si+OPCODE.COMPARE]
- stosb
- mov al,ah
- call asmrm
- ret
- aop7err:
- stc
- ret
- AOP7 ENDP
- ;
- ; word regrm, reg = dest.
- ;
- AOP8 PROC
- call noarg3
- call intsize
- cmp [arg1.asize],BYTESIZE
- je aop8errx
- mov bx,offset arg1
- call chkreg
- mov al,[bx+asmop.asize]
- cmp bl,1
- jne aop8ok
- aop8errx:
- stc
- ret
- aop8ok:
- mov al,byte ptr [si+OPCODE.COMPARE]
- stosb
- mov al,[bx+asmop.areg1]
- mov bx,offset arg2
- call asmrm
- ret
- AOP8 ENDP
- ;
- ; interrupts (imm byte)
- ;
- AOP9 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkimm
- cmp byte ptr [arg1.addrx],3
- je aop9i3
- mov al,byte ptr [si+OPCODE.COMPARE]
- or al,1
- stosb
- mov al,byte ptr [bx+asmop.addrx]
- stosb
- clc
- ret
- aop9i3:
- mov al,0cch
- stosb
- ret
- AOP9 ENDP
- ;
- ; short relative branches
- ;
- AOP10 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkimm
- movzx eax,[lastofs]
- sub eax,[bx+asmop.addrx]
- neg eax
- sub eax,2
- cmp eax,-128
- jl aop10errx
- cmp eax,127
- jle aop10ok
- aop10errx:
- stc
- ret
- aop10ok:
- push ax
- mov al,byte ptr [si+OPCODE.COMPARE]
- stosb
- pop ax
- stosb
- clc
- ret
- AOP10 ENDP
- ;
- ; RM, IMMEDIATE
- ; bit 0 = size
- ;
- AOP11 PROC
- call noarg3
- call intsize
- mov bx,offset arg2
- call chkimm
- mov bx,offset arg1
- mov ax,[si+OPCODE.COMPARE]
- call sizeb0
- stosb
- xchg al,ah
- call asmrm2
- mov bx,offset arg2
- call rmszimm
- ret
- AOP11 ENDP
- ;
- ; ACC,immediate
- ; bit 0 = size
- ;
- AOP12 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- call chkax
- mov bx,offset arg2
- call chkimm
- mov al,byte ptr [si+OPCODE.COMPARE]
- call sizeb0
- stosb
- call rmszimm
- ret
- AOP12 ENDP
- ;
- ; mem,acc
- ; bit 0 = size
- ;
- AOP13 PROC
- call noarg3
- call intsize
- mov bx,offset arg2
- call chkax
- mov bx,offset arg1
- call chkmem
- mov al,byte ptr [si+OPCODE.COMPARE]
- call sizeb0
- stosb
- call rmszoffs
- ret
- AOP13 ENDP
- ;
- ; sign-extended RM/IMM
- ; b1 = 0, treat as normal RM/IMM (aop11)
- ; else b01=11 means sign-extend byte to word
- ;
- AOP14 PROC
- call noarg3
- call intsize
- mov bx,offset arg2
- call chkimm
- cmp [bx+asmop.asize],BYTESIZE
- je aop11
- mov eax,[bx +asmop.addrx]
- cmp eax,-128
- jl aop11
- cmp eax,127
- jge aop11
- ;
- ; get here for signed extension
- ;
- mov bx,offset arg1
- mov ax,[si+opcode.compare]
- or al,3
- stosb
- xchg al,ah
- call asmrm2
- mov al,byte ptr [arg2.addrx]
- stosb
- ret
- AOP14 ENDP
- ;
- ; acc,imm
- ; b3 of opcode = size
- ;
- AOP15 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- call chkax
- mov bx,offset arg2
- call chkimm
- mov al,byte ptr [si+OPCODE.COMPARE]
- call sizeb3
- stosb
- call rmszimm
- ret
- AOP15 ENDP
- ;
- ; seg,regrm or regrm,seg
- ; b1 set if seg is dest
- ;
- AOP16 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- cmp [bx+asmop.mode],AM_SEG
- jne aop16seg2
- mov al,byte ptr [si+OPCODE.COMPARE]
- or al,2
- mov ah,[bx+asmop.areg1]
- mov bx,offset arg2
- jmp aop16rm
- aop16seg2:
- mov bx,offset arg2
- call chkseg
- mov al,byte ptr [si+OPCODE.COMPARE]
- mov ah,[bx+asmop.areg1]
- mov bx,offset arg1
- aop16rm:
- stosb
- xchg al,ah
- call asmrm
- ret
- AOP16 ENDP
- ;
- ; returns which pop the stack
- ;
- AOP17 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkimm
- mov al,byte ptr [si+OPCODE.COMPARE]
- stosb
- mov ax,word ptr [bx+asmop.addrx]
- stosw
- clc
- ret
- AOP17 ENDP
- ;
- ; far branch or call
- ;
- AOP18 PROC
- call noarg2
- call intsize
- cmp [arg1.mode],AM_SEGOFFS
- jne aop18bad
- mov al,byte ptr [si+OPCODE.COMPARE]
- stosb
- mov ax,word ptr [arg1.addrx2]
- stosw
- mov ax,word ptr [arg1.addrx]
- stosw
- clc
- ret
- aop18bad:
- stc
- ret
- AOP18 ENDP
- ;
- ; ESC instruction
- ; imm,rm... imm is six bits and fills the low three bits of the
- ; opcode and the reg field
- ;
- AOP19 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- call chkimm
- mov al,byte ptr [bx+asmop.addrx]
- shr al,3
- and al,7
- or al,byte ptr [si+OPCODE.compare]
- stosb
- mov al,byte ptr [bx+asmop.addrx]
- and al,7
- mov bx,offset arg2
- call asmrm
- ret
- AOP19 ENDP
- ;
- ; long relative branch
- ; (the parser fills in the 0f starter)
- ;
- AOP20 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkimm
- movzx eax,[lastofs]
- sub eax,[bx+asmop.addrx]
- neg eax
- sub eax,3
- cmp byte ptr [si+OPCODE.COMPARE],0e0h
- jae aop20got
- dec eax
- aop20got:
- cmp eax,-32768
- jl aop20errx
- cmp eax,32767
- jle aop20ok
- aop20errx:
- stc
- ret
- aop20ok:
- push ax
- mov al,byte ptr [si+OPCODE.COMPARE]
- stosb
- pop ax
- stosw
- clc
- ret
- AOP20 ENDP
- ;
- ; acc,dx (in instructions)
- ; bit 0 = size
- ;
- AOP21 PROC
- call noarg3
- call intsize
- mov bx,offset arg2
- call chkdx
- mov bx,offset arg1
- call chkax
- mov al,byte ptr [ si+OPCODE.COMPARE]
- cmp [bx+asmop.asize],BYTESIZE
- je aop21nw
- or al,1
- aop21nw:
- cmp [bx +asmop.asize],DWORDSIZE ; auto prefixing on
- jne aop21nw2 ; ins & outs is disabled
- or [PrefixBitmapWord],AS_OPSIZE
- aop21nw2:
- stosb
- clc
- ret
- AOP21 ENDP
- ;
- ; dx,acc (out_)
- ; bit 0 = size
- ;
- AOP22 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- call chkdx
- mov bx,offset arg2
- call chkax
- mov al,byte ptr [ si+OPCODE.COMPARE]
- cmp [bx+asmop.asize],BYTESIZE
- je aop22nw
- or al,1
- aop22nw:
- cmp [bx +asmop.asize],DWORDSIZE ; auto prefixing on
- jne aop22nw2 ; ins & outs is disabled
- or [PrefixBitmapWord],AS_OPSIZE
- aop22nw2:
- stosb
- clc
- ret
- AOP22 ENDP
- ;
- ; port,acc or acc,port
- ; b0 =size, b1 = 1 if port is dest
- ;
- AOP23 PROC
- call noarg3
- call intsize
- test byte ptr [si+OPCODE.COMPARE],2
- jz aop23in
- mov bx,offset arg2
- call chkax
- mov bx,offset arg1
- call chkimm
- jmp aop23j
- aop23in:
- mov bx,offset arg1
- call chkax
- mov bx,offset arg2
- call chkimm
- aop23j:
- mov al,byte ptr [si+OPCODE.compare]
- cmp [bx +asmop.asize],WORDSIZE
- jb aop23b
- or al,1
- aop23b:
- clc
- stosb
- mov al,byte ptr [bx +asmop.addrx]
- stosb
- ret
- AOP23 ENDP
- ;
- ; acc,mem
- ; bit 0 = size
- ;
- AOP24 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- call chkax
- mov bx,offset arg2
- call chkmem
- mov al,byte ptr [si+OPCODE.COMPARE]
- call sizeb0
- stosb
- call rmszoffs
- ret
- AOP24 ENDP
- ;
- ; immediate byte or word
- ; this is push imm, bit 1 set for byte
- ; we were about due for a departure from the standard...
- ; anyway the op is sign-extended if it is byte size
- ;
- AOP25 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkimm
- mov al,byte ptr [si+OPCODE.COMPARE]
- mov ebx,[bx+asmop.addrx]
- cmp ebx,-128
- jl aop25w
- cmp ebx,127
- jg aop25w
- ;
- ; byte size
- ;
- or al,2
- stosb
- mov al,bl
- stosb
- ret
- aop25w:
- stosb
- test [PrefixBitmapWord],AS_OPSIZE
- jnz aop25dw
- cmp ebx,-23768
- jl aop25dw
- cmp ebx,32767
- jg aop25dw
- mov ax,bx
- stosw
- clc
- ret
- aop25dw:
- or [PrefixBitmapWord],AS_OPSIZE
- mov eax,ebx
- stosd
- clc
- ret
- AOP25 ENDP
- ;
- ; enter command, we have a word then a byte
- ;
- AOP26 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- call chkimm
- mov [bx+asmop.asize],WORDSIZE
- mov bx,offset arg2
- call chkimm
- mov [bx+asmop.asize],BYTESIZE
- mov al,byte ptr [si+OPCODE.COMPARE]
- stosb
- mov ax,word ptr [arg1.addrx]
- stosw
- mov al,byte ptr [arg2.addrx]
- stosb
- ret
- AOP26 ENDP
- ;
- ; stringu/w/d, pushaw,pushfw, etc
- ; explicit byte sizing handled elsewhere (aop0)
- ;
- AOP27 PROC
- call noarg1
- call intsize
- mov al,byte ptr [si+opcode.compare]
- cmp [lastbyte],'w'
- je aop27w
- cmp [lastbyte],'d'
- je aop27dw
- ;
- ; get here if no size specced.
- mov al,byte ptr [si+opcode.compare]
- and al,NOT 1
- cmp al,60h ; default for push/pop is word
- je aop27w
- cmp al,9ch
- je aop27w
- stosb ; else default is byte
- clc
- ret
- aop27dw:
- or [PrefixBitmapWord],AS_OPSIZE ; come here if specified dword
- aop27w:
- mov al,byte ptr [si+opcode.compare] ; or here if specified word
- stosb
- clc
- ret
- AOP27 ENDP
- ;
- ; rm,reg (test instruction)
- ; bit 0 = size
- ;
- AOP28 PROC
- call noarg3
- call intsize
- mov bx,offset arg2
- call chkreg
- mov al,byte ptr [si+OPCODE.COMPARE]
- call sizeb0
- stosb
- mov al,[arg2.areg1]
- mov bx,offset arg1
- call asmrm
- ret
- AOP28 ENDP
- ;
- ; rm, size don't care
- ;
- AOP29 PROC
- call noarg2
- mov ax,[si+OPCODE.COMPARE]
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmrm2
- ret
- AOP29 ENDP
- ;
- ; RM, shift
- ; bit 0 & 1 of opcode set if uses CL
- ; bit 0 & 4 set if uses uses 1
- ; else nothing set
- ;
- AOP30 PROC
- call noarg3
- call intsize
- mov ax,word ptr [si+OPCODE.compare]
- and al,0ech ; get rid of extraneous bits
- mov bx,offset arg2
- cmp [bx+asmop.areg1],isEBX
- je aop30cl
- call chkimm
- cmp [bx+asmop.addrx],1
- jne aop30xx
- or al,11h
- stosb
- xchg al,ah
- call asmrm2
- ret
- aop30xx:
- or al,3
- stosb
- xchg al,ah
- call asmrm2
- mov al,byte ptr [arg2.addrx]
- stosb
- ret
- aop30cl:
- cmp [bx+asmop.asize],BYTESIZE
- jne aop30bad
- cmp [bx+asmop.mode],AM_REG
- jne aop30bad
- stosb
- xchg al,ah
- call asmrm2
- ret
-
- aop30bad:
- stc
- ret
- AOP30 ENDP
- ;
- ; reg,rm,imm or reg,imm (imul)
- ; bit 1 = set if immed = signed byte
- ;
- AOP31 PROC
- cmp [arg3.mode],AM_NONE
- jne aop31three
- mov bx,offset arg1
- call chkreg
- mov al,byte ptr [si+OPCODE.compare]
- mov bx,offset arg2
- call chkimm
- call aop31sb
- stosb
- push ax
- mov al,[arg1.areg1]
- mov ah,al
- shl al,3
- or al,ah
- or al,0c0h
- stosb
- jmp aop31sz
- aop31three:
- mov bx,offset arg1
- call chkreg
- mov al,byte ptr [si+OPCODE.compare]
- mov bx,offset arg3
- call chkimm
- call aop31sb
- stosb
- push ax
- push bx
- mov al,[arg1.areg1]
- mov bx,offset arg2
- call asmrm
- pop bx
- jmp aop31sz
- aop31sz:
- pop ax
- test al,2
- mov eax,dword ptr [bx +asmop.addrx]
- jnz aop31sb1
- test [PrefixBitmapWord],AS_OPSIZE
- jz aop31szw
- stosd
- clc
- ret
- aop31szw:
- stosw
- clc
- ret
- aop31sb1:
- stosb
- clc
- ret
- aop31sb PROC
- mov ecx,[bx+asmop.addrx]
- test ecx,NOT 7fh
- jnz aop31sbx
- cmp ecx,-80h
- jl aop31sbx
- cmp [bx+asmop.asize],BYTESIZE
- je aop31sbx
- or al,2
- aop31sbx:
- ret
- aop31sb ENDP
-
- AOP31 ENDP
- ;
- ; move to/from a special register
- ; bit 1 = set if spc reg is the dest
- ; bit 0 & 2 define the special reg
- ;
- AOP32 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- mov cx,offset arg2
- mov ax,[si+OPCODE.COMPARE]
- cmp [arg1.asize],DWORDSIZE
- jne aop32bad
- cmp [arg1.mode],am_reg
- je aop32crsource
- or al,2
- xchg bx,cx
- aop32crsource:
- sub dl,dl
- cmp [ecx+asmop.mode],AM_CR
- je aop32c
- mov dl,1
- cmp [ecx+asmop.mode],AM_DR
- je aop32c
- mov dl,4
- cmp [ecx+asmop.mode],AM_TR
- jne aop32bad
- aop32c:
- or al,dl
- stosb
-
- call chkreg
- movzx ecx,cx
- mov al,[ecx+asmop.areg1]
- shl al,3
- or al,[bx +asmop.areg1]
- or al,ah ; actually is a MOD/RM which is restricted
- ; to regs
- stosb
- and [PrefixBitmapWord],NOT AS_OPSIZE ; don't need opsize for this
- ; and there will be no clash
- ; if we got this far
- ret
- aop32bad:
- stc
- ret
- AOP32 ENDP
- ;
- ; rm,reg,count (shld/shrd)
- ; bit 0 = set if using CL for count
- ;
- ;
- aop33 PROC
- mov bx,offset arg2
- call chkreg
- cmp [bx+asmop.asize],BYTESIZE
- je aop33bad
- mov ah,[bx+asmop.areg1]
- mov al,byte ptr [si+OPCODE.compare]
- mov bx,offset arg3
- cmp [bx+asmop.areg1],isECX
- je aop33cl
- call chkimm
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmrm
- mov al,byte ptr [arg3.addrx]
- stosb
- ret
- aop33cl:
- cmp [bx+asmop.mode],AM_REG
- jne aop33bad
- or al,1h
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmrm
- ret
-
- aop33bad:
- stc
- ret
- AOP33 ENDP
- ;
- ; push & pop rm
- ;
- AOP34 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- cmp [bx+asmop.asize],BYTESIZE
- je aop34bad
- mov ax,[si+OPCODE.compare]
- stosb
- xchg al,ah
- call asmrm2
- ret
- aop34bad:
- stc
- ret
- AOP34 ENDP
- ;
- ; floating R/M
- ; bit two of opcode set if size is qword
- ; bit 3 of mod/rm set if last ch = 'p'
- ;
- AOP35 PROC
- call noarg2
- mov ax,[si+OPCODE.COMPARE]
- and ax,010d8h
- cmp [arg1.mode],AM_FPREG
- je aop35fin
- cmp [arg1.asize],QWORDSIZE
- jne aop35fin
- or al,4
- aop35fin:
- cmp [lastbyte],'p'
- jne aop35fin2
- or ah,8
- aop35fin2:
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmfrm
- ret
- AOP35 ENDP
- ;
- ; fmathp
- ; sti),st(0) or nothing
- ;
- AOP36 PROC
- cmp [arg3.mode],AM_NONE
- jne aop36errx
- mov ax,100h
- cmp [arg2.mode],AM_NONE
- jne aop362arg
- call noarg1
- jmp aop36fin
- aop362arg:
- cmp [arg1.mode],AM_FPREG
- jne aop36errx
- cmp [arg2.mode],AM_FPREG
- jne aop36errx
- cmp [arg2.areg1],isEAX
- jne aop36errx
- mov ah,[arg1.areg1]
- aop36fin:
- or ax,[si+OPCODE.COMPARE]
- stosw
- ret
- aop36errx:
- stc
- ret
- AOP36 ENDP
- ;
- ; fmath
- ; st(i),st(0) ; st(0), st(i), mem
- ; bit two of opcode set for i dest or qword mem
- ; bit 3 of mod/rm gets flipped if reg & al &6 & bit 5 of mod/rm set
- ;
- ;
- AOP37 PROC
- cmp [arg3.mode],AM_NONE
- jne aop37errx
- mov ax,[si+OPCODE.COMPARE]
- and al,NOT 4
- cmp [arg2.mode], AM_NONE
- je aop37mem
- cmp [arg1.mode],AM_FPREG
- jne AOP37mem
- cmp [arg2.mode],AM_FPREG
- jne AOP37errx
- mov bl,[arg2.areg1]
- mov bh,[arg1.areg1]
- cmp bh,0
- je aop37isrc
- cmp bl,0
- jne aop37errx
- xchg bl,bh
- or al,4
- aop37isrc:
- test al,6
- jz aop371
- test ah,20h
- jz aop371
- xor ah,8
- aop371:
- or ah,bl
- or ah,0c0h
- stosw
- ret
- aop37mem:
- cmp [arg2.mode],AM_NONE
- jne aop37errx
- cmp [arg1.asize],QWORDSIZE
- jne aop37memnq
- or al,4
- aop37memnq:
- stosb
- xchg al,ah
- mov bx,offset [arg1]
- call asmfrm
- ret
- aop37errx:
- stc
- ret
- AOP37 ENDP
- ;
- ; far RM
- ;
- AOP38 PROC
- call noarg2
- cmp [arg1.asize],DWORDSIZE
- jne aop38errx
- cmp [arg1.mode],AM_REG
- je aop38errx
- mov ax,[si+opcode.compare]
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmrm2
- ret
- aop38errx:
- stc
- ret
- AOP38 ENDP
- ;
- ; word regrm with reg source
- ; bug: lets arpl [bx],eax through
- ;
- AOP39 PROC
- cmp [arg2.asize],BYTESIZE
- jne AOP40
- stc
- ret
- AOP39 ENDP
- ;
- ; regrm with reg source
- ; bit 0 = size
- AOP40 PROC
- call noarg3
- call intsize
- mov bx,offset arg2
- call chkreg
- mov al,byte ptr [si+opcode.compare]
- call sizeb0
- stosb
- mov al,[arg2.areg1]
- mov bx,offset arg1
- call asmrm
- ret
- AOP40 ENDP
- ;
- ; rm,immediate
- ;
- AOP41 PROC
- call noarg3
- call intsize
- mov bx,offset arg2
- call chkimm
- cmp [arg1.asize],BYTESIZE
- je aop41errx
- mov ax,[si+OPCODE.COMPARE]
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmrm2
- mov al,byte ptr [arg2.addrx]
- stosb
- ret
- aop41errx:
- stc
- ret
- AOP41 ENDP
- ;
- ; regrm with reg dest & forced strictness (MOVZX & MOVSX)
- ; bit 0 of opcode set if size is word
- ;
- AOP42 PROC
- call noarg3
- call intsize
- mov bx,offset arg1
- call chkreg
- cmp [arg1.asize],BYTESIZE
- je aop42errx
- cmp [arg2.asize],NOSIZE
- je aop42errx
- mov bx,offset arg2
- mov ax,[si+OPCODE.COMPARE]
- call sizeb0
- stosb
- xchg al,ah
- call asmrm2
- cmp [arg1.asize],DWORDSIZE ; another func for which
- ; auto extend to dword doesn't work
- jne aop42x
- or [PrefixBitmapWord],AS_OPSIZE
- aop42x:
- clc
- ret
- aop42errx:
- stc
- ret
- AOP42 ENDP
- ;
- ; not needed in assembler, same as no args
- ;
- AOP43 PROC
- jmp aop0
- AOP43 ENDP
- ;
- ; unused
- ;
- AOP44 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkreg
- cmp [bx+asmop.asize],DWORDSIZE
- jne aop44errx
- or [PrefixBitmapWord],AS_OPSIZE
- mov al,byte ptr [si+OPCODE.COMPARE]
- or al,[bx+asmop.areg1]
- stosb
- ret
- aop44errx:
- stc
- ret
- AOP44 ENDP
- ;
- ; any regrm with reg source
- ; same as aop40
- ;
- AOP45 PROC
- jmp aop40
- AOP45 ENDP
- ;
- ; rm , size don't care, but no regs
- ;
- AOP46 PROC
- cmp [arg1.mode],AM_FPREG
- je aop46err
- cmp [arg1.mode],AM_REG
- jne aop29
- aop46err:
- stc
- ret
- AOP46 ENDP
- ;
- ; ax reg only
- ;
- AOP47 PROC
- call noarg2
- mov bx,offset arg1
- call chkaxw
- mov ax,[si+OPCODE.COMPARE]
- stosw
- clc
- ret
- AOP47 ENDP
- ;
- ; bswap, 32-bit reg to bits 0-3 of opcode
- ;
- AOP48 PROC
- call noarg2
- call intsize
- mov bx,offset arg1
- call chkreg
- cmp [bx+asmop.asize],DWORDSIZE
- jne aop48errx
- or [PrefixBitmapWord],AS_OPSIZE
- mov al,byte ptr [si+OPCODE.COMPARE]
- or al,[bx+asmop.areg1]
- stosb
- ret
- aop48errx:
- stc
- ret
- AOP48 ENDP
- ;
- ; fst
- ; same as next but no tbyte
- ;
- AOP49 PROC
- cmp [arg1.asize],TBYTESIZE
- jb aop50
- stc
- ret
- AOP49 ENDP
- ;
- ; fld/fstp
- ; freg
- ; dword,qword,tybe
- ; bit 1 of opcode set for tbyte
- ; bit 2 of opcode set for qword or store
- ; bit 5 of modrm set if tbyte
- ; bit 3 of modrm gets cleared if not tbyte && bit 4 set
- ;
- AOP50 PROC
- call noarg2
- mov ax,[si+OPCODE.COMPARE]
- AND ax,NOT 0e006h
- cmp [arg1.mode],AM_FPREG
- je aop50reg
- cmp [arg1.asize],DWORDSIZE
- jb aop50errx
- aop502:
- cmp [arg1.asize],TBYTESIZE
- jne aop503
- or ax,2802h
- jmp aop505
-
- aop503:
-
- cmp [arg1.asize],QWORDSIZE
- jne aop504
- or al,4
- aop504:
- test ah,10h
- jnz aop505
- and ah,NOT 8
- aop505:
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmfrm
- ret
- aop50reg:
- test ah,10h
- jnz aop506
- and ah,NOT 8
- jmp aop507
- aop506:
- or al,4
- aop507:
- or ah,0c0h
- or ah,[arg1.areg1]
- stosw
- ret
- aop50errx:
- stc
- ret
- AOP50 ENDP
- ;
- ;
- ; fbld/fbstp
- ; tbyte ptr mem
- ;
- AOP51 PROC
- call noarg2
- cmp [arg1.mode],AM_FPREG
- je aop51errx
- cmp [arg1.asize],NOSIZE
- je aop51c
- cmp [arg1.asize],TBYTESIZE
- jne aop51errx
- aop51c:
- mov ax,[si+OPCODE.COMPARE]
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmfrm
- ret
- aop51errx:
- stc
- ret
- AOP51 ENDP
- ;
- ; fild/fistp
- ; word,dword,qword mem
- ; bit 2 of opcode set if word or qword
- ; bit 3 of modrm gets cleared if not qword & bit 4 is set
- ; bit 5 or modrm set if qword
- ;
- AOP52 PROC
- call noarg2
- mov ax,[si+OPCODE.COMPARE]
- and ax,NOT 2004h
- cmp [arg1.mode],AM_FPREG
- je aop52errx
- cmp [arg1.asize],DWORDSIZE
- je aop522
- or al,4
- aop522:
- cmp [arg1.asize],QWORDSIZE
- ja aop52errx
- jne aop523
- or ah,20h
- jmp aop524
- aop523:
- test ah,10h
- jnz aop524
- and ah, NOT 8
- aop524:
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmfrm
- ret
- aop52errx:
- stc
- ret
- AOP52 ENDP
- ;
- ; fist
- ; same as above but no qword mode
- ;
- AOP53 PROC
- cmp [arg1.asize],QWORDSIZE
- jb aop52
- stc
- ret
- AOP53 ENDP
- ;
- ; freg
- ; reg put in mod/rm byte
- ;
- AOP54 PROC
- call noarg2
- cmp [arg1.mode],AM_FPREG
- jne aop54errx
- mov ax,[si+OPCODE.COMPARE]
- or ah,[arg1.areg1]
- stosw
- ret
- aop54errx:
- stc
- ret
- AOP54 ENDP
- ;
- ; same as above, deault to reg 1 if no args
- AOP55 PROC
- cmp [arg3.mode],AM_NONE
- jne aop55errx
- cmp [arg2.mode],AM_NONE
- jne aop55errx
- call noarg2
- mov ax,[si+OPCODE.COMPARE]
- cmp [arg1.mode],AM_FPREG
- jne aop55chknone
- or ah,[arg1.areg1]
- stosw
- ret
- aop55chknone:
- cmp [arg1.mode],AM_NONE
- jne aop55errx
- or ah,1
- stosw
- ret
- aop55errx:
- stc
- ret
- AOP55 ENDP
- ;
- ; fimath
- ; word or dword arg
- ; bit two gets set if word
- ;
- AOP56 PROC
- call noarg2
- call intsize
- cmp [arg1.asize],BYTESIZE
- je aop56errx
- cmp [arg1.mode],AM_FPREG
- je aop56errx
- mov ax,[si+OPCODE.COMPARE]
- cmp [arg1.asize],WORDSIZE
- jne aop56c
- or al,4
- aop56c:
- stosb
- xchg al,ah
- mov bx,offset arg1
- call asmfrm
- ret
- aop56errx:
- ret
-
- AOP56 ENDP
-
- ;
- ; addrsize prefix on one-byte
- ;
- AOP57 PROC
- or [PrefixBitmapWord],AS_ADDRSIZE
- jmp aop0
- AOP57 ENDP
- ;
- ; opsize prefix on one-byte
- ;
- AOP58 PROC
- or [PrefixBitmapWord],AS_OPSIZE
- jmp aop0
- AOP58 ENDP
- end