; ; GRDP ; ; Copyright(c) LADsoft ; ; David Lindauer, gclind01@starbase.spd.louisville.edu ; ; ; 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 VERBOSE = 1 include dispatch.ase include opcodes.asi include operands.asi include options.ase include opcom.ase PUBLIC TabTo, ReadOverrides, DispatchOperands PUBLIC FormatDisassembly, FormatValue, Code_Address PUBLIC PutDword, PutWord,PutByte PUBLIC put2,put3,put4 SZ_QWORD =2 SZ_TBYTE= 4 .DATA code_address dw 0 dest2 dw 0 source2 dw 0 segs dw 0 extraoperand OPERAND ? source OPERAND ? dest OPERAND ? nmmnemonic db 10 DUP (?) strict db 0 .CODE strlen PROC push di push si push cx mov di,si mov cx,-1 sub al,al repnz scasb mov ax,cx neg ax dec 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 dgroup: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 [strict],FALSE mov [di + OPERAND.code],OM_SEGMENT mov [di + OPERAND.THEREG],al ret SetSeg ENDP SetReg PROC mov [strict],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 [strict],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 MnemonicChar PROC push di mov di,offset dgroup: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 [strict],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 [strict],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 [strict],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 [strict],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 [strict],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 mov al,REG_EAX call SetReg sub ax,ax ret op23 ENDP ;/* op 24 acc, absolute */ op24 PROC sub cx,cx mov al,REG_EAX call SetReg mov di,bx mov [di + OPERAND.CODE],OM_ABSOLUTE bt [di + OPERAND.OEFLAGS],OMF_ADR32 jnc short op24word inc cl inc cl LONG si+1 jmp short op24done op24word: UINT si+1 op24done: mov [di + OPERAND.ADDRESS],eax mov ax,cx ret op24 ENDP ;/* op 25 - immediate byte or word */ op25 PROC mov [strict],false bts [di + OPERAND.OEFLAGS],OMF_BYTE bt DWORD PTR fs:[si],1 jc short op25fin btr [di + OPERAND.OEFLAGS],OMF_BYTE op25fin: push si inc si call Immediate pop si ret op25 ENDP ;/* op 26, immediate 2byte,byte */ op26 PROC mov [strict],false btr [di + OPERAND.OEFLAGS],OMF_BYTE btr [di + OPERAND.OEFLAGS],OMF_OP32 push si inc si call Immediate mov di,bx bts [di + OPERAND.OEFLAGS],OMF_BYTE btr [di + OPERAND.OEFLAGS],OMF_OP32 inc si inc si call Immediate pop si sub ax,ax ret op26 ENDP ;/* op 27 - string */ op27 PROC mov al,'d' bt [di + OPERAND.OEFLAGS],OMF_OP32 jc short op27pc mov al,'w' op27pc: call MnemonicChar sub ax,ax ret op27 ENDP ;/* op 28 - source = REG, dest = RM */ op28 PROC REG si call SetReg mov di,bx RM si call SetReg sub ax,ax ret op28 ENDP ;/* op 29 - dest = RM, immediate */ op29 PROC bts [di + OPERAND.OEFLAGS],OMF_BYTE RM si call SetReg mov di,bx bts [di + OPERAND.OEFLAGS],OMF_BYTE push si inc si inc si call Immediate pop si sub ax,ax ret op29 ENDP ;/* op30 - RM, shift with B3 of stream selecting COUNT or CL*/ op30 PROC call ReadRM mov cx,ax mov di,bx mov [di + OPERAND.CODE],OM_SHIFT bt DWORD PTR fs:[si],3 jnc op30cl movzx esi,si movzx ecx,cx movzx eax,byte ptr [esi+ecx+2] mov [di + OPERAND.ADDRESS],eax inc cx jmp short op30done op30cl: bts [di + OPERAND.OEFLAGS],OMF_CL op30done: mov ax,cx ret op30 ENDP ;/* op 31- reg, rm, count where B1 of opcode = byte/word */ op31 PROC call copyextra REG si call SetReg mov di,bx call ReadRM mov cx,ax mov di,offset dgroup:extraoperand bts [di + OPERAND.OEFLAGS],OMF_BYTE bt DWORD PTR fs:[si],1 jc short op31byte btr [di + OPERAND.OEFLAGS],OMF_BYTE op31byte: push si inc si inc si call Immediate pop si add ax,cx ret op31 ENDP ;/* op32 - 386 special regs */ op32 PROC mov cx,WORD PTR fs:[si] and cx,0c005h cmp cx,0c000h mov al,OM_CRX jz short op32gotype cmp cx,0c001h mov al,OM_DRX jz short op32gotype cmp cx,0c004h mov al,OM_TRX jz short op32gotype mov al,OM_SUD op32gotype: btr [di + OPERAND.OEFLAGS],OMF_BYTE btr [bx + OPERAND.OEFLAGS],OMF_BYTE bts [di + OPERAND.OEFLAGS],OMF_OP32 bts [bx + OPERAND.OEFLAGS],OMF_OP32 bt DWORD PTR fs:[si],1 jc op32noswap xchg bx,di op32noswap: mov [di + OPERAND.CODE],al REG si mov [di + OPERAND.THEREG],al mov di,bx RM si call SetReg sub ax,ax ret op32 ENDP ;/* op33 - reg,rm,shiftcnt where B3 = reg source, b0 = shift cl */ op33 PROC btr [di + OPERAND.OEFLAGS],OMF_BYTE btr [bx + OPERAND.OEFLAGS],OMF_BYTE call CopyExtra call ReadRM mov cx,ax REG si mov di,bx call SetReg mov di,offset dgroup:extraoperand mov [di + OPERAND.CODE],OM_SHIFT bt DWORD PTR fs:[si],0 jnc short getofs bts [di + OPERAND.OEFLAGS],OMF_CL jmp short op33done getofs: movzx ecx,cx movzx esi,si movzx eax,BYTE PTR [esi+ecx+2] op33done: mov ax,cx ret op33 ENDP ;/* op 34 - push & pop word, also no strict single args */ op34 PROC call ReadRM ret op34 ENDP ;/* op 35 -floating RM */ op35 PROC mov [strict],FALSE mov ax,fs:[si] and ax,0d0deh cmp ax,0d0deh jnz short op35nop mov al,'p' call MnemonicChar op35nop: MODX si cmp al,3 jnz short op35fsttab bts [di + OPERAND.OEFLAGS],OMF_FST jmp short op35fin op35fsttab: bts [di + OPERAND.OEFLAGS],OMF_FSTTAB movzx eax,BYTE PTR fs:[di] B12 shl eax, OM_FTAB or [di + OPERAND.OEFLAGS],ax op35fin: call ReadRM ret op35 ENDP ;/* op 36 - sized floating RM */ op36 PROC mov cx,SZ_QWORD mov [strict],FALSE mov ax,fs:[si] and ax,2807h cmp ax,2807h jz short op36notbyte mov cx,SZ_TBYTE op36notbyte: bts [di + OPERAND.OEFLAGS],OMF_FSTTAB shl cx,OM_FTAB or [di + OPERAND.OEFLAGS],cx call ReadRM ret op36 ENDP ;/* OP 37 - floating MATH */ op37 PROC sub dx,dx mov ax,fs:[si] and ax,0e0dch cmp ax,0e0dch jnz short op37noflop inc dl op37noflop: cmp ah,0e0h jc op37nor REG si xor al,dl and al,1 jz short op37nor mov al,'r' call MnemonicChar op37nor: MODX si cmp al,3 jz op37reg bts [di + OPERAND.OEFLAGS],OMF_FSTTAB movzx ax,fs:[si] B12 shl eax,OM_FTAB or [di + OPERAND.OEFLAGS],ax call ReadRM jmp short op37done op37reg: test BYTE PTR fs:[si],2 jz short op37nop mov al,'p' call MnemonicChar op37nop: bt DWORD PTR fs:[si],2 jc short op37noswap xchg bx,di RM si call SetReg bts [di + OPERAND.OEFLAGS],OMF_FST mov di,bx bts [di + OPERAND.OEFLAGS],OMF_FST sub al,al call SetReg sub ax,ax op37done: ret op37noswap: RM si call SetReg bts [di + OPERAND.OEFLAGS],OMF_FST sub ax,ax ret op37 ENDP op38 PROC mov [strict],FALSE bts [di + OPERAND.OEFLAGS],OMF_FSTTAB call ReadRM ret op38 ENDP ;/* OP39 - word regrm with reg source */ op39 PROC btr [di + OPERAND.OEFLAGS],OMF_BYTE btr [bx + OPERAND.OEFLAGS],OMF_BYTE call op40 ret op39 ENDP ;/* op 40 regrm with reg source */ op40 PROC mov [dest2],bx mov [source2],di call RegRM ret op40 ENDP ;/* op 41 reg, bitnum */ op41 PROC btr [di+OPERAND.OEFLAGS],OMF_BYTE call ReadRM mov cx,ax mov di,bx bts [di+OPERAND.OEFLAGS],OMF_BYTE push si add si,cx add si,2 call Immediate pop si mov ax,cx ret op41 ENDP ;/* op 42 mixed regrm with reg dest & strictness enforced */ op42 PROC mov [dest2],di mov [source2],bx btr [di + OPERAND.OEFLAGS],OMF_BYTE btr [bx + OPERAND.OEFLAGS],OMF_OP32 call RegRM mov [strict],TRUE ret op42 ENDP ;/* op 43 CWDE op43 PROC bt [di + OPERAND.OEFLAGS],OMF_OP32 jnc short op43nochng push si mov si,offset dgroup:nmmnemonic + 1 mov eax,"wde" call put3 mov BYTE PTR [si],0 pop si sub ax,ax op43nochng: ret op43 ENDP ;/* op 44 BSWAP op44 PROC btr [di + OPERAND.OEFLAGS],OMF_BYTE mov al,fs:[si] and al,7 call SetReg sub ax,ax ret op44 ENDP ;/* OP45 - any regrm with reg dest */ op45 PROC bt word ptr [si-1],0 jc op45nb btr [di + OPERAND.OEFLAGS],OMF_BYTE btr [bx + OPERAND.OEFLAGS],OMF_BYTE op45nb: XCHG BX,DI REG si call SetReg XCHG bx,di call ReadRM ret op45 ENDP ;/* op 46 - no strict single args */ op46 PROC btr [di+OPERAND.OEFLAGS],OMF_OP32 mov [strict],false call ReadRM ret op46 ENDP ;/* op47 - AX */ op47 PROC btr [di + OPERAND.OEFLAGS],OMF_OP32 btr [di + OPERAND.OEFLAGS],OMF_BYTE sub al,al call SetReg sub ax,ax ret op47 ENDP ReadOverrides PROC ro_lp: sub ax,ax lods BYTE PTR fs:[si] test [opt32ins],1 jz testseg cmp al,64h jc short testseg cmp al,68h jnc short testseg sub al,64h mov bx,SG_FS ro_found: mov cl,al shl bx,cl or [segs],bx jmp short ro_lp testseg: push ax and al,0e7h cmp al,026h pop ax jnz testrep mov bx,1 shr ax,3 and al,3 jmp ro_found testrep: sub al,0f2h cmp al,2 jnc ro_done mov bx,SG_REPNZ jmp short ro_found ro_done: dec si ret ReadOverrides ENDP DispatchOperands PROC mov dx,ax push bx mov di,offset dgroup:nmmnemonic push si mov si,[bx + OPCODE.MNEMONIC] call strcpy pop si mov [strict],TRUE movzx ax,[bx + OPCODE.OPERANDS] push ax mov di,offset dgroup:dest mov bx,offset dgroup:source cmp BYTE PTR fs:[si-1],0fh jnz short notwobyte or [segs],SG_TWOBYTEOP notwobyte: mov ax,offset dgroup:extraoperand movzx eax,ax mov [eax + OPERAND.CODE],0 mov [di + OPERAND.CODE],0 mov [bx + OPERAND.CODE],0 mov [di + OPERAND.OEFLAGS],0 mov [bx + OPERAND.OEFLAGS],0 bt DWORD PTR fs:[si],0 jc notbyte bts [di + OPERAND.OEFLAGS],OMF_BYTE bts [bx + OPERAND.OEFLAGS],OMF_BYTE notbyte: or dx,dx jz short xadr16 bts [di + OPERAND.OEFLAGS],OMF_ADR32 bts [bx + OPERAND.OEFLAGS],OMF_ADR32 bts [di + OPERAND.OEFLAGS],OMF_OP32 bts [bx + OPERAND.OEFLAGS],OMF_OP32 xadr16: test [segs],SG_ADRSIZ jz do_word1 btc [di + OPERAND.OEFLAGS],OMF_ADR32 btc [bx + OPERAND.OEFLAGS],OMF_ADR32 do_word1: test [segs],SG_OPSIZ jz do_word2 btc [di + OPERAND.OEFLAGS],OMF_OP32 btc [bx + OPERAND.OEFLAGS],OMF_OP32 do_word2: pop ax or ax,ax jz nodispatch dec al push 0 call TableDispatch dw 46 dw OP1, OP2, OP3, OP4, OP5, OP6, OP7, OP8, OP9, OP10 dw OP11, OP12, OP13, OP14, OP15, OP16, OP17, OP18, OP19, OP20 dw OP21, OP22, OP23, OP24, OP25, OP26, OP27, OP28, OP29, OP30 dw OP31, OP32, OP33, OP34, OP35, OP36, OP37, OP38, OP39, OP40 dw OP41, OP42, OP43, OP44, OP45, OP46, OP47 movzx ax,al add si,ax nodispatch: pop bx movzx ax,[bx + OPCODE.OCLENGTH] add si,ax ret DispatchOperands ENDP dostrict PROC push di push si test [strict],-1 jz short floatstrict bt [di + OPERAND.OEFLAGS],OMF_BYTE jnc chkdwptr mov di,si mov si,offset dgroup:byptr jmp short strictend chkdwptr: bt [di + OPERAND.OEFLAGS],OMF_OP32 mov di,si jnc mkwordptr mov si,offset dgroup:dwptr jmp short strictend mkwordptr: mov si,offset dgroup:woptr jmp short strictend floatstrict: bt [di + OPERAND.OEFLAGS],OMF_FSTTAB jnc strictdone mov ax,[di + OPERAND.OEFLAGS] shr ax,OM_FTAB and ax,7 mov di,si push di mov si,offset dgroup:sts movzx esi,si movzx eax,ax mov si,[esi + eax * 2] call strcat mov si,offset dgroup:theptr pop di strictend: call strcat strictdone: pop si call strlen add si,ax pop di ret DoStrict ENDP TabTo PROC movzx eax,al mov cx,ax call strlen xchg ax,cx sub ax,cx jnc tt_noover add ax,cx add si,ax jmp short tt_done tt_noover: add si,cx mov cx,ax or cx,cx jnz tabtlp inc cx tabtlp: mov BYTE PTR [si],' ' inc si loop tabtlp tt_done: mov BYTE PTR [si],0 ret TabTo ENDP GetST PROC push edi mov al,[di + OPERAND.THEREG] push ax xchg si,di mov si,offset dgroup:stsreg call strcpy pop ax add al,'0' dec di stosb mov al,')' stosb sub al,al stosb dec di xchg si,di pop edi ret GetST ENDP GetStdReg PROC push edi or al,al jnz short gsrnoe mov BYTE PTR [si],'e' inc si gsrnoe: mov di,offset dgroup:regs movzx edi,di movzx ecx,cx mov ax,[edi + ecx *2] mov [si],al inc si mov [si],ah inc si mov BYTE PTR [si],0 pop edi ret GetStdReg ENDP GetReg PROC movzx cx,al sub al,al inc al bt [di + OPERAND.OEFLAGS],OMF_BYTE jc short grno32 bt [di + OPERAND.OEFLAGS],OMF_OP32 jnc short grno32 dec al grno32: bt [di + OPERAND.OEFLAGS],OMF_BYTE jc short isbyte or cl,8 isbyte: call GetStdReg ret GetReg ENDP GetSpecial PROC mov al,[bx] mov [si],al inc si inc bx mov al,[bx] mov [si],al inc si inc bx movzx eax,[di + OPERAND.THEREG] movzx ebx,bx mov al,[ebx +eax] mov [si],al inc si mov BYTE PTR [si],0 ret GetSpecial ENDP GetSeg PROC push edi push ax mov di,offset dgroup:psegs movzx edi,di movzx ecx,cx mov ax,[edi + ecx *2] mov [si],al inc si mov [si],ah inc si pop ax or al,al mov al,':' jz short nocolon mov [si],al inc si nocolon: mov BYTE PTR [si],0 pop edi ret GetSeg ENDP SegOverride PROC mov al,1 sub cx,cx test [segs],SG_ES jz short so_testcs call GetSeg so_testcs: inc cx test [segs],SG_CS jz short so_testss call GetSeg so_testss: inc cx test [segs],SG_SS jz short so_testds call GetSeg so_testds: inc cx test [segs],SG_DS jz short so_testfs call GetSeg so_testfs: inc cx test [segs],SG_FS jz short so_testgs call GetSeg so_testgs: inc cx test [segs],SG_GS jz short so_done call GetSeg so_done: mov [segs],0 ret SegOverride ENDP Scaled PROC push DWORD PTR [di + OPERAND.OEFLAGS] btr [di + OPERAND.OEFLAGS],OMF_BYTE bts [di + OPERAND.OEFLAGS],OMF_OP32 or al,al jz short notbased sub al,al mov al,[di + OPERAND.THEREG] call GetReg notbased: bt [di + OPERAND.OEFLAGS],OMF_SCALED jnc short notscaled2 movzx cx,[di + OPERAND.SCALE] mov ax,cx add cx,cx add cx,ax add cx,offset dgroup:scales movzx ecx,cx mov eax,[ecx] call put3 or al,1 mov al,[di + OPERAND.SCALEREG] call GetReg notscaled2: pop DWORD PTR [di + OPERAND.OEFLAGS] ret Scaled ENDP FOM_FSTREG PROC mov di,offset dgroup:stalone call strcat ret FOM_FSTREG ENDP FOM_CRX PROC mov bx,offset dgroup:crreg call GetSpecial ret FOM_CRX ENDP FOM_DRX PROC mov bx,offset dgroup:drreg call GetSpecial ret FOM_DRX ENDP FOM_TRX PROC mov bx,offset dgroup:trreg call GetSpecial ret FOM_TRX ENDP FOM_SUD PROC mov bx,offset dgroup:sudreg call GetSpecial ret FOM_SUD ENDP FOM_PORT PROC mov al,SY_PORT format: call FormatValue ret FOM_PORT ENDP FOM_INT PROC mov al,SY_INTR jmp short format FOM_INT ENDP FOM_SHIFT PROC bt [di + OPERAND.OEFLAGS],OMF_CL jnc fos_notcl mov ax,"cl" call put2 ret fos_notcl: cmp [di + OPERAND.ADDRESS],1 mov al,SY_SHIFT jnz format mov BYTE PTR [si],'1' inc si mov BYTE PTR [si],0 ret FOM_SHIFT ENDP FOM_RETURN PROC mov al,SY_RETURN jmp format FOM_RETURN ENDP FOM_SHORTBRANCH PROC mov al,SY_SHORTBRANCH jmp format FOM_SHORTBRANCH ENDP FOM_LONGBRANCH PROC mov al,SY_LONGBRANCH jmp format FOM_LONGBRANCH ENDP FOM_FARBRANCH PROC mov al,SY_SEGMENT call format mov BYTE PTR [si],':' inc si mov al,SY_ABSBRANCH call format ret FOM_FARBRANCH ENDP FOM_ABSOLUTE PROC call DoStrict call SegOverride mov BYTE PTR [si],'[' inc si mov BYTE PTR [si],0 bt [di + OPERAND.OEFLAGS],OMF_SCALED jnc foa_notscaled mov al,SY_WORDOFS call FormatValue sub ax,ax call Scaled jmp short foa_finish foa_notscaled: mov al,SY_ABSOLUTE call FormatValue foa_finish: mov BYTE PTR [si],']' inc si mov BYTE PTR [si],0 ret FOM_ABSOLUTE ENDP FOM_IMMEDIATE PROC bt [di + OPERAND.OEFLAGS],OMF_BYTE mov al,SY_WORDIMM jnc short absformat mov al,SY_SIGNEDIMM bt [di + OPERAND.OEFLAGS],SY_SIGNEDIMM jc short absformat mov al,SY_SIGNEDIMM absformat: jmp format FOM_IMMEDIATE ENDP FOM_REG PROC bt [di + OPERAND.OEFLAGS],OMF_FST jnc short foreg call GetST ret foreg: mov al,[di + OPERAND.THEREG] call GetReg ret FOM_REG ENDP FOM_BASED PROC call DoStrict call SegOverride mov BYTE PTR [si],'[' inc si mov BYTE PTR [si],0 bt [di + OPERAND.OEFLAGS],OMF_ADR32 jnc fob_notscaled mov al,1 call scaled jmp short fob2 fob_notscaled: push di push si movzx eax,BYTE PTR [di + OPERAND.THEREG] xchg si,di mov si,offset dgroup:based movzx esi,si movzx ecx,cx mov si,[esi + eax * 2] call strcpy pop si pop di call strlen add si,ax fob2: test [di + OPERAND.OEFLAGS],OMF_OFFSET jz short fob_noofs bt [di + OPERAND.OEFLAGS],OMF_SIGNED_OFFSET mov al,SY_SIGNEDOFS jc fob_format mov al,SY_WORDOFS bt [di + OPERAND.OEFLAGS],OMF_WORD_OFFSET jc fob_format mov al,SY_BYTEOFS fob_format: call FormatValue fob_noofs: mov BYTE PTR [si],']' inc si mov BYTE PTR [si],0 ret FOM_BASED ENDP FOM_SEGMENT PROC movzx cx,[di + OPERAND.THEREG] sub ax,ax call GetSeg ret FOM_SEGMENT ENDP PutOperand PROC call strlen add si,ax mov al,[di + OPERAND.CODE] dec al js short po_none push 0 call TableDispatch dw 17 dw fom_based dw fom_segment dw fom_reg dw fom_immediate dw fom_absolute dw fom_farbranch dw fom_longbranch dw fom_shortbranch dw fom_return dw fom_shift dw fom_int dw fom_port dw fom_sud dw 0 dw fom_trx dw fom_drx dw fom_crx dw fom_fstreg po_none: ret PutOperand ENDP FormatDisassembly PROC ENTER 256,0 push si lea di,[bp-256] mov BYTE PTR [di],0 test [segs],SG_REPZ push di jz fd_notrepz mov si,offset dgroup:st_repz call strcpy fd_notrepz: test [segs],SG_REPNZ jz fd_notrepnz mov si,offset dgroup:st_repnz call strcpy fd_notrepnz: pop di xchg si,di call strlen add si,ax xchg si,di mov si,offset dgroup:nmmnemonic call strcat lea si,[bp-256] sub ax,ax mov al,TAB_ARGPOS call TabTo mov di,offset dgroup:dest call PutOperand mov di,offset dgroup:source test [di + OPERAND.CODE],-1 jz short nosource mov BYTE PTR [si],',' inc si mov BYTE PTR [si],0 call PutOperand nosource: mov di,offset dgroup:extraoperand test [di + OPERAND.CODE],-1 jz short noextra mov BYTE PTR [si],',' inc si mov BYTE PTR [si],0 call PutOperand noextra: pop si mov BYTE PTR [si],0 call SegOverride mov di,si lea si,[bp-256] call strcat LEAVE ret FormatDisassembly ENDP putdword: push eax ; To print a dword shr eax,16 ; Print the high 16 bits call putword pop eax ; And the low 16 bits putword: push ax ; To print a word mov al,ah ; Print the high byte call putbyte pop ax ; And the low byte putbyte: push ax ; To print a byte shr ax,4 ; Print the high nibble call putnibble pop ax ; And the low nibble putnibble: and al,0fh ; Get a nibble add al,'0' ; Make it numeric cmp al,'9' ; If supposed to be alphabetic jle onib add al,7 ; Add 7 onib: mov [si],al inc si ret putwordox: bt [di + OPERAND.OEFLAGS],OMF_OP32 jnc putword jmp putdword putwordax: bt [di + OPERAND.OEFLAGS],OMF_ADR32 jnc putword jmp putdword ABSX PROC bt eax,31 jnc noabs neg eax noabs: ret ABSX ENDP FSY_SIGNEDOFS PROC bt [di + OPERAND.ADDRESS],31 mov al,'+' jnc fso_pos mov al,'-' fso_pos: mov byte ptr [si],al inc si mov eax,[di + OPERAND.ADDRESS] call ABSX call putbyte ret FSY_SIGNEDOFS ENDP FSY_WORDOFS PROC mov byte ptr [si],'+' inc si mov eax,[di + OPERAND.ADDRESS] call putwordax ret FSY_WORDOFS ENDP FSY_BYTEOFS PROC mov byte ptr [si],'+' inc si mov eax,[di + OPERAND.ADDRESS] call putbyte ret FSY_BYTEOFS ENDP FSY_ABSOLUTE PROC mov eax,[di + OPERAND.ADDRESS] call putwordax ret FSY_ABSOLUTE ENDP FSY_SIGNEDIMM PROC bt [di + OPERAND.ADDRESS],31 mov al,'+' jnc fsi_pos mov al,'-' fsi_pos: mov byte ptr [si],al inc si mov eax,[di + OPERAND.ADDRESS] call ABSX call putbyte ret FSY_SIGNEDIMM ENDP FSY_WORDIMM PROC mov eax,[di + OPERAND.ADDRESS] call putwordox ret FSY_WORDIMM ENDP FSY_BYTEIMM PROC mov eax,[di + OPERAND.ADDRESS] call putbyte ret FSY_BYTEIMM ENDP FSY_PORT PROC mov eax,[di + OPERAND.ADDRESS] call putbyte ret FSY_PORT ENDP FSY_INTR PROC mov eax,[di + OPERAND.ADDRESS] call putbyte ret FSY_INTR ENDP FSY_RETURN PROC mov eax,[di + OPERAND.ADDRESS] call putword ret FSY_RETURN ENDP FSY_ABSBRANCH PROC mov eax,[di + OPERAND.ADDRESS] call putword ret FSY_ABSBRANCH ENDP FSY_LONGBRANCH PROC mov eax,[di + OPERAND.ADDRESS] call putword ret FSY_LONGBRANCH ENDP FSY_SHORTBRANCH PROC mov eax,[di + OPERAND.ADDRESS] call putword ret FSY_SHORTBRANCH ENDP FSY_SHIFT PROC mov eax,[di + OPERAND.ADDRESS] call putbyte ret FSY_SHIFT ENDP FSY_SEGMENT PROC mov ax,[di + OPERAND.OESEG] call putword ret FSY_SEGMENT ENDP FormatValue PROC dec al push 0 call TableDispatch dw 14 dw FSY_SIGNEDOFS,FSY_WORDOFS,FSY_BYTEOFS,FSY_ABSOLUTE dw FSY_SIGNEDIMM,FSY_WORDIMM,FSY_BYTEIMM,FSY_PORT dw FSY_INTR,FSY_RETURN,FSY_ABSBRANCH,FSY_LONGBRANCH dw FSY_SHORTBRANCH,FSY_SHIFT,FSY_SEGMENT mov byte ptr [si],0 ret FormatValue ENDP END