Programa Debug
Programa Debug
Processo de criao de programas Registradores da CPU Programa debug Estrutura Assembly Criando um programa assembly simples Armazenando e carregando os programas Mais programas no debug
Registradores da CPU
Para o propsito didtico, vamos focar registradores de 16 bits. A CPU possui alguns registradores internos, entre eles AX, BX, CX e DX. So registradores de uso geral e tambm podem ser usados como registradores de 8 bits. Para tanto devemos referenci-los
como, por exemplo, AH e AL, que so, respectivamente, o byte high e o low do registrador AX. Esta nomenclatura tambm se aplica para os registradores BX, CX e DX. Os registradores, segundo seus respectivos nomes: AX Registrador Acumulador BX Registrador Base CX Registrador Contador DX Registrador de Dados DS Registrador de Segmento de Dados ES Registrador de Segmento Extra SS Registrador de Segmento de Pilha CS Registrador de Segmento de Cdigo BP Registrador Apontador da Base SI Registrador de ndice Fonte DI Registrador de ndice Destino SP Registrador Apontador de Pilha IP Registrador Apontador da Prxima Instruo F Registrador de Flag
Programa Debug
Para a criao de um programa em assembly existem opes: uma delas usar o TASM Turbo Assembler da Borland, outra o Debug. Nesta primeira seo vamos usar o debug, uma vez que podemos encontr-lo em qualquer PC com o MS-DOS. Debug pode apenas criar arquivos com a extenso .COM, e por causa das caractersticas deste tipo de programa, eles no podem exceder os 64 Kb, e tambm devem iniciar no endereo de memria 0100H dentro do segmento especfico. importante observar isso, pois deste modo os programas .COM no so relocveis. Os principais comandos do programa debug so: A Montar instrues simblicas em cdigo de mquina D Mostrar o contedo de uma rea da memria E Entrar dados na memria, iniciando num endereo especfico G Rodar um programa executvel na memria N Dar nome a um programa P Proceder, ou executar um conjunto de instrues relacionadas Q Sair do programa debug R Mostrar o contedo de um ou mais registradores T Executar passo a passo as instrues U Desmontar o cdigo de mquina em instrues simblicas W Gravar um programa em disco possvel visualizar os valores dos registradores internos da CPU usando o programa Debug. Debug um programa que faz parte do pacote do DOS, e pode ser encontrado normalmente no diretrio C:\DOS. Para inici-lo, basta digitar Debug na linha de comando: C:/>Debug [Enter] Voc notar ento a presena de um hfen no canto inferior esquerdo da tela. No se espante, este o prompt do programa. Para visualizar o contedo dos registradores, experimente:
-r[Enter] AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D62 ES=0D62 SS=0D62 CS=0D62 IP=0100 NV UP EI PL NZ NA PO NC 0D62:0100 2E CS: 0D62:0101 803ED3DF00 CMP BYTE PTR [DFD3],00 CS:DFD3=03
mostrado o contedo de todos os registradores internos da CPU; um modo alternativo para visualizar um nico registrador usar o camando "r" seguido do parmetro que faz referncia ao nome do registrador:
-rbx BX 0000 :
Esta instruo mostrar o contedo do registrador BX e mudar o indicador do Debug de "-" para ":" Quando o prompt assim se tornar, significa que possvel, embora no obrigatria, a mudana do valor contido no registrador, bastando digitar o novo valor e pressionar [Enter]. Se voc simplesmente pressionar [Enter] o valor antigo se mantm.
Estrutura Assembly
Nas linhas do cdigo em Linguagem Assembly h duas partes: a primeira o nome da instruo a ser executada; a segunda, os parmetros do comando. Por exemplo: add ah ,bh Aqui "add" o comando a ser executado, neste caso uma adio, e "ah" bem como "bh" so os parmetros. Outro exemplo: mov al, 25 No exemplo acima, estamos usando a instruo mov, que significa mover o valor 25 para o registrador al. O nome das instrues nesta linguagem constitudo de 2, 3 ou 4 letras. Estas instrues so chamadas mnemnicos ou cdigos de operao, representando a funo que o processador executar. s vezes instrues aparecem assim: add al,[170] Os colchetes no segundo parmetro indica-nos que vamos trabalhar com o contedo da clula de memria de nmero 170, ou seja, com o valor contido no endereo 170 da memria e no com o valor 170, isto conhecido como "endereamento direto".
O que o programa faz? Move o valor 0002 para o registrador ax, move o valor 0004 para o registrador bx, adiciona o contedo dos registradores ax e bx, guardando o resultado em ax e finalmente a instruo nop (nenhuma operao) finaliza o programa. No programa debug, a tela se parecer com:
C:\>debug -a 100 0D62:0100 mov ax,0002 0D62:0103 mov bx,0004 0D62:0106 add ax,bx
Vemos o valor 0002 no registrador AX. Teclamos "t" para executar a segunda instruo:
-t AX=0002 BX=0004 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=0D62 ES=0D62 SS=0D62 CS=0D62 IP=0106 NV UP EI PL NZ NA PO NC 0D62:0106 01D8 ADD AX,BX
Possivelmente a maioria dos registradores ter valores diferentes, entretanto AX e BX devem conter os mesmos valores acima descritos. Para sair do Debug usamos o comando "q" (quit).
Usando como exemplo o seguinte programa, vamos clarear a idia de como realizar os passos acima descritos:
0C1B:0100 0C1B:0103 0C1B:0106 0C1B:0108 mov ax,0002 mov bx,0004 add ax,bx int 20
0C1B:010A
Para obter o tamanho de um programa, o comando "h" usado, j que ele nos mostra a adio e subtrao de dois nmeros em hexadecimal. Para obter o tamanho do programa em questo, damos como parmetro o valor do endereo final do nosso programa (10A), e o endereo inicial (100). O primeiro resultado mostra-nos a soma dos endereos, o segundo, a subtrao.
-h 10a 100 020a 000a
O comando "rcx" permite-nos mudar o contedo do registrador CX para o valor obtido como tamanho do arquivo com o comando "h", neste caso 000a.
-rcx CX 0000 :000a NOTA: Se o valor no couber em CX, utilize o registrador BX.
Finalmente, o comando "w" grava nosso programa no disco, indicando quantos bytes gravou.
-w Writing 000A bytes
Para j salvar um arquivo quando carreg-lo, 2 passos so necessrios: 1. Dar o nome do arquivo a ser carregado; e 2. Carreg-lo usando o comando "l" (load). Para obter o resultado correto destes passos, necessrio que o programa acima j esteja criado. Dentro do Debug, escrevemos o seguinte:
-n test.com -l -u 100 109 0C3D:0100 B80200 MOV AX,0002 0C3D:0103 BB0400 MOV BX,0004 0C3D:0106 01D8 ADD AX,BX 0C3D:0108 CD20 INT 20
O ltimo comando "u" usado para verificar que o programa foi carregado na memria. O que ele faz desmontar o cdigo e mostr-lo em assembly. Os parmetros indicam ao Debug os endereos inicial e final a serem desmontados. O Debug sempre carrega os programas na memria no endereo 100h, conforme j comentamos.
pela documentao. Voc pode executar cada programa assembly usando o comando "g" (go), para ver o que cada programa faz.
Primeiro passo
Carregar o programa Por exemplo:
C:\>debug -n one.com -l -u 100 109 0D80:0100 B80600 0D80:0103 BB0400 0D80:0106 01D8 0D80:0108 CD20 -n one.com
Carrega o programa
-u 100 109 //Desmonta o cdigo do endereo inicial ao endereo final especificado
Segundo passo
Digite o comando g Por exemplo:
-g Program terminated normally -
A nica coisa que este programa faz salvar dois valores em dois registradores e adicionar o valor de um ao outro.
- a100 0C1B:0100 jmp 125 ;Salta para o endereo 125h 0C1B:0102 [Enter] - e 102 'Hello, How are you ?' 0d 0a '$' - a125 0C1B:0125 MOV DX,0102 ;Copia a string para registrador DX 0C1B:0128 MOV CX,000F ;Quantas vezes a string ser mostrada 0C1B:012B MOV AH,09 ;Copia o valor 09 para registrador AH 0C1B:012D INT 21 ;Mostra a string 0C1B:012F DEC CX ;Subtrai 1 de CX 0C1B:0130 JCXZ 0134 ;Se CX igual a 0 salta para o endereo 0134 0C1B:0132 JMP 012D ;Salta ao endereo 012D 0C1B:0134 INT 20 ;Finaliza o programa
MOV AH,01 ;Funo para mudar o cursor MOV CX,0007 ;Formata o cursor INT 10 ;Chama interrupo do BIOS INT 20 ;Finaliza o programa
Quarto exemplo
-a100 297D:0100 297D:0102 297D:0104 297D:0106 297D:0108 297D:010A 297D:010C 297D:010E MOV AH,01 ;Funo 1 (l caractere do teclado) INT 21 ;Chama interrupo do DOS CMP AL,0D ;Compara se o caractere lido um ENTER JNZ 0100 ;Se no , l um outro caractere MOV AH,02 ;Funo 2 (escreve um caractere na tela) MOV DL,AL ;Character to write on AL INT 21 ;Chama interrupo do DOS INT 20 ;Finaliza o programa
Este programa usa a interrupo 21h do DOS. Usa duas funes da mesma: a primeira l um caractere do teclado (funo 1) e a segundo escreve um caractere na tela. O programa l caracteres do teclado at encontrar um ENTER.
Quinto exemplo
Este programa mostra na tela um nmero binrio atravs de um ciclo condicional (LOOP) usando a rotao do byte.
-a100 297D:0100 297D:0102 297D:0105 297D:0107 297D:0109 297D:010C 297D:010E 297D:0110 MOV AH,02 ;Funo 2 (escreve caractere na tela) MOV CX,0008 ;Pe o valor 0008 no registrador CX MOV DL,00 ;Pe o valor 00 no registrador DL RCL BL,1 ;Rotaciona o byte em BL um bit para a esquerda ADC DL,30 ;Converte o registrador de flag para 1 INT 21 ;Chama interrupo do DOS LOOP 0105 ;Salta se CX > 0 para o endereo 0105 INT 20 ;Finaliza o programa
Sexto exemplo
Este programa imprime um valor zero em dgitos hexadecimais.
-a100 297D:0100 297D:0102 297D:0104 297D:0107 297D:010A 297D:010C 297D:010F 297D:0111 MOV AH,02 ;Funo 2 (escreve caractere na tela) MOV DL,BL ;Pe o valor de BL em DL ADD DL,30 ;Adiciona o valor 30 a DL CMP DL,3A ;Compara 3A com contedo de DL sem afet-lo ;apenas modifica o estado do flag de carry JL 010F ;salta ao endereo 010f, se for menor ADD DL,07 ;Adiciona o valor 07 a DL INT 21 ;Chama interrupo do DOS INT 20 ;Finaliza o programa
Stimo exemplo
Este programa imprime um valor zero em dgitos hexadecimais.
-a100 297D:0100 297D:0102 297D:0104 297D:0107 297D:010A 297D:010D 297D:010F 297D:0112 297D:0114 MOV AH,02 ;Funo 2 (escreve caractere na tela) MOV DL,BL ;Pe o valor de BL em DL AND DL,0F ;Transporta fazendo AND dos nmeros bit a bit ADD DL,30 ;Adiciona 30 a Dl CMP DL,3A ;Compara Dl com 3A JL 0112 ;Salta ao endereo 0112, se menor ADD DL,07 ;Adiciona 07 a DL INT 21 ;Chama interrupo do DOS INT 20 ;Finaliza o programa
Oitavo exemplo
-a100 297D:0100 297D:0102 297D:0104 297D:0106 297D:0108 297D:010B 297D:010E 297D:0110 297D:0113 297D:0115 MOV AH,02 ;Funo 2 (escreve caractere na tela) MOV DL,BL ;Pe o valor de BL em DL MOV CL,04 ;Pe o valor 04 em CL SHR DL,CL ;Desloca os 4 bits mais altos do nmero ;ao nibble mais direita ADD DL,30 ;Adiciona 30 a DL CMP DL,3A ;Compara Dl com 3A JL 0113 ;Salta ao endereo 0113, se menor ADD DL,07 ;Adiciona 07 a DL INT 21 ;Chama interrupo do DOS INT 20 ;Finaliza o programa
Nono exemplo
-a100 297D:0100 297D:0102 297D:0104 297D:0106 297D:0108 297D:010B 297D:010E 297D:0110 297D:0113 297D:0115 297D:0117 297D:011A 297D:011D 297D:0120 297D:0122 297D:0125 297D:0127 MOV AH,02 ;Funo 2 (escreve caractere na tela) MOV DL,BL ;Pe o valor de BL em DL MOV CL,04 ;Pe o valor 04 em CL SHR DL,CL ;Desloca os 4 bits mais altos do nmero ;ao nibble mais direita ADD DL,30 ;Adiciona 30 a DL CMP DL,3A ;Compara Dl com 3A JL 0113 ;Salta ao endereo 0113, se menor ADD DL,07 ;Adiciona 07 a DL INT 21 ;Chama interrupo do DOS MOV DL,BL ;Pe o valor de BL em DL AND DL,0F ;Transporta fazendo AND dos nmeros bit a bit ADD DL,30 ;Adiciona 30 a DL CMP DL,3A ;Compara Dl com 3A JL 0125 ;Salta ao endereo 0125, se menor ADD DL,07 ;Adiciona 07 a DL INT 21 ;Chama interrupo do DOS INT 20 ;Finaliza o programa
Dcimo exemplo
-a100 297D:0100 297D:0102 297D:0104 297D:0106 297D:0109 297D:010C 297D:010E 297D:0111 297D:0113 297D:0115 297D:0117 297D:0119 297D:011B 297D:011D 297D:011F 297D:0121 MOV AH,01 ;Funo 1 (l caractere do teclado) INT 21 ;Chama interrupo do DOS MOV DL,AL ;Pe o valor de AL em DL SUB DL,30 ;Subtrai 30 de DL CMP DL,09 ;Compara DL com 09 JLE 0111 ;Salta ao endereo 0111, se menor ou igual SUB DL,07 ;Subtrai 07 de DL MOV CL,04 ;Pe o valor 04 em CL SHL DL,CL ;Insere zeros direita INT 21 ;Chama interrupo do DOS SUB AL,30 ;Subtrai 30 de AL CMP AL,09 ;Compara AL com 09 JLE 011F ;Salta ao endereo 011f, se menor ou igual SUB AL,07 ;Subtrai 07 de AL ADD DL,AL ;Adiciona AL a DL INT 20 ;Finaliza o programa
-a200 297D:0200 PUSH DX ;Pe o valor de DX na pilha 297D:0201 MOV AH,08 ;Funo 8 297D:0203 INT 21 ;Chama interrupo do DOS 297D:0205 CMP AL,30 ;Compara AL com 30 297D:0207 JB 0203 ;Salta se CF ativado ao endereo 0203 297D:0209 CMP AL,46 ;Compara AL com 46 297D:020B JA 0203 ;Salta ao endereo 0203, se diferente 297D:020D CMP AL,39 ;Compara AL com 39 297D:020F JA 021B ;Salta ao endereo 021B, se diferente 297D:0211 MOV AH,02 ;Funo 2 (escreve caractere na tela) 297D:0213 MOV DL,AL ;Pe o valor de AL em DL 297D:0215 INT 21 ;Chama interrupo do DOS 297D:0217 SUB AL,30 ;Subtrai 30 de AL 297D:0219 POP DX ;Extrai o valor de DX da pilha 297D:021A RET ;Retorna o controle ao programa principal 297D:021B CMP AL,41 ;Compara AL com 41 297D:021D JB 0203 ;Salta se CF ativado ao endereo 0203 297D:021F MOV AH,02 ;Funo 2 (escreve caractere na tela) 297D:022 MOV DL,AL ;Pe o valor AL em DL 297D:0223 INT 21 ;Chama interrupo do DOS 297D:0225 SUB AL,37 ;Subtrai 37 de AL 297D:0227 POP DX ;Extrai o valor de DX da pilha 297D:0228 RET ;Retorna o controle ao programa principal
Este programa se mantm lendo caracteres at receber um que possa ser convertido para um nmero hexadecimal.