Este documento descreve um código assembly para desassemblar instruções Intel/AMD. Ele fornece rotinas para ler o código de máquina e imprimir a representação assembly correspondente na memória. As rotinas auxiliares tratam da impressão de operandos, registradores e prefixos de segmento de acordo com os bits de controle armazenados em CH. O programa funciona lendo bytes de código sequencialmente e chamando as rotinas FF apropriadas.
C. Bombardelli - Desassembler routine in text mode built in assembly language
1. File: C:PGMdesa_prg32 COMPLETO.cb
; Código para rotina desassembladora versão 1.03 - 16/03/01 23:13;
; (Código Intel #16)
; Usa: FASM ASSEMBLER, rotinas: print$mem.nsm
; Autor: Clovis Bombardelli
;------------------------------------------------------------------------------------------------------------------------------------------------------------]
; INTRODUÇÂO:
; Esta é uma rotina construída em linguagem assembly para desassemblar instruções dos processadores INTEL/AMD. Ela deve
; ser introduzida como rotina no programa principal.
; RESUMO:
; Dado um determinado endereço binário apontado por ebx, o programa escreve numa região da memória indicada por es:edi,
; a instrução assembly que representa o código existente no endereço fornecido.
; Espaços de códigos indicados por "livre" posicionam cy=1
; Códigos "vazio" não marcam carry flag. As instruções terão sempre de 2 bytes
; flags de ch
; #7 0- end #16 1- end#32
; #6 0- op #16 1- op#32
; #5 0- dado byte 1- dado word ou dword
; #4 0-rm,r 1- r,rm
; #3 uso diverso, depende da instrução
; #2,1,0 000- sem prefixo,
; 001- es:,
; 010- cs:,
; 011- ss:,
; 100- ds:,
; 101- fs:,
; 110- gs:,
; 111- não usado
; Condições que geram erro devem posicionar #0[dh]=1 para na saida posicionar cy=1
; Instrução lock marca #2[dh]=1 para ser utilizado pelas demais instruções para verificar a validade das mesmas.
; Para testar este programa, siga o exemplo abaixo
;
;teste mov ebx,0x3000
; mov edi, 0x3010
; mov ch, [modo]
; call desa_ini
; int3
; int 0x20
;
Page: 1
2. File: C:PGMdesa_prg32 COMPLETO.cb
; ROTINA PRINCIPAL
align 4
desa_ini:
push edx
and ch, 0xc0 ; só usa os bits #6 e #7 (ver detalhes)
mov dh, ch ; salva ambiente em dh
push esi
and [opcode_cont], dword 0 ; inicializa contador
and [opcode_cont+4], dword 0
and [opcode_cont+8], dword 0
and [opcode_cont+0xc], dword 0
continue: xor eax, eax ; eax deve ficar zerado aqui
mov al, [ebx]
call imp_opcodehex ; imprimir na memoria
inc ebx ; al contém o caratere para impressão.
mov cl, al ; se for 00, terminou,
mov esi, eax
shl esi, 2
reentra: mov esi, [esi + base_indices] ; busca o indice relativo ao 1. codigo
.loop: mov al, [esi] ; loop de impressão
inc esi
cmp al, 0xff
je .a
or al, al
je .saida
call Imp_al ; imprime al (Imp_al)
jmp .loop
.a: mov al, [esi] ; busca rotina ff
inc esi
;and eax, 0xff ; instrução desnecessária
shl eax, 2
call dword [eax + base_rotinas_ff - 0x4]
xor eax, eax
jmp .loop
.saida: pop esi ; saida geral
test dh, 0x01
je .b
stc
.b: pop edx
ret
; Entrada: ds:ebx = posição da leitura
; es:edi = posição da escrita
; ch = ambiente
; para ambiente #32 setar #6,7 =1,
; para ambiente #16 setar #6,7=0 (outros bits são desconsiderados)
; usar outra flag para diferenciar impressao na tela ou na memoria (#5)...reformar
; Saida: cy = 0 ok ebx = posiçao da próxima instrução
; edi = posição seguinte à impressão
; cy =1 encontrada instrução inválida.
; Altera: ebx, edi, eax, cx
;
Page: 2
3. File: C:PGMdesa_prg32 COMPLETO.cb
; ROTINAS AUXILIARES
align 4
opcode_cont dd 0
buffer_opcode rb 0xf
imp_opcodehex : ; Escreve um byte de opcode em memoria
push ebx
movzx ebx, byte [opcode_cont]
mov byte [buffer_opcode+ebx], al ; exige um buffer em memória para composição
inc ebx ; INCREMENTA CONTADOR
mov byte [opcode_cont], bl
pop ebx
ret
align 4
imp_dwOpcodehex :
push ebx
movzx ebx, byte [opcode_cont]
mov byte [buffer_opcode+ebx], al
inc ebx
ror eax, 8
mov byte [buffer_opcode+ebx], al
inc ebx
ror eax, 8
mov byte [opcode_cont],bl
pop ebx
ret
align 4
imp_ddOpcodehex :
push ebx
movzx ebx, byte [opcode_cont]
mov byte [buffer_opcode+ebx], al
inc ebx
ror ax, 8
mov byte [buffer_opcode+ebx], al
inc ebx
ror ax, 8
mov byte [buffer_opcode+ebx], al
inc ebx
ror ax, 8
mov byte [buffer_opcode+ebx], al
inc ebx
ror ax, 8
mov byte [opcode_cont],bl
pop ebx
ret
align 4
Imp_al:
mov [edi], al
inc edi
inc edi
retn
align 4
imp_byhex: ; Imprime um byte em hexadecimal
.a: aam 0x10
cmp ah,0x09
jna .b
add ah,0x07
.b: cmp al,0x09
jna .c
add al,0x07
.c: add ax,0x3030
xchg ah,al
Page: 3
4. File: C:PGMdesa_prg32 COMPLETO.cb
call Imp_al
xchg ah,al
call Imp_al
retn
align 4
imp_wohex:
push ecx
mov ecx,2
push edx
mov edx,eax
.c: rol edx,0x08
mov al,dl
call imp_byhex
loop .c
pop edx
pop ecx
.b: retn
align 4
imp_ddhex:
.a: push ecx
mov ecx,4
push edx
mov edx,eax
.c: rol edx,0x08
mov al,dl
call imp_byhex ; Imprime 1 byte
loop .c
pop edx
pop ecx
.b: retn
align 4
imp_stringzGS: ; Imprime string tipo Z na posição indicada por es: edi
.b: mov al,[esi]
or al,al
je .a
inc esi
mov [edi],al
inc edi
inc edi
jmp .b
.a: ret
; ROTINAS FF
align 4
desa01 : ; marca tamanho do operando
add esp, 0x04 ;***
test dh, 0x40
je .a
and ch, 0xbf ; 1011 1111, zera #6
jmp continue
.a: or ch, 0x40 ; seta #6
jmp continue ; continue: busca novo byte de código
ret
align 4
desa02 : ; marca tamanho do endereçamento
add esp, 0x04 ;***
test dh, 0x80
je .a
and ch, 0x7f ; zera #7
jmp continue
.a: or ch, 0x80 ; seta #7
Page: 4
5. File: C:PGMdesa_prg32 COMPLETO.cb
jmp continue ; continue: busca novo byte de código
ret
align 4
desa03 : ; marca prefixo segmento (es, cs, ss, ds)
add esp, 0x04 ;***
and ch, 0xf8
test cl, 0x10
jne .a
test cl, 0x8
jne .b
or ch, 0x1 ; es
jmp continue
.a: test cl, 0x8
jne .c
or ch, 0x3 ; ss
jmp continue
.b: or ch, 0x2 ; cs
jmp continue
.c: or ch, 0x4 ; ds
jmp continue ; continue: busca novo byte de código
ret
align 4
desa04 : ; Marca prefixo segmento (fs, gs)
add esp, 0x4 ;***
and ch, 0xf8
test cl ,0x1
jne .a
or ch, 0x5 ; fs
jmp continue
.a: or ch, 0x6 ; gs
jmp continue ; continue: busca novo byte de código
ret
align 4
desa05 : ; Opcode de 2 bytes, reentra
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al ; al=2o opcode (01,02,08 ou 09)
mov esi, eax
shl esi, 2 ;1
add esi, 0x400
add esp, 0x4 ;***
jmp reentra
ret
align 4
desa06 : ; Seleciona e imprime iv ou ib em função de #0[cl]
test cl, 0x1
jne desa09 ; Continua em desa08
desa08 : ; Rotina imprime byte hex
mov al, [ebx]
call imp_opcodehex ; Imprime opcode no buffer em memoria
inc ebx
call imp_byhex ; Imprime ib hex
ret
align 4
desa09 : ; Seleciona iv ou iw em função de #6[cl]
test ch, 0x40
je desa0a
.a: mov eax, [ebx] ; Imprime id
call imp_ddOpcodehex
add ebx, 0x4
Page: 5
6. File: C:PGMdesa_prg32 COMPLETO.cb
call imp_ddhex ; Imprime id hex
ret
align 4
desa0a : ; Rotina imprime word hex
mov ax, [ebx]
call imp_dwOpcodehex
add ebx, 0x2
call imp_wohex ; Imprime iw hex
;mov [0xf0], byte 0x61
ret
align 4
desa07 : ; Seleciona e imprime ib, iv em função de #5[ch]
test ch, 0x20
jne desa09 ; #5[ch]=1, imprime word ou dword
jmp desa08 ; #5[ch]=0, imprime byte
ret
align 4
desa23 : ; Imprime endereço direto em função de #7[ch]
test ch,0x80
je desa0a ; Imprime iw
jmp desa09 ; Imprime iv (pode ser iw ou id)
align 4
desa0b : ; seleciona ab ou av em função de #0[cl]
test cl, 0x1
jne desa0f
push esi
mov esi, reg8
.a: call imp_stringzGS ; Imprime rb
pop esi
ret
align 4
desa0f : ; seleciona e imprime ax ou eax
push esi
mov esi, reg32
.b: test ch, 0x40
jne .a
inc esi
.a: call imp_stringzGS ; Imprime rw ou rd
pop esi
ret
align 4
desa15 : ; Imprime D, em função do prefixo 66 test ch, 0x40
je .a
mov al, 'd'
call Imp_al
.a: ret
align 4
desa32 : ; Imprime ib ou cl
test ch, 0x8
je desa06
push esi
mov esi, reg8+0x3
call imp_stringzGS
pop esi
ret
align 4
desa0e : ; Escolhe e imprime rv em função de #6[ch] e #0,1,2[cl]
Page: 6
7. File: C:PGMdesa_prg32 COMPLETO.cb
mov al, cl
.a: push esi
mov esi, reg32
and ax, 0x7 ; filtra 8 condições
shl al, 0x2 ; al*4
add esi, eax
.b: test ch, 0x40
jne .c ; eax
inc esi ; ax
.c: call imp_stringzGS
pop esi
ret
align 4
desa10 : ; Escolhe e imprime rb em função de #0,1,2[cl]
mov al, cl
.a: push esi
mov esi, reg8
and eax, 0x7
.b: mov ah, al
shl al, 1 ; al*2+al=al*3
add al, ah
xor ah, ah
add esi, eax
call imp_stringzGS ; Imprime
pop esi
ret
align 4
desa11 : ; Seleciona e imprime condição
push esi
mov esi, cond
mov al, cl
and eax, 0x0f ; filtra 16 condições
mov ah, al ; pode-se usar jmp desa10.b neste ponto
shl al, 1 ;
add al, ah
xor ah, ah
add esi, eax
call imp_stringzGS
pop esi
ret
align 4
desa18 : ; Imprime B, W ou D
mov al, 'b'
test cl, 1
je .a
mov al, 'w'
test ch, 0x40
je .a
mov al, 'd'
.a: call Imp_al
ret
align 4
rmb_rmv : ; Busca byte rm e escolhe rmb / rmv ou rb / rv em função de #0[cl]
test cl, 1
je desa13
or ch, 0x20
desa13 : ; Busca byte rm e escolhe rmb / rmv ou rb / rv (memória ou registrador)
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
rmv : ; Escolhe rmb / rmv ou rb / rv
xor al, 0xc0 ; verifica se #6,7 = 11 - end. por registrador
Page: 7
8. File: C:PGMdesa_prg32 COMPLETO.cb
test al, 0xc0
je rv
memv : ; Escolhe memória
call desa17 ; Imprime prefixo de segmento, se existir
mov al, cl
and ax, 0x7
shl ax, 2
test ch, 0x80
je .a
add ax, modo32 - modo16
.a: push esi
mov esi, modo16
add esi, eax
call aux_busca
pop esi
ret
rv : ; Escolhe rb ou rv (escolhe registrador)
test ch, 0x20
jne near desa0e ; Imprime rv
jmp desa10 ; Imprime rb
align 4
aux_busca :
mov esi, [esi] ; busca ponteiro da string
.a: mov al, [esi] ; loop de impressão
inc esi
cmp al, 0xff
je .b
or al, al
je .saida
call Imp_al ; Imprime al (Imp_al)
jmp .a
.b: mov al, [esi] ; busca rotina ff
inc esi
;and eax, 0xff
shl eax, 2
call dword [eax + base_rotinas_ff - 0x4]
xor eax, eax ; GARANTE EAX=0
jmp .a
.saida: ret
align 4
desa3a : ; Imprime rmb ou rmv dependendo de #5[ch] (usada pelas instruções do grupo 4 e 5)
push esi
mov al,cl
call desa16.b ; rb ou mb
pop esi
ret
align 4
desa16 : ; Imprime rmb ou rmv com prefixo de segmento + by, wo ou dw
test cl, 1
je .a
.c: or ch, 0x20
.a: mov al, [ebx]
call imp_opcodehex
inc ebx
.b: mov cl, al
xor al, 0xc0 ; busca rm, inverte #6,7 (qq valor=1 -> busca mem)
test al, 0xc0
je rv ; busca r
call aux16 ; Imprime by, wo ou dw
jmp memv ; busca m
align 4
aux16 :
push esi
Page: 8
9. File: C:PGMdesa_prg32 COMPLETO.cb
mov esi, tipo
test ch, 0x20 ; dado variavel ou byte
je .a
add esi, 0x3
test ch, 0x40 ; operando #32
je .a
add esi, 0x3
.a: call imp_stringzGS
pop esi
ret
align 4
desa17 : ; Busca e imprime registrador de segmento como prefixo
mov al, ch
and eax, 0x7
je .a
call aux17
mov al, ':'
call Imp_al
.a: ret
align 4
aux17 : push esi ; Imprime registrador de segmento
mov esi, regseg - 0x3
jmp desa10.b
align 4
desa19 : ; Altera "si" para buscar uma das quatro instruções: "cbw", "cwde", "cwd" ou "cdq"
mov esi, _cbw
test cl, 1
jne .a
test ch, 0x40
je .saida
mov esi, _cwde
jmp .saida
.a: mov esi, _cwd
test ch, 0x40
je .saida
mov esi, _cdq
.saida: ret ; saida geral
align 4
desa1a : ; Imprime endereço relativo curto
movsx eax, byte [ebx]
call imp_ddOpcodehex
inc ebx
.a: add eax, ebx
test ch, 0x40
je near imp_wohex
jmp imp_ddhex
align 4
desa1b : ; Imprime endereço relativo longo
test ch, 0x80
jne .a
movsx eax, word [ebx]
call imp_ddOpcodehex
add ebx, 0x2
jmp desa1a.a
.a: mov eax, [ebx]
call imp_ddOpcodehex
add ebx, 0x4
jmp desa1a.a
align 4
desa1c : ; Imprime es, cs, ss ou ds (OK 30/01/01 15:43)
push esi
Page: 9
10. File: C:PGMdesa_prg32 COMPLETO.cb
mov esi, regseg - 0x2
mov al, cl
shl al, 1
add al, cl
shr al, 0x3
and eax, 0xf
add esi, eax
call imp_stringzGS
pop esi
ret
align 4
desa1d : ; Imprime fs ou gs
push esi
mov esi, regseg + 0x0C
test cl, 0x8
je .a
add esi, 0x3
.a: call imp_stringzGS
pop esi
ret
align 4
desa1e : ; Imprime ecx ou cx
push esi
mov esi, reg32 + 0x4
test ch, 0x40
jne .a
inc esi
.a: call imp_stringzGS
pop esi
ret
align 4
desa1f : ; Imprime ne ou e em função de #0[cl]
push esi
mov esi, cond + 0x0f
test cl, 1
je .a
inc esi
.a: call imp_stringzGS
pop esi
ret
align 4
desa20 : ; Escolhe um dos nomes adc, or, add...cmp em função de #3,4,5[cl]
mov al, cl ; OK 30/03/01 20:29
test al, 0x2
je .a
or ch, 0x10
.a: push esi
mov esi, grupo1 ; adc, or, add....cmp
.b: shr al, 1
and eax, 0x1c
add esi, eax
call imp_stringzGS
pop esi
ret
align 4
desa21: ; Busca byte rm e imprime "rv,rmv/rmv,rv" ou "rb,rmb/rmb,rb"
test ch, 0x10 ; (vale todo intervalo para byte rm)
je .a
test cl, 1
je .b
.c: or ch, 0x20
.b: mov al, [ebx]
Page: 10
11. File: C:PGMdesa_prg32 COMPLETO.cb
call imp_opcodehex
inc ebx
mov cl, al
.d: call R_reg ; imprime r'
.e: mov al, ','
call Imp_al
mov al, cl
jmp rmv ; imprime m ou r
.a: call rmb_rmv ; Imprime m ou r
mov al, ','
call Imp_al ; continua em R_reg
R_reg: ; Imprime rb ou rv em função de #4,5,6[cl]
mov al, cl
shr al, 0x3
test ch, 0x20
jne near desa0e.a ; Imprime rv
jmp desa10.a ; Imprime rb
align 4
desa22 : ; Imprime "mov" setando #5[ch] se #0[cl]=1 e #4[ch] se #1[cl]=1
push esi
mov esi, _mov
test cl, 0x1
je .a
or ch, 0x20
.a: test cl, 0x2
je near desa1d.a
or ch, 0x10
call imp_stringzGS
pop esi
ret
align 4
desa24: ; Busca byte rm e seleciona um dos nomes do grupo1 em função #3,4,5[byte rm]
test cl, 1
je .a
or ch, 0x20
.a: mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
call desa20.a ; busca nome da instrução em função #3,4,5[byte rm]
.b: mov al, ' '
call Imp_al ; Imprime espaço
mov al, cl
jmp desa16.b ; busca end à memória em função #1,2,3[byte rm]
align 4
desa25: ; Busca byte rm e seleciona um dos nomes do grupo 2....
test cl, 0x1
je .a
or ch, 0x20
.a: mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
call aux25 ; busca nome do grupo 2 em função #3,4,5[byte rm]
jmp desa24.b ; repete rotina de endereçamento à memória
align 4
aux25 : ; Busca nome das instruções do grupo 2
push esi
mov esi, grupo2
jmp desa20.b
align 4
desa26 : ; Imprime aviso3 (para ser usada somente internamente à rotina aux_busca (ver grupo3))
Page: 11
12. File: C:PGMdesa_prg32 COMPLETO.cb
push esi ; aux27, mas deve ser indexada por isso recebeu o nome desa26
mov esi, aviso3
call imp_stringzGS
add esp, 0x0c
pop esi
or dh, 0x01
add esp, 0x4
ret
align 4
desa27 : ; Busca byte rm e escolhe nome do grupo 3...
test cl, 1
je .a
or ch, 0x20
.a: mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
push esi
mov esi, grupo3
shr al, 0x3
and eax, 0x7
je .b ; instrução test m,i
mov ah, al ; rotina para as demais instruções (NOT...NEG...)
shl al, 0x2 ; x4
add al, ah ; x5
and eax, 0x3f ; filtra
add esi, eax ; ajusta ponteiro
call aux_busca.a ; se a rotina 0xff26 for encontrada, imprime aviso3 e sai
pop esi
mov al, ' '
call Imp_al ; Imprime espaço
mov al, cl
jmp desa16.b
.b: ; test rmv,iv
call aux_busca.a ; rotina específica para test rmv,iv
mov al, ' '
call Imp_al ; Imprime espaço
mov al, cl
call desa16.b ; busca rmv
mov al, ','
call Imp_al ; Imprime ','
pop esi
jmp desa07
align 4
desa28 : ; Busca endereço far imediato
test ch, 0x40
je .a
push dword [ebx]
add ebx, 0x4
call desa0a
mov al, ':'
call Imp_al
pop eax
call imp_ddhex
retn
.a: push word [ebx]
add ebx, 0x2
call desa0a
mov al, ':'
call Imp_al
pop eax
call imp_wohex
ret
align 4
Page: 12
13. File: C:PGMdesa_prg32 COMPLETO.cb
desa29 : ; Busca deslocamento nos modos de endereçamento
test cl, 0xc0
je .a
test cl, 0x80
jne .b
mov dl, [ebx]
inc ebx
test dl, 0x80
je .c
mov al, '-'
neg dl
jmp .d
.c: mov al, '+'
.d: call Imp_al
mov al, dl
call imp_opcodehex
call imp_byhex
retn
.b: test ch, 0x80
jne .e
mov ax, [ebx]
call imp_dwOpcodehex
add ebx, 0x2
test ah, 0x80
je .f
neg eax
push eax
mov al, '-'
jmp .g
.f: push eax
mov al, '+'
.g: call Imp_al
pop eax
call imp_wohex
retn
.e: mov eax, [ebx]
call imp_ddOpcodehex ; Imprime opcode
add ebx, 0x4
bt eax, 0x1f
jae .h
neg eax
push eax
mov al, '-'
jmp .i
.h: push eax
mov al, '+'
.i: call Imp_al
pop eax
call imp_ddhex
.a: ret
align 4
desa2a: ; Executa rotina 21 com #5[ch]=1.
or ch, 0x10 ; Referencia incondicional à memoria tipo rv,rmv
jmp desa21.c
align 4
desa2b : ; Busca byte rm e busca endereçamento à memoria (rv,m).
or ch, 0x20 ; marca para rv, para usar a rotina 21
mov al, [ebx] ; Referencia a registrador imprime instrução inválida
call imp_opcodehex
inc ebx
mov cl, al
xor al, 0xc0
test al, 0xc0
jne near desa21.d
push esi ; instrução inválida se referenciar um registrador
Page: 13
14. File: C:PGMdesa_prg32 COMPLETO.cb
mov esi, aviso5
call imp_stringzGS
pop esi
or dh, 0x01 ; marcação de erro para acionar cy=1 na saida
ret
align 4
desa2c: ; Executa rotina 21 com #6[ch]=0. usada pela instrução "arpl"
and ch, 0xbf
jmp desa21.a
align 4
desa2d : ; Busca byte rm especifica para referencia a registradores de segmento (rseg,mem ou mem,rseg)
or ch, 0x20
and ch, 0xbf ; fixa registradores sempre do tipo word
test cl, 2
je .a
mov al, [ebx] ; ordem rseg, mem
call imp_opcodehex
inc ebx
mov cl, al
or ch, 0x8 ; fixa o modo de uso da rotina aux2d
call aux2d
jmp desa21.e
.a: call desa13 ; ordem mem, rseg
mov al, ','
call Imp_al
aux2d: push esi
mov esi, regseg
mov al, cl
and eax, 0x38
test ch, 0x8
je .a
cmp al, 0x8
je .b
.a: mov ah, al
shl al, 1
add al, ah
shr al, 3
cmp al, 0xf
ja .b
xor ah, ah
add esi, eax
jmp .c
.b: mov esi, aviso2
or dh, 0x1 ; posiciona erro
.c: call imp_stringzGS
pop esi
ret
align 4
desa2e : ; Rotina especifica para prefixos "rep", "repe" e "repne"
mov al,[ebx]
call imp_opcodehex
inc ebx
push eax
xor al, 0xa6
test al, 0xa6
jne .a ; pula se for "rep"
call desa1f ; Imprime "e" ou "ne"
.a: mov al, ' '
call Imp_al
pop eax
mov cl, al
mov esi, eax
Page: 14
15. File: C:PGMdesa_prg32 COMPLETO.cb
shl esi, 2 ; 1 mudado para 2--- OK
add esp, 0x4
jmp reentra
; antiga rotina 2f
; sem_uso mov al, [ebx]
; call imp_opcodehex
; inc ebx
; mov cl, al
; mov si, ax
; shl si, 1
; jmp aux_busca
align 4
desa30 : ; Rotina especifica para as instruções movsx e movzx
test cl, 1
je .a
or ch, 0x20
.a: mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
test ch, 0x20
je .b
or ch, 0x40
call R_reg
and ch, 0xbf
.c: mov al, ','
call Imp_al
mov al, cl
jmp desa16.b
.b: ;or ch, 0x01
call R_reg
and ch, 0x9f
jmp .c
ret
align 4
desa31 : ; Busca byte rm para endereçamento tipo rmv,rv. marca #3[ch]=1 se #0[byte anterior]=1
test cl, 1
je .a
or ch, 0x08
.a: call desa16.c ; busca byte rm e imprime m ou r
mov al, ','
call Imp_al
jmp R_reg ; Imprime r'
align 4
desa33 : ; Escolhe e imprime uma das letras: "s", "r" ou "c"
mov al, cl
sub al, 0xa3
je .a
shr al, 0x1
push esi
mov esi, src - 0x2
add esi, eax
call imp_stringzGS
pop esi
.a: ret
align 4
desa34 : ; Escolhe e imprime uma das letras: "s", "r" ou "c", específica para grupo 8
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
and eax, 0x38
Page: 15
16. File: C:PGMdesa_prg32 COMPLETO.cb
shr al, 1
or ch, 0x8
cmp al, 0x8
je .a
push esi
jb .b
mov esi, src - 0xa
add esi, eax
.c: call imp_stringzGS
pop esi
.a: retn
.b: mov al, 'x' ; instrução inválida se fora do intervalo válido
call Imp_al ; #3,4,5[byte rm] < 4
mov esi, aviso5
or dh, 0x01
jmp .c
align 4
desa35 : ; Escolhe uma das funções do grupo 0f00 ("ldtr", "str"....etc), em função de #3,4,5[byte rm]
push esi
mov esi, grupo6
.a: mov al, [ebx] ; busca byte rm
call imp_opcodehex
inc ebx
mov cl, al
and eax, 0x38
xor ah, ah
shr al, 1 ; desloca 8 por 1(/2) para calcular o endereço dentro do bloco
grupo6
add esi, eax
call aux_busca.a
pop esi
ret
align 4
desa36 : ; Busca endereçamento rmw em função de #0,1,2[cl]
and ch, 0xbf ; zera #6, seta #5
or ch, 0x20 ; fixa variavel em word
mov al, cl
jmp desa16.b ; busca modo de endereçamento
align 4
desa37 : ; Busca endereçamento m em função de #0,1,2[cl].
mov al, cl ; O tamanho do operando depende da instrução
xor al, 0xc0
test al, 0xc0
je desa38 ; mostra aviso de instrução inválida se o endereço referenciar
registrador
jmp rmv ; busca modo de endereçamento
align 4
desa38 : ; Imprime "Instrução inválida"
push esi
mov esi, aviso1
call imp_stringzGS
pop esi
or dh, 0x01 ; posiciona marca para erro
ret
align 4
desa39 : ; Escolhe uma das funções do grupo 0f01, em função de #3,4,5 [byte rm]
push esi
mov esi, grupo7
jmp desa35.a
align 4
desa3b : ; Busca byte rm e escolhe uma das instruções do grupo 5
Page: 16
17. File: C:PGMdesa_prg32 COMPLETO.cb
or ch, 0x20
mov esi, grupo5
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
jmp aux4d
align 4
desa3c : ; Imprime rmv (usada pela instrução push rmv do grupo 5)
or ch, 0x20
jmp desa16.b
align 4
desa44 : ; Busca proximo byte e imprime "mov" posicionando #6[ch]=1,
mov al, [ebx] ; (usada nas instruções tipo mov cr0, rd)
call imp_opcodehex
inc ebx
mov cl, al
or ch, 0x40 ; continua na rotina 3d
desa3d : ; Imprime 'mov'
push esi
mov esi, _mov
call imp_stringzGS
pop esi
ret
align 4
desa3e : ; Imprime 'pop'
push esi
mov esi, _pop
call imp_stringzGS
pop esi
ret
align 4
desa3f : ; Imprime 'push'
push esi
mov esi, _push
call imp_stringzGS
pop esi
ret
align 4
desa0c : ; Diferencia [endereçamento direto] de [bp+deslocamento]
test cl, 0xc0
je .a ; se #6,7[cl]=0 buscar .a ou .b (end dir)
push esi
mov esi,0xabcd
mov esi, insbp
call aux_busca.a
pop esi
retn
.a: ; Busca endereçcamento direto word
test ch, 0x80
jne .b
mov ax, [ebx] ; pode-se substituir por jmp desa0a
call imp_dwOpcodehex
add ebx, 0x2
call imp_wohex
retn
.b: ; Busca endereçcamento direto dword
mov eax, [ebx] ; pode-se substituir por desa09.a
call imp_ddOpcodehex ; Imprime opcode
add ebx, 0x4
call imp_ddhex
Page: 17
18. File: C:PGMdesa_prg32 COMPLETO.cb
ret
align 4
desa0d : ; Diferencia [endereçamento direto] de [ebp+deslocamento]
test cl, 0xc0
je desa0c.a
push esi
mov esi, insebp
call aux_busca.a
pop esi
ret
align 4
desa40 : ; Busca byte rm para instruções mpu (rotina principal)
push esi
mov al, cl
and eax, 0x7
mov dl, al
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
xor al, 0xc0
test al, 0xc0
je .a
mov esi, R_d8 ; base do bloco com referencia à memória
and eax, 0x38
shr al, 1
add esi, eax
mov al, dl
shl al, 4
add esi, eax
call aux_busca
mov al, cl
call memv
pop esi
retn
.a: mov esi, R_d8.c0 ; base do bloco com referencia aos registradores
shl ax, 2 ;
add esi, eax
mov al, dl
shl ax, 7
add esi, eax
xor eax, eax
call aux_busca
pop esi
ret
align 4
desa41 : ; Imprime "st0,stx" em função de #0,1,2[cl]
push esi
mov esi, _st
call imp_stringzGS
mov al, ','
call Imp_al
mov al, cl
and eax, 0x7
shl al, 0x2
mov esi, _st
add esi,eax
call imp_stringzGS
pop esi
ret
align 4
desa42 : ; Imprime "stx,st0" em função de #0,1,2[cl]
push esi
Page: 18
19. File: C:PGMdesa_prg32 COMPLETO.cb
mov esi, _st
mov al, cl
and eax, 0x7
shl al, 0x2
add esi,eax
call imp_stringzGS
mov al, ','
call Imp_al
mov esi, _st
call imp_stringzGS
pop esi
ret
align 4
desa43 : ; Imprime stx em função de #0,1,2[cl]
mov al, cl
and eax, 0x7
push esi
mov esi, _st
shl al, 0x2
add esi, eax
call imp_stringzGS
pop esi
R_ret: ret
align 4
desa45 : ;.Marca erro posicionando #1[dh]=1
or dh, 0x1
ret
align 4
desa46 : ; Marca #2[dh]=1 e continua. Rotina especifica para instrução lock
or dh, 0x2
add esp, 0x4
jmp continue
align 4
desa47 : ; Busca byte rm para instruções dos grupos 12, 13 e 14
mov al, cl
and eax, 3
je .a
dec al
shl al, 0x4
mov esi, grupo12
add esi, eax
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
xor al, 0xc0
test al, 0xc0
jne near desa38 ; referencia à memoria deve buscar outro ponteiro
and eax, 0x38 ; ou indicar inst. inválida
shr al, 0x2 ;
add si, ax ; só altera si para busca do ponteiro
mov esi, [esi] ; busca novo ponteiro
ret
.a: mov esi, livre
ret
align 4
desa2f : ; Imprime #3,4,5[byte rm] como um numero entre 0 e 7
mov al, cl
and eax, 0x38
shr al, 0x3
add al, 0x30
call Imp_al
Page: 19
20. File: C:PGMdesa_prg32 COMPLETO.cb
ret
; sem_uso2 ; Imprime D, em função do pref. 67 ( semelhante à desa15, mas sensivel ao bit #7[ch]
; test ch, 0x80
; je .a
; mov al, 'd'
; call Imp_al
;.a ret
align 4
desa14 : ; Busca byte sib
mov dl, [ebx]
inc ebx
mov al, dl
push esi
mov esi, reg32
and ax, 0x7
shl al, 0x2
add esi, eax
call imp_stringzGS
mov al, '+'
call Imp_al
mov al, dl
call imp_opcodehex ;*
shr al, 0x3
mov esi, reg32
and eax, 0x7
shl al, 0x2
add esi, eax
call imp_stringzGS
pop esi
push ecx
mov cl, dl
shr cl , 6
je .a
mov al , '*'
call Imp_al
mov al, 1
shl al, cl
add al, 0x30
call Imp_al
.a: pop ecx
jmp desa29
align 4
desa12 : ; Escolhe e imprime rd em função de #0,1,2[cl]
push esi
mov esi, reg32
and ax, 0x7
shl al, 0x2
add esi, eax
call imp_stringzGS
pop esi
ret
align 4
desa48 : ; Busca byte rm e escolhe umas das instruções do grupo 4
mov esi, grupo4
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
jmp aux4d
align 4
desa49 : ; Busca byte rm para instruções mmx (rmmx, rmmx/m64)
mov al, [ebx]
Page: 20
21. File: C:PGMdesa_prg32 COMPLETO.cb
call imp_opcodehex
inc ebx
mov cl, al
shr al, 3
call rmmx
mov al, ','
call Imp_al
mov al, cl
aux4a: xor al,0xc0
test al,0xc0
je near memv ; Escolhe memória
rmmx: push esi ; Imprime rmmx, se não for memória
mov esi, _xmm + 1
and eax, 0x7
shl eax, 2
add esi, eax
call imp_stringzGS
pop esi
ret
align 4
desa4a : ; Busca byte rm para instruções mmx reversas (rmmx/m64, rmmx)
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
call aux4a
mov al, ','
call Imp_al
mov al, cl
shr al, 3
jmp rmmx
align 4
desa4b : ; Busca byte rm para instrução movd (rmmx,r/m32)
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
shr al, 3
call rmmx
mov al, ','
call Imp_al
mov al, cl
or ch, 0x60 ; seta rd
jmp rmv
align 4
desa4c : ; Busca byte rm para instrução movdr (r/m32,rmmx)
mov al, [ebx]
call imp_opcodehex
inc ebx
mov cl, al
or ch, 0x60
call rmv
mov al, ','
call Imp_al
mov al, cl
shr al, 3
jmp rmmx
align 4
desa4d : ; Busca ponteiro para instruções do grupo 12
mov esi, grupo12
aux4d:
and eax, 0x38
shr al, 1
Page: 21
22. File: C:PGMdesa_prg32 COMPLETO.cb
add esi, eax
call aux_busca
ret
align 4
desa4e : ; Busca ponteiro para instruções do grupo 13
mov esi, grupo13
jmp aux4d
align 4
desa4f : ; Busca ponteiro para instruções do grupo 14
mov esi, grupo14
jmp aux4d
align 4
desa50 : ; Rotina usada pelas instruções dos blocos 12, 13 e 14
mov al,cl ; byte rm deve já estar em cl.
call rmmx ; Imprime reg mmx, ref. à memória devem buscar...
mov al, ','
call Imp_al
mov al, [ebx] ; busca dado imediato
call imp_opcodehex
inc ebx
call imp_byhex ; Imprime ib
ret
; DADOS CONSTANTES
; db 'desa1.3 jan01'
; Tabela de ponteiros das rotinas FF
align 4
base_rotinas_ff:
dd desa01 ; Marca prefixo de tamanho de operando
dd desa02 ; Marca prefixo de tamanho de endereço
dd desa03 ; Marca prefixo de segmento es, cs, ss ou ds
dd desa04 ; Marca prefixo de segmento fs ou gs
dd desa05 ; Marca instrução com dois bytes, busca opcode na tabela seguinte
dd desa06 ; Escolhe e imprime ib ou iv em função de #0[cl]
dd desa07 ; Seleciona e imprime ib, iv em função de #5[ch]
dd desa08 ; Imprime ib
dd desa09 ; Escolhe e imprime iw ou id em função de #6[ch]
dd desa0a ; Imprime iw
dd desa0b ; Escolhe e imprime al ou axv em função de #0[cl]
dd desa0c ; Diferencia [endereçamento direto] de [bp+deslocamento]
dd desa0d ; Diferencia [endereçamento direto] de [ebp+deslocamento]
dd desa0e ; Escolhe e imprime rv em função de #6[ch] e #0,1,2[cl]
dd desa0f ; Escolhe e imprime ax ou eax
dd desa10 ; Escolhe e imprime rb em função de #0,1,2[cl]
dd desa11 ; Escolhe e imprime condição
dd desa12 ; Imprime rd em função de #0,1,2[cl] (similar a desa0e, insensível ao pref. 66)
dd desa13 ; Busca byte rm e escolhe rmb / rmv ou rb / rv (memória ou registrador)
dd desa14 ; Busca byte sib
dd desa15 ; Imprime D, em função do prefixo 66
dd desa16 ; Imprime rmb ou rmv com prefixo de segmento + by, wo ou dd
dd desa17 ; Imprime prefixo de segmento em função #0,1,2[ch]
dd desa18 ; Imprime b, w ou d
dd desa19 ; Altera "si" para buscar uma das quatro : "cbw", "cwde", "cwd" ou "cdq"
dd desa1a ; Imprime endereço relativo curto
dd desa1b ; Imprime endereço relativo longo variável
dd desa1c ; Imprime es, cs, ss ou ds
dd desa1d ; Imprime fs ou gs
dd desa1e ; Imprime cx ou ecx
dd desa1f ; Imprime ne ou e
dd desa20 ; Imprime add, or, adc, sbb, and, sub, xor, cmp em função #3,4,5[cl]
dd desa21 ; Escolhe rv,rmv/rmv,rv ou rb,rmb/rmb,rb
dd desa22 ; Imprime 'mov' setando #5[ch] se #0[cl]=1
Page: 22
23. File: C:PGMdesa_prg32 COMPLETO.cb
dd desa23 ; Imprime endereço direto em função #7[ch]
dd desa24 ; Busca byte rm e seleciona um dos nomes do grupo1 em função #3,4,5[byte rm]
dd desa25 ; Seleciona e imprime um dos nomes..rol, ror, rcl, rcr, shl, shr, sal, sar
dd desa26 ; Imprime aviso3: código de instrução não usado (usada pela rotina desa27)
dd desa27 ; Escolhe nome test, x, not, neg, mul, imul,...
dd desa28 ; Busca endereço far imediato
dd desa29 ; Busca deslocamento nos modos de endereçamento
dd desa2a ; Executa rotina 21 com #5[ch]=1. Referencia à memoria tipo rv,rmv incondicional
dd desa2b ; Busca byte rm e busca endereçamento à memoria (rv,m)
dd desa2c ; Executa rotina 21 com #6[ch]=0. Usada pela instrução "arpl"
dd desa2d ; Busca byte rm especifica para referencia a reg seg (rseg,rm ou rm,rseg)
dd desa2e ; Rotina especifica para prefixos "rep", "repe" e "repne"
dd desa2f ; Imprime #3,4,5[byte rm] como um numero entre 0 e 7
dd desa30 ; Rotina especifica para as instruções movsx e movzx
dd desa31 ; Busca byte rm para end tipo rmv,rv. marca #3[ch]=1 se #0[byte anterior]=1
dd desa32 ; Imprime ib ou cl em função de #3[cl]
dd desa33 ; Escolhe e imprime uma das letras: "s", "r" ou "c"
dd desa34 ; Escolhe e imprime uma das letras: "s", "r" ou "c", específica para grupo 8
dd desa35 ; Escolhe no grupo 0f00 ("ldtr", "str"....etc), em função de #3,4,5[byte rm]
dd desa36 ; Busca endereçamento rmw em função de #0,1,2[cl]
dd desa37 ; Busca end M em função de #0,1,2[cl]. O tam. do operando depende da instrução
dd desa38 ; Imprime "Instrução inválida"
dd desa39 ; Escolhe uma das funções do grupo 0f01, em função de #3,4,5 [byte rm]
dd desa3a ; Imprime rmb ou rmv dependendo de #5[ch] (usada pelas instr do grupo 4 e 5)
dd desa3b ; Busca byte rm e escolhe uma das instruções do grupo 5
dd desa3c ; Imprime rmv (usada pela instrução push rmv do grupo 5)
dd desa3d ; Imprime 'mov'
dd desa3e ; Imprime 'pop'
dd desa3f ; Imprime 'push'
dd desa40 ; Busca byte rm para instruções mpu (rotina principal)
dd desa41 ; Imprime "st0,stx" em função de #0,1,2[cl]
dd desa42 ; Imprime "stx,st0" em função de #0,1,2[cl]
dd desa43 ; Imprime stx em função de #0,1,2[cl]
dd desa44 ; Busca proximo byte e imprime "mov" posicionando #6[ch]=1
dd desa45 ; Marca erro posicionando #1[dh]=1
dd desa46 ; Marca #2[dh]=1 e continua. Rotina especifica para instrução lock
dd desa47 ; Busca byte rm para instruções dos grupos 12, 13 e 14
dd desa48 ; Busca byte rm e escolhe umas das instruções do grupo 4
dd desa49 ; Busca byte rm para instruções mmx (rmmx, rmmx/m64)
dd desa4a ; Busca byte rm para instruções mmx reversas (rmmx/m64, rmmx)
dd desa4b ; Busca byte rm para instrução movd (rmmx,r/m32)
dd desa4c ; Busca byte rm para instrução movdr (r/m32,rmmx)
dd desa4d ; Busca ponteiro para instruções do grupo 12
dd desa4e ; Busca ponteiro para instruções do grupo 13
dd desa4f ; Busca ponteiro para instruções do grupo 14
dd desa50 ; Rotina usada pelas instruções dos blocos 12, 13 e 14
modo16:
dd m16.0
dd m16.1
dd m16.2
dd m16.3
dd m16.4
dd m16.5
dd m16.6
dd m16.7
modo32:
dd m32.0
dd m32.1
dd m32.2
dd m32.3
dd m32.4
dd m32.5
dd m32.6
dd m32.7
Page: 23
24. File: C:PGMdesa_prg32 COMPLETO.cb
grupo4 dd _incx
dd _decx
dd livre
dd livre
dd livre
dd livre
dd livre
grupo4.7 dd livre
grupo5 dd _incx
dd _decx
dd _callx
dd _callfarx
dd _jmpx
dd _jmpfarx
dd _pusx
grupo5.7 dd livre
; IMPORTANTE: Os blocos 12, 13 e 14 devem ficar coesos entre si
; Prever mais 3 blocos livres para as referencias à memória nestes 3 blocos. (ou pensar noutra solução)
grupo12: dd livre
dd livre
dd _psrlwi
dd livre
dd _psrawi
dd livre
dd _psllwi
dd livre
grupo13 dd livre
dd livre
dd _psrldi
dd livre
dd _psradi
dd livre
dd _pslldi
dd livre
grupo14 dd livre
dd livre
dd _psrlqi
dd livre
dd livre
dd livre
dd _psllqi
dd livre
; times 0x180 - ( _ - __ ) db 0
;-----------------------------------------------------------------------------------------------------------------------------------------------------------
; Tabela de índices (aviso4= instrução indisponível)
db 'BASE INDICE'
align 16
base_indices:
dd _add ; 00- add rmb,rb
dd _add ; 01- add rmv,rv
dd _add ; 02- add rb,rmb
dd _add ; 03- add rv,rmv
dd _addi ; 04- add al,ib ; a mesma rotina serve para os códigos 04 e 05
dd _addi ; 05- add axv,iv
dd _pushs ; 06- push es
dd _pops ; 07- pop es
dd _add ; 08- or rmb,rb
dd _add ; 09- or rmv,rv
dd _add ; 0a- or rb,rmb
dd _add ; 0b- or rv,rmv
dd _addi ; 0c- or al,ib
Page: 24