📄 operands.asm
字号:
;
; GRDP
;
; Copyright(c) LADsoft
;
; David Lindauer, camille@bluegrass.net
;
;
; Operands.asm
;
; Function: Handle 386 operands as dictated by the opcode table
; Handle formatting output
;
; Sorry, I didn't have time to document this one yet
;
; years later:
;
; sorry, I STILL didn't have time to document this one yet :)
;
;MASM MODE
.MODEL SMALL
.386
include edispatc.inc
include iopcodes.inc
include ioperand.inc
include eoptions.inc
include eopcom.inc
PUBLIC TabTo, ReadOverrides, DispatchOperands
PUBLIC FormatDisassembly, FormatValue, Code_Address
PUBLIC PutDword, PutWord,PutByte
PUBLIC put2,put3,put4, strlen
extrn x86pfx : byte
SZ_QWORD = 2
SZ_TBYTE = 4
.DATA
code_address dw 0 ;disassembly address within segment
dest2 dw 0 ;temps to aid decoding
source2 dw 0
segs dw 0
extraoperand OPERAND <> ;third operand
source OPERAND <> ;second operand
dest OPERAND <> ;first operand
nmmnemonic db 10 DUP (?) ;mnemonic (may be modified here)
reqsPtrSizeOvride db 0 ;flag set if xxx ptr required
.CODE
;Find the length of a string in a buffer pointed to by SI, and return that
;length in AX. This is a strange way to do this. I think I'll change it
;just a little.
; If SI comes in pointing to a 0, we return a string length of 0
strlen PROC
push di
push si
push cx
mov di,si
mov cx,-1
sub al,al
repnz scasb
mov ax,cx
not ax
dec ax
pop cx
pop si
pop di
ret
strlen ENDP
strcpy PROC
strcpylp:
lodsb
stosb
or al,al
jnz strcpylp
ret
strcpy ENDP
strcat PROC
mov al,[di]
inc di
or al,al
jnz strcat
dec di
jmp strcpy
strcat ENDP
CopyExtra PROC
push si
push di
mov si,offset extraoperand
xchg si,di
mov cx,OPERANDSIZE
rep movsb
pop di
pop si
ret
CopyExtra ENDP
put2 PROC
mov [si],ah
inc si
mov [si],al
inc si
mov BYTE PTR [si],0
ret
put2 ENDP
put3 PROC
push eax
shr eax,8
mov [si],ah
inc si
pop eax
call put2
ret
put3 ENDP
put4 PROC
push eax
shr eax,16
call put2
pop eax
call put2
ret
put4 ENDP
SetSeg PROC
mov [reqsPtrSizeOvride],FALSE
mov [di+OPERAND.code],OM_SEGMENT
mov [di+OPERAND.THEREG],al
ret
SetSeg ENDP
SetReg PROC
mov [reqsPtrSizeOvride],FALSE
mov [di+OPERAND.code],OM_REG
mov [di+OPERAND.THEREG],al
ret
SetReg ENDP
ReadRM PROC
push cx
sub cx,cx
mov cl,2
RM si
mov [di+OPERAND.THEREG],al
MODX si
mov ch,al
cmp ch,MOD_REG
jnz short notregreg
mov [di+OPERAND.CODE],OM_REG
mov [reqsPtrSizeOvride],FALSE
sub ax,ax
pop cx
ret
notregreg:
bt [di+OPERAND.OEFLAGS],OMF_ADR32
jnc adr16
cmp [di+OPERAND.THEREG],RM_32_SCALED
jnz notscaled
inc cl
RM si+1
mov [di+OPERAND.THEREG],al
REG si+1
mov [di+OPERAND.SCALEREG],al
MODX si+1
mov [di+OPERAND.SCALE],al
cmp [di+OPERAND.SCALEREG],RM_32_STACKINDEX
jz hassp
bts [di+OPERAND.OEFLAGS],OMF_SCALED
hassp:
cmp [di+OPERAND.THEREG],RM_32_ABSOLUTE
jnz basedAndScaled
cmp ch,MOD_NOOFS
jnz short basedAndScaled
mov [di+OPERAND.CODE],OM_ABSOLUTE
LONG si+3
mov [di+OPERAND.ADDRESS],eax
sub ax,ax
mov al,5
pop cx
ret
notscaled:
cmp ch,MOD_NOOFS
jnz basedAndScaled
cmp [di+OPERAND.THEREG], RM_32_ABSOLUTE
jnz basedAndScaled
mov [di+OPERAND.CODE], OM_ABSOLUTE
LONG si+2
mov [di+OPERAND.ADDRESS],eax
sub ax,ax
sub ax,ax
mov al,4
pop cx
ret
adr16:
movzx esi,si
cmp ch,MOD_NOOFS
jnz basedAndScaled
cmp [di+OPERAND.THEREG], RM_16_ABSOLUTE
jnz basedAndScaled
mov [di+OPERAND.CODE], OM_ABSOLUTE
UINT si+2
mov [di+OPERAND.ADDRESS],eax
sub ax,ax
mov al,2
pop cx
ret
basedAndScaled:
mov [di+OPERAND.CODE], OM_BASED
cmp ch,MOD_ADDR
jnz short checksigned
bts [di+OPERAND.OEFLAGS], OMF_WORD_OFFSET
push cx
sub ch,ch
movzx ecx,cl
mov eax,fs:[esi+ecx]
pop cx
bt [di+OPERAND.OEFLAGS], OMF_ADR32
jc dwordx
and eax,0ffffh
sub cl,2
dwordx:
mov [di+OPERAND.ADDRESS],eax
add cl,4
jmp short readrmdone
checksigned:
cmp ch, MOD_SIGNED
jnz short readrmdone
bts [di+OPERAND.OEFLAGS],OMF_SIGNED_OFFSET
movzx ecx,cl
movzx eax,byte ptr fs:[esi+ecx]
mov [di+OPERAND.ADDRESS],eax
inc cl
readrmdone:
movzx ax,cl
sub al,2
pop cx
ret
ReadRM ENDP
RegRM PROC
mov di,[dest2]
REG si
call SetReg
mov di,[source2]
call ReadRM
ret
RegRM ENDP
Immediate PROC
push cx
sub cx,cx
mov [di+OPERAND.CODE],OM_IMMEDIATE
bt [di+OPERAND.OEFLAGS],OMF_BYTE
jnc short inotbyte
inc cl
sub ax,ax
mov al,fs:[si]
jmp short i_ret
inotbyte:
bt [di+OPERAND.OEFLAGS], OMF_OP32
jnc iword
add cl,4
LONG si
jmp short i_ret
iword:
add cl,2
UINT si
i_ret:
mov [di+OPERAND.ADDRESS],eax
mov ax,cx
pop cx
ret
Immediate ENDP
;Find a binary 0, stick whatever is in AL there, and put a 0 after that.
MnemonicChar PROC
push di
mov di,offset nmmnemonic
mc2:
inc di
cmp BYTE PTR [di-1],0
jnz mc2
mov [di-1],al
mov BYTE PTR [di],0
pop di
ret
MnemonicChar ENDP
;/* op 1- word reg from bits 0 - 2 of opcode */
op1 PROC
btr [di+OPERAND.OEFLAGS],OMF_BYTE
mov al,fs:[si]
B02
call SetReg
sub ax,ax
ret
op1 ENDP
;/* Op2 acc, reg bits 0-2 of opcode */
op2 PROC
btr [di+OPERAND.OEFLAGS],OMF_BYTE
btr [bx+OPERAND.OEFLAGS],OMF_BYTE
mov al,REG_EAX
call SetReg
mov di,bx
mov al,fs:[si]
and al,7
call SetReg
sub ax,ax
ret
op2 ENDP
;/* op3 - seg from b3-5 of opcode */
Op3 PROC
mov al,fs:[si]
B35
call SetSeg
sub ax,ax
ret
op3 ENDP
;/* op4 - REGRM with b1 of opcode set reg is dest else source */
op4 PROC
bt DWORD PTR fs:[si],1
jc short op4nox
xchg bx,di
op4nox:
mov [dest2],di
mov [source2],bx
call RegRM
ret
op4 ENDP
;/* op5 - use RM only */
op5 PROC
call ReadRM
ret
op5 ENDP
;/* op6 READRM for shift */
op6 PROC
call ReadRM
sub cx,cx
mov cl,al
mov di,bx
mov [di+OPERAND.CODE],OM_SHIFT
bt DWORD PTR fs:[si],4
jnc short op6cnt
bt DWORD PTR fs:[si],1
jnc op61
bts [di+OPERAND.OEFLAGS],OMF_CL
jmp short op6done
op61:
mov [di+OPERAND.ADDRESS],1
jmp short op6done
op6cnt:
movzx ecx,cx
movzx esi,si
movzx eax,BYTE PTR fs:[esi+ecx+2]
inc cl
mov [di+OPERAND.ADDRESS],eax
op6done:
mov ax,cx
ret
op6 ENDP
;/* op 7 regrm with reg dest */
op7 PROC
mov [dest2],di
mov [source2],bx
call RegRM
ret
op7 ENDP
;/* OP8 - word regrm with reg dest */
op8 PROC
btr [di+OPERAND.OEFLAGS],OMF_BYTE
btr [bx+OPERAND.OEFLAGS],OMF_BYTE
jmp op7
op8 ENDP
;/* op 9 - interrupts */
op9 PROC
mov [reqsPtrSizeOvride],FALSE
sub eax,eax
mov al,3
bt DWORD PTR fs:[si],0
jnc short op9int3
mov al,fs:[si+1]
op9int3:
mov [di+OPERAND.ADDRESS],eax
mov BYTE PTR [di+OPERAND.CODE],OM_INT
sub al,al
ret
op9 ENDP
;/* op 10, short relative branch */
op10 PROC
mov [reqsPtrSizeOvride],FALSE
mov [di+OPERAND.CODE],OM_SHORTBRANCH
movsx eax,BYTE PTR fs:[si+1]
inc ax
inc ax
add ax,[code_address]
mov [di+OPERAND.ADDRESS],eax
bt [di+OPERAND.OEFLAGS],OMF_OP32
jc short op10notword
and [di+OPERAND.ADDRESS],0ffffh
op10notword:
sub ax,ax
ret
op10 ENDP
;/* op 11 RM, immediate */
op11 PROC
call ReadRM
movzx cx,al
mov di,bx
push si
add si,cx
add si,2
call Immediate
add cl,al
pop si
mov ax,cx
ret
op11 ENDP
;/* op 12 - acc, immediate */
op12 PROC
mov al,REG_EAX
call SetReg
mov di,bx
inc si
call Immediate
dec si
ret
op12 ENDP
;/* op 13 absolute, acc*/
op13 PROC
sub cx,cx
mov [di+OPERAND.CODE],OM_ABSOLUTE
bt [di+OPERAND.OEFLAGS],OMF_ADR32
jnc short op13word
LONG si+1
inc cl
inc cl
jmp short op13fin
op13word:
UINT si+1
op13fin:
mov [di+OPERAND.ADDRESS],eax
mov di,bx
mov al,REG_EAX
call SetReg
mov ax,cx
ret
op13 ENDP
;/* op 14 - RM, immediate, b01 of opcode != 1 for byte */
op14 PROC
call ReadRM
movzx cx,al
mov al,fs:[si]
B01
jnz short op14checkbyte
bts [bx+OPERAND.OEFLAGS],OMF_BYTE
bts [di+OPERAND.OEFLAGS],OMF_BYTE
jmp short op14source
op14checkbyte:
btr [bx+OPERAND.OEFLAGS],OMF_BYTE
cmp al,1
jz short op14check2
bts [bx+OPERAND.OEFLAGS],OMF_BYTE
op14check2:
btr [di+OPERAND.OEFLAGS],OMF_BYTE
op14source:
mov di,bx
push si
add si,cx
add si,2
call Immediate
pop si
add cl,al
mov al,fs:[si]
B01
cmp al,3
jnz op14done
bt [di+OPERAND.OEFLAGS],OMF_BYTE
jnc op14done
bts [di+OPERAND.OEFLAGS],OMF_SIGNED
movzx eax,byte ptr [di+OPERAND.ADDRESS]
mov [di+OPERAND.ADDRESS],eax
op14done:
mov ax,cx
ret
op14 ENDP
;/* op 15 - acc, immediate, B3 of opcode clear for byte */
op15 PROC
mov al,fs:[si]
B02
call SetReg
bt DWORD PTR fs:[si],3
jnc op15byte
btr [di+OPERAND.OEFLAGS],OMF_BYTE
btr [bx+OPERAND.OEFLAGS],OMF_BYTE
jmp short op15source
op15byte:
bts [di+OPERAND.OEFLAGS],OMF_BYTE
bts [bx+OPERAND.OEFLAGS],OMF_BYTE
op15source:
mov di,bx
inc si
call Immediate
dec si
ret
op15 ENDP
;/* op 16 - seg,readrm, if B1 of opcode seg is dest else source */
op16 PROC
bt DWORD PTR fs:[si],1
jc noswap
xchg bx,di
noswap:
REG si
call SetSeg
mov di,bx
btr [di+OPERAND.OEFLAGS],OMF_BYTE
call ReadRM
ret
op16 ENDP
;/* op 17, far return */
op17 PROC
mov [reqsPtrSizeOvride],false
mov [di+OPERAND.CODE],OM_RETURN
btr [di+OPERAND.OEFLAGS],OMF_ADR32
btr [di+OPERAND.OEFLAGS],OMF_OP32
btr [di+OPERAND.OEFLAGS],OMF_BYTE
UINT si+1
mov [di+OPERAND.ADDRESS],eax
sub ax,ax
ret
op17 ENDP
;/* op 18, far branch/call */
op18 PROC
sub cx,cx
mov [reqsPtrSizeOvride],FALSE
mov [di+OPERAND.CODE],OM_FARBRANCH
btr [di+OPERAND.OEFLAGS],OMF_BYTE
bt [di+OPERAND.OEFLAGS],OMF_OP32
jnc short op18word
inc cl
inc cl
LONG si+1
jmp short op18fin
op18word:
UINT si+1
op18fin:
mov [di+OPERAND.ADDRESS],eax
movzx ecx,cx
movzx esi,si
UINT esi+ecx+3
mov [di+OPERAND.OESEG],ax
mov ax,cx
ret
op18 ENDP
;/* op 19 - ESC, mnem of bits 0-2 of opcode, imm,readrm */
op19 PROC
mov [di+OPERAND.CODE],OM_IMMEDIATE
bts [di+OPERAND.OEFLAGS],OMF_BYTE
mov al,fs:[si]
and al,7
shl al,3
mov ah,fs:[si+1]
shr ah,3
and ah,7
or al,ah
sub ah,ah
cwde
mov [di+ OPERAND.ADDRESS],eax
mov di,bx
call ReadRM
ret
op19 ENDP
;/* op 20 - long branch */
op20 PROC
sub eax,eax
mov [reqsPtrSizeOvride],FALSE
sub cx,cx
mov [di+OPERAND.CODE],OM_LONGBRANCH
bt [di+OPERAND.OEFLAGS],OMF_OP32
jnc short op20word
LONG si+1
inc cl
inc cl
jmp short op20fin
op20word:
UINT si+1
op20fin:
add ax,[code_address]
test [segs],SG_TWOBYTEOP
jz op20xx
inc ax
op20xx:
add ax,cx
add ax,3
bt [di+OPERAND.OEFLAGS],OMF_OP32
jc op20done
and eax,0ffffh
op20done:
mov [di+OPERAND.ADDRESS],eax
mov ax,cx
ret
op20 ENDP
;/* op21 acc,dx */
op21 PROC
mov al,REG_EAX
call SetReg
mov di,bx
btr [di+OPERAND.OEFLAGS],OMF_OP32
btr [di+OPERAND.OEFLAGS],OMF_BYTE
mov al,REG_DX
call SetReg
sub ax,ax
ret
op21 ENDP
;/* op22 - dx,acc */
op22 PROC
btr [di+OPERAND.OEFLAGS],OMF_OP32
btr [di+OPERAND.OEFLAGS],OMF_BYTE
mov al,REG_DX
call SetReg
mov di,bx
mov al,REG_EAX
call SetReg
sub ax,ax
ret
op22 ENDP
;/* op23 - port,acc where B1 of opcode set is port dest */
op23 PROC
bt DWORD PTR fs:[si],1
jc short op20NoSwap
xchg bx,di
op20noswap:
bts [di+OPERAND.OEFLAGS],OMF_BYTE
mov [di+OPERAND.CODE],OM_PORT
movzx eax,BYTE PTR fs:[si+1]
mov [di+OPERAND.ADDRESS],eax
mov di,bx
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -