;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISASSEMBLER ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TODO: prepare to work independently from debugger ;----------------------------------------------------------------------------- ; Read next byte for disassembly ; ; out: AL = byte disasm_get_byte: push ecx mov ecx, [disasm_cur_pos] sub ecx, [disasm_start_pos] cmp ecx, [disasm_buf_size] jae disasm_err mov al, [disasm_buffer+ecx] pop ecx inc [disasm_cur_pos] ret ;----------------------------------------------------------------------------- ; Read next word for disassembly ; ; out: AX = word disasm_get_word: push ecx mov ecx, [disasm_cur_pos] sub ecx, [disasm_start_pos] inc ecx cmp ecx, [disasm_buf_size] jae disasm_err mov ax, word [disasm_buffer-1+ecx] pop ecx add [disasm_cur_pos], 2 ret ;----------------------------------------------------------------------------- ; Read next dword for disassembly ; ; out: EAX = dword disasm_get_dword: push ecx mov ecx, [disasm_cur_pos] sub ecx, [disasm_start_pos] add ecx, 3 cmp ecx, [disasm_buf_size] jae disasm_err mov eax, dword [disasm_buffer-3+ecx] pop ecx add [disasm_cur_pos], 4 ret ;----------------------------------------------------------------------------- disasm_err: mov esp, ebp ; TODO: make it local? stc_ret: stc ret ;----------------------------------------------------------------------------- ; Exit from disassembly loop disasm_ret: mov esp, ebp and byte [edi], 0 ret ;----------------------------------------------------------------------------- ; Disassembly one instruction ; ; Read data, in loop, to read multibyte instruction opcodes disasm_instr: mov ebp, esp cmp [debuggee_pid], 0 jz stc_ret mov edi, disasm_string xor ecx, ecx ; TODO: make it local? ; ecx=flags (IN or OUT?) disasm_loop1: xor eax, eax call disasm_get_byte jmp dword [disasm_table_1 + eax*4] ;----------------------------------------------------------------------------- cop0: clock: csegcs: csegds: cseges: csegss: csegfs: cseggs: mov esi, cmd1 iglobal cmd1: db 0x2E,3,'cs:' db 0x36,3,'ss:' db 0x3E,3,'ds:' db 0x26,3,'es:' db 0x64,3,'fs:' db 0x65,3,'gs:' db 0x06,10,'push es' db 0x07,10,'pop es' db 0x0E,10,'push cs' db 0x16,10,'push ss' db 0x17,10,'pop ss' db 0x1E,10,'push ds' db 0x1F,10,'pop ds' db 0x27,3,'daa' db 0x2F,3,'das' db 0x37,3,'aaa' db 0x3F,3,'aas' db 0x60,6,0,'pusha' db 0x61,5,0,'popa' db 0x90,3,'nop' db 0x9B,5,'fwait' db 0x9C,6,0,'pushf' db 0x9D,5,0,'popf' db 0x9E,4,'sahf' db 0x9F,4,'lahf' db 0xA4,5,'movsb' db 0xA5,5,0,'movs' db 0xA6,5,'cmpsb' db 0xA7,5,0,'cmps' db 0xAA,5,'stosb' db 0xAB,5,0,'stos' db 0xAC,5,'lodsb' db 0xAD,5,0,'lods' db 0xAE,5,'scasb' db 0xAF,5,0,'scas' db 0xC3,3,'ret' db 0xC9,5,'leave' db 0xCC,4,'int3' db 0xF0,4,'lock' db 0xF5,3,'cmc' db 0xF8,3,'clc' db 0xF9,3,'stc' db 0xFA,3,'cli' db 0xFB,3,'sti' db 0xFC,3,'cld' db 0xFD,3,'std' cmd2: db 0x05,7,'syscall' db 0x06,4,'clts' db 0x31,5,'rdtsc' db 0x34,8,'sysenter' db 0xA2,5,'cpuid' db 0x77,4,'emms' endg jmp @f ;----------------------------------------------------------------------------- ccpuid: crdtsc: cemms: cop0_F: mov esi, cmd2 @@: cmp al, [esi] jz .found inc esi movzx edx, byte [esi] inc esi add esi, edx jmp @b .found: inc esi lodsb cmp byte [esi], 0 jz @f movzx ecx, al disasm_1: rep movsb and byte [edi], 0 ret @@: mov dl, ch movzx ecx, al dec ecx inc esi rep movsb test dl, 1 mov al, 'w' jnz @f mov al, 'd' @@: stosb and byte [edi], 0 ret c67: or ch, 2 jmp disasm_loop1 c66: or ch, 1 jmp disasm_loop1 ;----------------------------------------------------------------------------- cxlat: cunk: cerr: mov eax, '???' stosd clc ret cF: call disasm_get_byte jmp dword [disasm_table_2 + eax*4] ;----------------------------------------------------------------------------- ; Parse operand prefixes crep: push [disasm_cur_pos] call disasm_get_byte cmp al, 0x0F jz .sse mov dl, al mov eax, 'rep ' stosd mov al, dl @@: and eax, not 1 cmp al, 0x66 jnz @f call disasm_get_byte mov dl, al jmp @b @@: cmp al, 0xA6 jz .repz cmp al, 0xAE jz .repz cmp al, 0xA4 jz .prefix cmp al, 0xAA jz .prefix cmp al, 0xAC jz .prefix cmp al, 0x6C jz .prefix cmp al, 0x6E jz .prefix .noprefix: pop [disasm_cur_pos] and byte [edi-1], 0 ret .repz: mov byte [edi-1], 'z' mov al, ' ' stosb .prefix: pop [disasm_cur_pos] jmp disasm_loop1 .sse: pop eax call disasm_get_byte ;----------------------------------------------------------------------------- iglobal rep_sse_cmds: db 0x58,3,'add' db 0xC2,3,'cmp' db 0,0 endg mov esi, rep_sse_cmds+1 @@: movzx edx, byte [esi] cmp al, [esi-1] jz @f lea esi, [esi+edx+2] cmp byte [esi], 0 jnz @b sub [disasm_cur_pos], 2 mov eax, 'rep' stosd ret @@: push ecx mov ecx, edx inc esi rep movsb pop ecx mov al, 's' stosb jmp rep_sse_final ;----------------------------------------------------------------------------- crepnz: call disasm_get_byte cmp al, 0x0F jz .sse mov dl, al mov eax, 'repn' stosd mov al, 'z' stosb mov al, ' ' stosb movzx eax, dl cmp al, 0x6C jb crep.noprefix cmp al, 0x6F jbe .prefix cmp al, 0xA4 jb crep.noprefix cmp al, 0xA7 jbe .prefix cmp al, 0xAA jb crep.noprefix cmp al, 0xAF ja crep.noprefix .prefix: jmp cop0 .sse: call disasm_get_byte mov esi, rep_sse_cmds+1 @@: movzx edx, byte [esi] cmp al, [esi-1] jz .found0 lea esi, [esi+edx+2] cmp byte [esi], 0 jnz @b mov esi, sse_cmds2+1 @@: movzx edx, byte [esi] cmp al, [esi-1] jz .found1 lea esi, [esi+edx+2] cmp byte [esi], 0 jnz @b sub [disasm_cur_pos], 2 mov eax, 'repn' stosd mov al, 'z' stosb and byte [edi], 0 ret .found0: push ecx mov ecx, edx inc esi rep movsb pop ecx mov al, 's' stosb mov al, 'd' jmp rep_sse_final .found1: push ecx mov ecx, edx inc esi rep movsb pop ecx mov al, 'p' stosb mov al, 's' rep_sse_final: stosb push ecx push 5 pop ecx sub ecx, edx adc ecx, 1 mov al, ' ' rep stosb pop ecx or ch, 1 jmp disasm_mmx1 ;----------------------------------------------------------------------------- macro disasm_set_modew { test al, 1 jz @f or ch, 80h @@: } ;----------------------------------------------------------------------------- cmov2: disasm_set_modew ; mov r/m,i call disasm_get_byte dec [disasm_cur_pos] test al, 00111000b jnz cunk mov eax, 'mov ' stosd mov eax, ' ' stosd call disasm_readrmop mov ax, ', ' stosw xor eax, eax test ch, 80h jnz .1 call disasm_get_byte jmp .3 .1: test ch, 1 jnz .2 call disasm_get_dword jmp .3 .2: call disasm_get_word .3: call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- cret2: mov eax, 'ret ' stosd mov eax, ' ' stosd xor eax, eax jmp cmov2.2 ;----------------------------------------------------------------------------- disasm_write_num: push esi cmp eax, 0x80 jl .nosymb lea esi, [eax-1] test eax, esi jz .nosymb call find_symbol jc .nosymb @@: lodsb test al, al jz @f stosb jmp @b @@: pop esi ret .nosymb: pop esi push ecx eax inc edi @@: mov ecx, eax shr eax, 4 jz @f inc edi jmp @b @@: pop eax cmp ecx, 10 jb @f inc edi @@: push edi eax @@: mov ecx, eax and al, 0xF cmp al, 10 sbb al, 69h das dec edi mov [edi], al mov eax, ecx shr eax, 4 jnz @b cmp ecx, 10 jb @f mov byte [edi-1], '0' @@: pop eax edi ecx cmp eax, 10 jb @f mov byte [edi], 'h' inc edi @@: ret ;----------------------------------------------------------------------------- iglobal label disasm_regs32 dword label disasm_regs dword db 'eax',0 db 'ecx',0 db 'edx',0 db 'ebx',0 db 'esp',0 db 'ebp',0 db 'esi',0 db 'edi',0 disasm_regs16 dw 'ax','cx','dx','bx','sp','bp','si','di' disasm_regs8 dw 'al','cl','dl','bl','ah','ch','dh','bh' disasm_scale db '1248' endg ;----------------------------------------------------------------------------- disasm_readrmop: call disasm_get_byte test ch, 40h jnz .skip_size push eax and al, 0xC0 cmp al, 0xC0 pop eax jz .skip_size test ch, 80h jz .byte test ch, 1 jnz .word mov dword [edi], 'dwor' mov byte [edi+4], 'd' inc edi jmp @f .byte: test ch, 20h jz .qb mov byte [edi], 't' inc edi .qb: mov dword [edi], 'byte' jmp @f .word: test ch, 20h jz .qw mov byte [edi], 'q' inc edi .qw: mov dword [edi], 'word' @@: mov byte [edi+4], ' ' add edi, 5 .skip_size: test ch, 2 jnz disasm_readrmop16 push ecx movzx ecx, al and eax, 7 shr ecx, 6 jz .vmod0 jp .vmod3 mov byte [edi], '[' inc edi cmp al, 4 jz .sib1 mov eax, [disasm_regs+eax*4] stosd dec edi jmp @f .sib1: call .parse_sib @@: mov al, '+' stosb dec ecx jz .vmod1 call disasm_get_dword jmp @f .vmod1: call disasm_get_byte movsx eax, al @@: test eax, eax jns .2 neg eax mov byte [edi-1], '-' .2: call disasm_write_num .2a: mov al, ']' stosb pop ecx ret .vmod3: pop ecx test ch, 10h jnz .vmod3_mmi test ch, 80h jz .vmod3_byte test ch, 1 jnz .vmod3_word test ch, 20h jnz .vmod3_sti mov eax, [disasm_regs32+eax*4] stosd dec edi ret .vmod3_byte: mov ax, [disasm_regs8+eax*2] @@: stosw ret .vmod3_word: mov ax, [disasm_regs16+eax*2] jmp @b .vmod3_sti: mov word [edi], 'st' add al, '0' mov byte [edi+2], al add edi, 3 ret .vmod3_mmi: disasm_write_mmreg = $ test ch, 1 jz @f mov byte [edi], 'x' inc edi @@: mov word [edi], 'mm' add al, '0' mov byte [edi+2], al add edi, 3 ret .vmod0: mov byte [edi], '[' inc edi cmp al, 4 jz .sib2 cmp al, 5 jz .ofs32 mov eax, [disasm_regs+eax*4] stosd mov byte [edi-1], ']' pop ecx ret .ofs32: call disasm_get_dword jmp .2 .sib2: call .parse_sib mov al, ']' stosb pop ecx ret .parse_sib: call disasm_get_byte push edx mov dl, al mov dh, 0 and eax, 7 cmp al, 5 jnz @f jecxz .sib0 @@: mov eax, [disasm_regs+eax*4] stosd dec edi mov dh, 1 .sib0: mov al, dl shr eax, 3 and eax, 7 cmp al, 4 jz .sibret test dh, dh jz @f mov byte [edi], '+' inc edi @@: mov eax, [disasm_regs+eax*4] stosd dec edi shr dl, 6 jz @f mov al, '*' stosb movzx eax, dl mov al, [disasm_scale+eax] stosb @@: .sibret: test dh, dh jnz .sibret2 call disasm_get_dword cmp byte [edi-1], '[' jz @f mov byte [edi], '+' test eax, eax jns .sibns neg eax mov byte [edi], '-' .sibns: inc edi @@: call disasm_write_num .sibret2: pop edx ret ;----------------------------------------------------------------------------- iglobal disasm_rm16_1 dd 'bxsi','bxdi','bpsi','bpdi' disasm_rm16_2 dw 'si','di','bp','bx' endg ;----------------------------------------------------------------------------- disasm_readrmop16: push ecx movzx ecx, al and eax, 7 shr ecx, 6 jz .vmod0 jp disasm_readrmop.vmod3 ; mod=3 is the same in 16- and 32-bit code ; 1 or 2 mov byte [edi], '[' inc edi cmp al, 4 jae @f mov eax, [disasm_rm16_1+eax*4] stosw mov al, '+' stosb shr eax, 16 jmp .1 @@: mov eax, dword [disasm_rm16_2+eax*2-4*2] .1: stosw mov al, '+' stosb xor eax, eax dec ecx jnz .2 call disasm_get_byte cbw jmp @f .2: call disasm_get_word @@: test ax, ax jns @f mov byte [edi-1], '-' neg ax @@: call disasm_write_num .done1: mov al, ']' stosb pop ecx ret .vmod0: mov byte [edi], '[' inc edi cmp al, 6 jz .ofs16 cmp al, 4 jae @f mov eax, [disasm_rm16_1+eax*4] stosw mov al, '+' stosb shr eax, 16 jmp .3 @@: mov eax, dword [disasm_rm16_2+eax*2-4*2] .3: stosw jmp .done1 .ofs16: xor eax, eax call disasm_get_word call disasm_write_num jmp .done1 ;----------------------------------------------------------------------------- cpush21: mov eax, 'push' stosd mov eax, ' ' stosd disasm_i32: call disasm_get_dword call disasm_write_num and byte [edi], 0 ret cpush22: mov eax, 'push' stosd mov eax, ' ' stosd call disasm_get_byte movsx eax, al @@: call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- center: mov eax, 'ente' stosd mov eax, 'r ' stosd xor eax, eax call disasm_get_word call disasm_write_num mov al, ',' stosb mov al, ' ' stosb xor eax, eax call disasm_get_byte jmp @b ;----------------------------------------------------------------------------- cinc1: ; inc reg32 cdec1: ; dec reg32 cpush1: ; push reg32 cpop1: ; pop reg32 cbswap: ; bswap reg32 mov edx, eax and edx, 7 shr eax, 3 sub al, 8 mov esi, 'inc ' jz @f mov esi, 'dec ' dec al jz @f mov esi, 'push' dec al jz @f mov esi, 'pop ' dec al jz @f mov esi, 'bswa' @@: xchg eax, esi stosd mov eax, ' ' jz @f mov al, 'p' @@: stosd xchg eax, edx call disasm_write_reg1632 and byte [edi], 0 ret ;----------------------------------------------------------------------------- cxchg1: ; xchg eax,reg32 and eax, 7 xchg eax, edx mov eax, 'xchg' stosd mov eax, ' ' stosd xor eax, eax call disasm_write_reg1632 mov ax, ', ' stosw xchg eax, edx call disasm_write_reg1632 and byte [edi], 0 ret cint: mov eax, 'int ' stosd mov eax, ' ' stosd disasm_i8u: xor eax, eax call disasm_get_byte call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- cmov11: ; mov r8,i8 mov ecx, eax mov eax, 'mov ' stosd mov eax, ' ' stosd and ecx, 7 mov ax, [disasm_regs8+ecx*2] stosw mov ax, ', ' stosw jmp disasm_i8u ;----------------------------------------------------------------------------- cmov12: ; mov r32,i32 xchg eax, edx mov eax, 'mov ' stosd mov eax, ' ' stosd xchg eax, edx and eax, 7 call disasm_write_reg1632 mov ax, ', ' stosw jmp cmov2.1 ;----------------------------------------------------------------------------- iglobal disasm_shifts dd 'rol ','ror ','rcl ','rcr ','shl ','shr ','sal ','sar ' endg ;----------------------------------------------------------------------------- cshift2: ; shift r/m,1 = D0/D1 cshift3: ; shift r/m,cl = D2/D3 disasm_set_modew mov dl, al call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 mov eax, [disasm_shifts+eax*4] stosd mov eax, ' ' stosd call disasm_readrmop cmp dl, 0xD2 jb .s1 mov eax, ', cl' stosd and byte [edi], 0 ret .s1: mov eax, ', 1' stosd clc ret ;----------------------------------------------------------------------------- cshift1: ; shift r/m,i8 = C0/C1 disasm_set_modew call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 mov eax, [disasm_shifts+eax*4] stosd mov eax, ' ' stosd call disasm_readrmop mov ax, ', ' stosw jmp disasm_i8u ;----------------------------------------------------------------------------- caam: mov eax, 'aam ' jmp @f caad: mov eax, 'aad ' @@: stosd mov eax, ' ' stosd xor eax, eax call disasm_get_byte cmp al, 10 jz @f call disasm_write_num @@: and byte [edi], 0 ret ;----------------------------------------------------------------------------- cmov3: ; A0: mov al,[ofs32] ; A1: mov ax/eax,[ofs32] ; A2: mov [ofs32],al ; A3: mov [ofs32],ax/eax mov edx, 'mov ' xchg eax, edx stosd mov eax, ' ' stosd test dl, 2 jnz .1 call .write_acc mov ax, ', ' stosw call .write_ofs32 jmp .2 .1: call .write_ofs32 mov ax, ', ' stosw call .write_acc .2: and byte [edi], 0 ret .write_acc: test dl, 1 jz .8bit test ch, 1 jnz .16bit mov eax, 'eax' stosd dec edi ret .16bit: mov ax, 'ax' stosw ret .8bit: mov ax, 'al' stosw ret .write_ofs32: mov al, '[' stosb call disasm_get_dword call disasm_write_num mov al, ']' stosb ret ;----------------------------------------------------------------------------- disasm_write_reg: test ch, 80h jnz disasm_write_reg1632 mov ax, [disasm_regs8+eax*2] stosw ret ;----------------------------------------------------------------------------- disasm_write_reg1632: test ch, 1 jnz @f mov eax, [disasm_regs32+eax*4] stosd dec edi ret @@: mov ax, [disasm_regs16+eax*2] stosw ret ;----------------------------------------------------------------------------- ; 0F B6/B7 cmovzx: ; 0F BE/BF cmovsx: mov edx, eax disasm_set_modew mov eax, 'movz' cmp dl, 0xB8 jb @f mov eax, 'movs' @@: stosd mov eax, 'x ' stosd call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 call disasm_write_reg1632 mov ax, ', ' stosw or ch, 1 ; 2nd operand - 8 or 16 bits call disasm_readrmop and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal disasm_op2cmds dd 'add ','or ','adc ','sbb ','and ','sub ','xor ','cmp ' endg ;----------------------------------------------------------------------------- cop21: disasm_set_modew mov esi, 'test' cmp al, 0A8h jae @f shr al, 3 and eax, 7 mov esi, [disasm_op2cmds+eax*4] @@: xchg eax, esi stosd mov eax, ' ' stosd test ch, 80h jnz .1632 mov eax, 'al, ' stosd jmp disasm_i8u .1632: test ch, 1 jnz .16 mov eax, 'eax,' stosd mov al, ' ' stosb call disasm_get_dword jmp .x .16: mov eax, 'ax, ' stosd xor eax, eax call disasm_get_word .x: call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- carpl: xor edx, edx or ch, 0C1h mov eax, 'arpl' jmp cop22.d2 ;----------------------------------------------------------------------------- ccmpxchg: xor edx, edx disasm_set_modew or ch, 40h mov eax, 'cmpx' stosd mov eax, 'chg ' jmp cop22.d1 ;----------------------------------------------------------------------------- cbsf: cbsr: or ch, 80h ;----------------------------------------------------------------------------- cop22: disasm_set_modew or ch, 40h mov edx, eax mov esi, 'lea ' cmp al, 8Dh jz @f mov esi, 'imul' cmp al, 0xAF jz @f mov esi, 'bsf ' cmp al, 0BCh jz @f mov esi, 'bsr ' cmp al, 0BDh jz @f mov esi, 'mov ' cmp al, 88h jae @f mov esi, 'xchg' cmp al, 86h jae @f mov esi, 'test' cmp al, 84h jae @f shr al, 3 and eax, 7 mov esi, [disasm_op2cmds+eax*4] @@: xchg eax, esi .d2: stosd mov eax, ' ' .d1: stosd call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 cmp dl, 0x8D jz @f cmp dl, 0x86 jz @f cmp dl, 0x87 jz @f cmp dl, 0xBC jz @f cmp dl, 0xBD jz @f test dl, 2 jz .d0 @@: call disasm_write_reg mov ax, ', ' stosw call disasm_readrmop and byte [edi], 0 ret .d0: push eax call disasm_readrmop mov ax, ', ' stosw pop eax call disasm_write_reg and byte [edi], 0 ret ;----------------------------------------------------------------------------- cbound: mov edx, eax mov eax, 'boun' stosd mov eax, 'd ' or ch, 0xC0 jmp cop22.d1 ;----------------------------------------------------------------------------- cop23: disasm_set_modew xchg eax, edx call disasm_get_byte dec [disasm_cur_pos] shr eax, 3 and eax, 7 mov eax, [disasm_op2cmds+eax*4] ctest: stosd mov eax, ' ' stosd call disasm_readrmop mov ax, ', ' stosw test ch, 80h jz .i8 cmp dl, 83h jz .i8 test ch, 1 jnz .i16 call disasm_get_dword jmp .ic .i8: xor eax, eax call disasm_get_byte cmp dl, 83h jnz .ic movsx eax, al jmp .ic .i16: xor eax, eax call disasm_get_word .ic: call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- cmovcc: or ch, 0C0h and eax, 0xF mov ax, [disasm_jcc_codes + eax*2] mov dword [edi], 'cmov' add edi, 4 stosw mov ax, ' ' stosw call disasm_get_byte dec [disasm_cur_pos] shr eax, 3 and eax, 7 call disasm_write_reg1632 mov ax, ', ' stosw call disasm_readrmop and byte [edi], 0 ret ; btx r/m,i8 = 0F BA cbtx1: or ch, 80h call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 cmp al, 4 jb cunk mov eax, [btx1codes+eax*4-4*4] stosd mov eax, ' ' stosd call disasm_readrmop mov ax, ', ' stosw jmp disasm_i8u ;----------------------------------------------------------------------------- iglobal btx1codes dd 'bt ','bts ','btr ','btc ' endg ;----------------------------------------------------------------------------- ; btx r/m,r = 0F 101xx011 (A3,AB,B3,BB) cbtx2: shr al, 3 and eax, 3 mov eax, [btx1codes+eax*4] stosd mov eax, ' ' stosd or ch, 0xC0 call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 push eax call disasm_readrmop mov ax, ', ' stosw pop eax call disasm_write_reg1632 and byte [edi], 0 ret ;----------------------------------------------------------------------------- csetcc: and eax, 0xF mov ax, [disasm_jcc_codes + eax*2] mov dword [edi], 'setc' add edi, 3 stosw mov ax, ' ' stosw stosb call disasm_readrmop and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal disasm_jcc_codes dw 'o ','no','b ','ae','z ','nz','be','a ','s ','ns','p ','np','l ','ge','le','g ' endg ;----------------------------------------------------------------------------- cjcc1: cjmp2: cmp al, 0xEB jz .1 and eax, 0xF mov ax, [disasm_jcc_codes + eax*2] jmp .2 .1: mov ax, 'mp' .2: mov byte [edi], 'j' inc edi stosw mov eax, ' ' stosb stosd call disasm_get_byte movsx eax, al disasm_rva: add eax, [disasm_cur_pos] call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- ccall1: cjmp1: cjcc2: mov edx, 'call' cmp al, 0xE8 jz @f mov edx, 'jmp ' cmp al, 0xE9 jz @f mov edx, ' ' and eax, 0xF mov dx, [disasm_jcc_codes+eax*2] shl edx, 8 mov dl, 'j' @@: xchg eax, edx stosd mov eax, ' ' stosd test ch, 1 jnz @f call disasm_get_dword jmp disasm_rva @@: call disasm_get_word add eax, [disasm_cur_pos] and eax, 0xFFFF call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- ccallf: mov eax, 'call' stosd mov eax, ' ' stosd mov al, 'd' test ch, 1 jnz @f mov al, 'p' @@: stosb mov eax, 'word' stosd mov al, ' ' stosb test ch, 1 jnz .1 call disasm_get_dword jmp .2 .1: xor eax, eax call disasm_get_word .2: push eax xor eax, eax call disasm_get_word call disasm_write_num mov al, ':' stosb pop eax call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal op11codes dd 'test',0,'not ','neg ','mul ','imul','div ','idiv' op12codes dd 'inc ','dec ','call',0,'jmp ',0,'push',0 endg ;----------------------------------------------------------------------------- cop1: disasm_set_modew xchg eax, edx call disasm_get_byte movzx esi, al dec [disasm_cur_pos] shr al, 3 and eax, 7 cmp dl, 0xFE jnz @f cmp al, 1 jbe @f .0: inc [disasm_cur_pos] jmp cunk @@: and edx, 8 add eax, edx cmp al, 11 jz .callfar cmp al, 13 jz .jmpfar mov eax, [op11codes+eax*4] test eax, eax jz .0 cmp eax, 'test' jz ctest .2: stosd mov eax, ' ' stosd call disasm_readrmop and byte [edi], 0 ret .callfar: mov eax, 'call' .1: cmp esi, 0xC0 jae .0 stosd mov eax, ' ' stosd mov eax, 'far ' stosd mov al, 'd' test ch, 1 jnz @f mov al, 'p' @@: stosb or ch, 1 call disasm_readrmop and byte [edi], 0 ret .jmpfar: mov eax, 'jmp ' jmp .1 ;----------------------------------------------------------------------------- cpop2: or ch, 80h call disasm_get_byte dec [disasm_cur_pos] test al, 00111000b jnz cunk mov eax, 'pop ' jmp cop1.2 ;----------------------------------------------------------------------------- cloopnz: mov eax, 'loop' stosd mov eax, 'nz ' test ch, 2 jz @f mov ah, 'w' @@: jmp cloop.cmn cloopz: mov eax, 'loop' stosd mov eax, 'z ' test ch, 2 jz @f mov eax, 'zw ' @@: jmp cloop.cmn cjcxz: cloop: cmp al, 0xE2 jz .loop test ch, 2 jnz .jcxz mov eax, 'jecx' stosd mov eax, 'z ' jmp .cmn .jcxz: mov eax, 'jcxz' stosd mov eax, ' ' jmp .cmn .loop: mov eax, 'loop' stosd mov eax, ' ' test ch, 2 jz .cmn mov al, 'w' .cmn: stosd call disasm_get_byte movsx eax, al add eax, [disasm_cur_pos] test ch, 1 jz @f and eax, 0xFFFF ; @@: disasm_write_num_done: @@: call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- ; imul r,r/m,i cimul1: or ch, 80h ; 32bit operation xchg eax, edx mov eax, 'imul' stosd mov eax, ' ' stosd call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 call disasm_write_reg1632 mov ax, ', ' stosw call disasm_readrmop mov ax, ', ' stosw test ch, 1 jnz .16 cmp dl, 0x69 jz .op32 call disasm_get_byte movsx eax, al jmp disasm_write_num_done .op32: call disasm_get_dword jmp disasm_write_num_done .16: cmp dl, 0x69 jz .op16 call disasm_get_byte cbw jmp disasm_write_num_done .op16: xor eax, eax call disasm_get_word jmp disasm_write_num_done ;----------------------------------------------------------------------------- cshld: cshrd: mov edx, 'shld' test al, 8 jz @f mov edx, 'shrd' @@: xchg eax, edx stosd mov eax, ' ' stosd call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 push eax or ch, 80h call disasm_readrmop mov ax, ', ' stosw pop eax call disasm_write_reg1632 mov ax, ', ' stosw test dl, 1 jz disasm_i8u mov ax, 'cl' stosw and byte [edi], 0 ret ;----------------------------------------------------------------------------- ccbw: mov eax, 'cbw ' test ch, 1 jnz @f mov eax, 'cwde' @@: stosd and byte [edi], 0 ret ccwd: mov eax, 'cwd ' test ch, 1 jnz @b mov eax, 'cdq ' jmp @b ;----------------------------------------------------------------------------- ccmpxchg8b: call disasm_get_byte cmp al, 0xC0 jae cerr shr al, 3 and al, 7 cmp al, 1 jnz cerr dec [disasm_cur_pos] mov eax, 'cmpx' stosd mov eax, 'chg8' stosd mov al, 'b' stosb mov al, ' ' stosb or ch, 40h call disasm_readrmop and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal fpuD8 dd 'add ','mul ','com ','comp','sub ','subr','div ','divr' endg ;----------------------------------------------------------------------------- cD8: call disasm_get_byte dec [disasm_cur_pos] push eax shr al, 3 and eax, 7 mov byte [edi], 'f' inc edi xchg eax, edx mov eax, [fpuD8+edx*4] stosd mov ax, ' ' stosw stosb pop eax cmp dl, 2 jb .1 cmp dl, 3 jbe .2 .1: cmp al, 0xC0 jb .2 mov eax, 'st0,' stosd mov al, ' ' stosb .2: or ch, 80h or 20h and ch, not 1 call disasm_readrmop and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal fpuD9_2: dq 'fchs ','fabs ',0,0,'ftst ','fxam ',0,0 db 'fld1 fldl2t fldl2e fldpi fldlg2 fldln2 fldz ' dq 0 db 'f2xm1 fyl2x fptan fpatan fxtract fprem1 fdecstp fincstp ' db 'fprem fyl2xp1 fsqrt fsincos frndint fscale fsin fcos ' fpuD9_fnop db 'fnop ' endg ;----------------------------------------------------------------------------- cD9: call disasm_get_byte sub al, 0xC0 jae .l1 dec [disasm_cur_pos] shr al, 3 and eax, 7 cmp al, 7 jnz @f mov eax, 'fnst' stosd mov eax, 'cw ' jmp .x1 @@: cmp al, 5 jnz @f mov eax, 'fldc' stosd mov eax, 'w ' .x1: stosd or ch, 0C1h jmp .cmn @@: mov edx, 'fld ' test al, al jz @f mov edx, 'fst ' cmp al, 2 jz @f mov edx, 'fstp' cmp al, 3 jnz cunk @@: xchg eax, edx stosd mov eax, ' ' stosd or ch, 80h and ch, not 1 .cmn: call disasm_readrmop and byte [edi], 0 ret .l1: cmp al, 10h jae .l2 mov edx, 'fld ' cmp al, 8 jb @f mov edx, 'fxch' @@: xchg eax, edx stosd mov eax, ' ' stosd xchg eax, edx and al, 7 add al, '0' shl eax, 16 mov ax, 'st' stosd clc ret .l2: cmp al, 0x10 jnz @f mov esi, fpuD9_fnop jmp .l3 @@: sub al, 0x20 jb cerr lea esi, [fpuD9_2+eax*8] cmp byte [esi], 0 jz cerr .l3: movsd movsd and byte [edi-1], 0 ret ;----------------------------------------------------------------------------- cDA: call disasm_get_byte cmp al, 0xC0 jae cunk dec [disasm_cur_pos] shr al, 3 and eax, 7 mov word [edi], 'fi' inc edi inc edi mov eax, [fpuD8+eax*4] stosd mov ax, ' ' stosw or ch, 80h and ch, not 1 ; 32-bit operand call disasm_readrmop and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal fpuDB dd 'ild ',0,'ist ','istp',0,'ld ',0,'stp ' endg ;----------------------------------------------------------------------------- cDB: call disasm_get_byte cmp al, 0xC0 jae .1 dec [disasm_cur_pos] shr al, 3 and eax, 7 xchg eax, edx mov eax, [fpuDB+edx*4] test eax, eax jz cerr mov byte [edi], 'f' inc edi stosd mov ax, ' ' stosw stosb or ch, 80h and ch, not 1 ; 32-bit operand cmp dl, 4 jb @f or ch, 20h and ch, not 80h ; 80-bit operand @@: call disasm_readrmop and byte [edi], 0 ret .1: cmp al, 0xE3 jnz cunk mov eax, 'fnin' stosd mov eax, 'it' stosd dec edi ret ; CF cleared ;----------------------------------------------------------------------------- iglobal fpuDC dd 'add ','mul ',0,0,'subr','sub ','divr','div ' endg ;----------------------------------------------------------------------------- cDC: call disasm_get_byte cmp al, 0xC0 jae .1 dec [disasm_cur_pos] shr al, 3 and eax, 7 mov byte [edi], 'f' inc edi mov eax, [fpuD8+eax*4] stosd mov ax, ' ' stosw stosb or ch, 0A1h ; qword call disasm_readrmop and byte [edi], 0 ret .1: mov dl, al shr al, 3 and eax, 7 mov eax, [fpuDC+eax*4] test eax, eax jz cerr mov byte [edi], 'f' inc edi stosd mov eax, ' s' stosd mov al, 't' stosb and edx, 7 lea eax, [edx+'0'] stosb mov eax, ', st' stosd mov ax, '0' stosw ret ; CF cleared ;----------------------------------------------------------------------------- iglobal fpuDD dd 'fld ',0,'fst ','fstp',0,0,0,0 fpuDD_2 dq 'ffree ',0,'fst ','fstp ','fucom ','fucomp ',0,0 endg ;----------------------------------------------------------------------------- cDD: call disasm_get_byte cmp al, 0xC0 jae .1 dec [disasm_cur_pos] shr al, 3 and eax, 7 xchg eax, edx mov eax, [fpuDD+edx*4] test eax, eax jz cunk stosd mov eax, ' ' stosd or ch, 0A1h ; qword operand call disasm_readrmop and byte [edi], 0 ret .1: push eax shr al, 3 and eax, 7 xchg eax, edx mov eax, dword [fpuDD_2+edx*8] test eax, eax jz cerr stosd mov eax, dword [fpuDD_2+4+edx*8] stosd mov ax, 'st' stosw pop eax and al, 7 add al, '0' stosb and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal fpuDE dd 'add ','mul ',0,0,'subr','sub ','divr','div ' endg ;----------------------------------------------------------------------------- cDE: call disasm_get_byte cmp al, 0xC0 jae .1 dec [disasm_cur_pos] mov word [edi], 'fi' inc edi inc edi shr al, 3 and eax, 7 mov eax, [fpuD8+eax*4] stosd mov ax, ' ' stosw or ch, 81h ; force 16-bit call disasm_readrmop and byte [edi], 0 ret .1: push eax shr al, 3 and eax, 7 xchg eax, edx mov eax, [fpuDE+edx*4] test eax, eax jz .fcompp mov byte [edi], 'f' inc edi stosd mov al, 'p' cmp byte [edi-1], ' ' jnz @f mov byte [edi-1], al mov al, ' ' @@: stosb mov eax, ' st' stosd pop eax and al, 7 add al, '0' stosb mov ax, ', ' stosw mov eax, 'st0' stosd ret ; CF cleared .fcompp: pop eax cmp al, 0xD9 jnz cerr mov eax, 'fcom' stosd mov ax, 'pp' stosw and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal fpuDF dd 'ild ',0,'ist ','istp','bld ','ild ','bstp','istp' endg ;----------------------------------------------------------------------------- cDF: call disasm_get_byte cmp al, 0xC0 jae .1 dec [disasm_cur_pos] shr al, 3 and eax, 7 xchg eax, edx mov eax, [fpuDF+edx*4] test eax, eax jz cerr mov byte [edi], 'f' inc edi stosd mov ax, ' ' stosw stosb or ch, 81h ; force 16-bit operand cmp dl, 4 jb @f or ch, 20h test dl, 1 jnz @f or ch, 40h @@: call disasm_readrmop and byte [edi], 0 ret .1: cmp al, 0xE0 jnz cunk mov eax, 'fnst' stosd mov eax, 'sw ' stosd mov ax, 'ax' stosw and byte [edi], 0 ret ;----------------------------------------------------------------------------- cmovd1: mov eax, 'movd' stosd mov eax, ' ' stosd call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 call disasm_write_mmreg mov ax, ', ' stosw or ch, 0C0h and ch, not 1 call disasm_readrmop and byte [edi], 0 ret ;----------------------------------------------------------------------------- cmovd2: mov eax, 'movd' stosd mov eax, ' ' stosd call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 push eax ecx or ch, 0C0h and ch, not 1 call disasm_readrmop mov ax, ', ' stosw pop ecx eax call disasm_write_mmreg and byte [edi], 0 ret ;----------------------------------------------------------------------------- cmovq1: test ch, 1 jz .mm mov eax, 'movd' stosd mov eax, 'qa ' stosd jmp disasm_mmx1 .mm: mov eax, 'movq' stosd mov eax, ' ' stosd jmp disasm_mmx1 ;----------------------------------------------------------------------------- cmovq2: test ch, 1 jz .mm mov eax, 'movd' stosd mov eax, 'qa ' stosd jmp disasm_mmx3 .mm: mov eax, 'movq' disasm_mmx2: stosd mov eax, ' ' stosd disasm_mmx3: or ch, 50h call disasm_get_byte dec [disasm_cur_pos] push eax call disasm_readrmop mov ax, ', ' stosw pop eax shr al, 3 and eax, 7 call disasm_write_mmreg and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal mmx_cmds: db 0x60,'unpcklbw' db 0x61,'unpcklwd' db 0x62,'unpckldq' db 0x63,'packsswb' db 0x64,'pcmpgtb ' db 0x65,'pcmpgtw ' db 0x66,'pcmpgtd ' db 0x67,'packuswb' db 0x68,'unpckhbw' db 0x69,'unpckhwd' db 0x6A,'unpckhdq' db 0x6B,'packssdw' db 0x74,'pcmpeqb ' db 0x75,'pcmpeqw ' db 0x76,'pcmpeqd ' db 0xD4,'paddq ' db 0xD5,'pmullw ' db 0xD8,'psubusb ' db 0xD9,'psubusw ' db 0xDA,'pminub ' db 0xDB,'pand ' db 0xDC,'paddusb ' db 0xDD,'paddusw ' db 0xDE,'pmaxub ' db 0xDF,'pandn ' db 0xE0,'pavgb ' db 0xE3,'pavgw ' db 0xE4,'pmulhuw ' db 0xE5,'pmulhw ' db 0xE8,'psubsb ' db 0xE9,'psubsw ' db 0xEA,'pminsw ' db 0xEB,'por ' db 0xEC,'paddsb ' db 0xED,'paddsw ' db 0xEE,'pmaxsw ' db 0xEF,'pxor ' db 0xF4,'pmuludq ' db 0xF5,'pmaddwd ' db 0xF6,'psadbw ' db 0xF8,'psubb ' db 0xF9,'psubw ' db 0xFA,'psubd ' db 0xFB,'psubq ' db 0xFC,'paddb ' db 0xFD,'paddw ' db 0xFE,'paddd ' endg ;----------------------------------------------------------------------------- cpcmn: mov esi, mmx_cmds @@: cmp al, [esi] jz @f add esi, 9 jmp @b @@: inc esi mov al, 'p' cmp byte [esi], al jz @f stosb @@: movsd movsd cmp byte [edi-1], ' ' jz @f mov al, ' ' stosb ; @@: disasm_mmx1: @@: or ch, 50h call disasm_get_byte dec [disasm_cur_pos] shr al, 3 and eax, 7 call disasm_write_mmreg mov ax, ', ' stosw call disasm_readrmop cmp word [disasm_string], 'cm' jz .cmp and byte [edi], 0 ret .cmp: call disasm_get_byte and eax, 7 mov dx, 'eq' dec eax js @f mov dx, 'lt' jz @f mov dh, 'e' dec eax jnz .no2 @@: xchg dx, word [disasm_string+3] mov word [disasm_string+5], dx and byte [edi], 0 ret .no2: dec eax jnz @f add edi, 2 push edi lea esi, [edi-3] lea ecx, [esi-(disasm_string+8)+2] std rep movsb cld mov cx, word [esi-3] mov dword [esi-3], 'unor' mov byte [esi+1], 'd' mov word [esi+2], cx pop edi and byte [edi+1], 0 ret @@: mov edx, 'neq' dec eax jz @f mov edx, 'nlt' dec eax jz @f mov edx, 'nle' dec eax jz @f mov edx, 'ord' @@: push edi lea esi, [edi-1] lea ecx, [esi-(disasm_string+8)+2] std rep movsb cld mov cx, word [esi-3] mov dword [esi-3], edx mov word [esi], cx pop edi and byte [edi+1], 0 ret ;----------------------------------------------------------------------------- cpsrlw: mov eax, 'psrl' jmp @f cpsraw: mov eax, 'psra' jmp @f cpsllw: mov eax, 'psll' @@: stosd mov eax, 'w ' stosd jmp disasm_mmx1 cpsrld: mov eax, 'psrl' jmp @f cpsrad: mov eax, 'psra' jmp @f cpslld: mov eax, 'psll' @@: stosd mov eax, 'd ' stosd jmp disasm_mmx1 cpsrlq: mov eax, 'psrl' jmp @f cpsllq: mov eax, 'psll' @@: stosd mov eax, 'q ' stosd jmp disasm_mmx1 ;----------------------------------------------------------------------------- csse1: iglobal sse_cmds1: db 0x2F,4,'comi' db 0x54,3,'and' db 0x55,4,'andn' db 0x58,3,'add' db 0xC2,3,'cmp' endg mov esi, sse_cmds1+1 .1: @@: movzx edx, byte [esi] cmp al, [esi-1] jz @f lea esi, [esi+edx+2] jmp @b @@: push ecx mov ecx, edx inc esi rep movsb pop ecx mov al, 's' cmp byte [edi-1], 'i' jz @f mov al, 'p' @@: stosb mov al, 'd' test ch, 1 jnz @f mov al, 's' @@: stosb push ecx push 5 pop ecx sub ecx, edx adc ecx, 1 mov al, ' ' rep stosb pop ecx or ch, 1 ; force XMM reg jmp disasm_mmx1 ;----------------------------------------------------------------------------- csse2: iglobal sse_cmds2: db 0xD0,6,'addsub' db 0,0 endg test ch, 1 jz cerr mov esi, sse_cmds2+1 jmp csse1.1 cpshift: mov dl, al mov ax, 'ps' stosw call disasm_get_byte push eax and al, 0xC0 cmp al, 0xC0 jnz .pop_cunk pop eax push eax shr al, 3 and eax, 7 cmp al, 2 jz .rl cmp al, 4 jz .ra cmp al, 6 jz .ll .pop_cunk: pop eax jmp cunk .ll: mov ax, 'll' jmp @f .rl: mov ax, 'rl' jmp @f .ra: cmp dl, 0x73 jz .pop_cunk mov ax, 'ra' @@: stosw mov al, 'w' cmp dl, 0x71 jz @f mov al, 'd' cmp dl, 0x72 jz @f mov al, 'q' @@: stosb mov ax, ' ' stosw stosb pop eax and eax, 7 call disasm_write_mmreg mov ax, ', ' stosw xor eax, eax call disasm_get_byte call disasm_write_num and byte [edi], 0 ret ;----------------------------------------------------------------------------- iglobal grp15c1 dq 'fxsave ','fxrstor ','ldmxcsr ','stmxcsr ',0,0,0,'clflush ' endg ;----------------------------------------------------------------------------- cgrp15: call disasm_get_byte cmp al, 0xC0 jae cunk shr al, 3 and eax, 7 mov edx, eax mov eax, dword [grp15c1+eax*8] test eax, eax jz cerr dec [disasm_cur_pos] stosd mov eax, dword [grp15c1+4+edx*8] stosd or ch, 40h call disasm_readrmop and byte [edi], 0 ret ; vim: ft=fasm tabstop=4