Universidade Federal de Santa Catarina
Centro Tecnológico
Departamento de Informática e Estatística
INE 5309 - Linguagem Assembly
Prof. Roberto Willrich


Aula Prática 01: Introdução à Linguagem Assembly


1. Introdução aos Registros do Processador 8088

A CPU tem 16 registros internos, cada um com 16 bits. Os 4 primeiros: AX, BX, CX e DX são registros de uso geral e podem ser usados como registros de 8 bits. Se usados em tal modo, é necessário referencia-los por exemplo como: AH e AL, que são os bytes altos e baixo do registros AX. Esta nomenclatura é também aplicável aos registros BX, CX e DX.

Os registros são conhecidos pelos seus nomes específicos:

2. Programa Debug

O Debug fornece um conjunto de comandos que deixa você executar um número de operações úteis. Alguns dos comandos do Debug estão apresentados na tabela abaixo.
 

Comando
Significado
Sintaxe
?
Imprime os comandos do Debug na tela ?
A
Permite montar o programa (translação das instruções Assembly em linguagem de máquina) a [end]
D
Apresenta o conteúdo de uma área de memória d [end]
E
Permite entrar o dado em uma memória e [end]
G
Executa um programa na memória g [end-ini] [end-fin]
H
Calcula a soma e a diferença de dois valores hexadecimais h [valorl] [valor2]
L
Carrega um programa do disco na memória l
N
Define um nome para o programa n [nome.ext]
Q
Permite abandonar o programa Debug q
R
Apresenta o conteúdo de um ou mais registradores r
T
Realiza o "Trace" de um programa (executa 1 comando) t
U
Permite desassemblar o código de máquina em código simbólico u [end-ini] [end-fin]
W
Permite escrever o programa em disco w

Para iniciar o trabalho com Debug, digite o seguinte comando no seu computador:
C:/>Debug [Enter]
-

Na próxima linha um traço aparecerá, ele é o prompt do Debug, neste momento as instruções do debug podem ser introduzidas. Por exemplo,
é possível visualizar os valores dos registros internos da CPU usando o seguinte comando:

-r[Enter]
AX=0000 BX=0000 CX=0446 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=1175 ES=1175 SS=1175 CS=1175 IP=0100 NV UP EI PL NZ NA PO NC
6897:0100 58 POP BX

Todos os conteúdos dos registros internos da CPU serão apresentados. Observe que, embora o seu computador apresente outros valores, os valores armazenados nos arquivos CS, DS, SS, ES são idênticos, assim todos os quatro segmentos têm o mesmo endereço de base (são mapeados no mesmo bloco de memória), características dos programas .COM.

É possível alterar os valores dos registros usando o comando "r". Veja exemplo abaixo:

-rbx[Enter]
BX 0000
:

Esta instrução apresentará o conteúdo do registro BX e o indicador Debug é mudado de "-" para ":". Quando o prompt é igual a ":", é possível mudar o valor do registro definido no parâmetro de entrada. Por exemplo, digite um número e digite [Enter]. Verifique novamente o valor dos registros utilizando o comando "r".

3. Estrutura Assembler

Linhas de código Assembly tem duas partes, a primeira é o nome da instrução que será executada, e a segunda são os parâmetros do comando. Por exemplo: MOV AL, 25. Aqui "MOV" é um comando a ser executado, no caso uma transferência de dados, e "AL" e "25" são os parâmetros. O nome das instruções na linguagem é feita de dois, três ou quatro letras. Estas instruções são chamadas de mnemônicos ou códigos de operação, desde que eles representam uma função que o processador executará.

Algumas instruções são usadas da seguinte forma: ADD AL, [170]. Os colchetes no segundo parâmetro indica-nos que nós estamos trabalhando com o conteúdo da célula de memória de número 170 e não com o valor 170. Isto é conhecido como endereçamento direto.

4. Criando um Programa Assembly Básico

O primeiro passo para ser criar um programa Assembly é iniciar o Debug, este passo consiste em digitar Debug[Enter] no prompt do DOS. Para montar um programa no Debug, o comando "a" (assemble) é usado. O endereço inicial do programa pode ser entrado como parâmetro, se este parâmetro é omitido a montagem será iniciada na localização especificada por CS:IP, tipicamente o deslocamento (IP) é 0100h, que é a localidade onde programas com a extensão .COM devem ser iniciados. Neste momento não é necessário dar ao comando "a" um parâmetro, isto é recomendável para evitar problemas desde que os registros CS:lP são utilizados, portanto nós digitamos:

a [Enter]
mov ax, 0002[Enter]
mov bx, 0004[Enter]
add ax, bx[Enter]
nop[Enter][Enter]

O que este programa faz? Move o valor 0002 para o registro AX, move o valor 0004 para o registro BX, adiciona os conteúdos dos registros AX e BX e armazena o resultado em AX. Finalmente, a instrução não operação (nop) é para notificar o fim do programa.

Após digitado (corretamente) este código, aparecerá na tela algo parecido com as seguintes linhas:

-a
1175:0100 mov ax,0002
1175:0103 mov bx,0004
1175:0106 add ax,bx
1175:0108 nop
1175:0109

Como já apresentado o comando "a" permite montar o programa de máquina. Debug monta o programa linha a linha. Por exemplo, quando nós digitalmos o [Enter] após a instrução mov ax,0002, debug automaticamente translada a linguagem simbólica em código de máquina. Caso nós digitarmos alguma instrução inválida,  o debug indicará o erro após digitarmos [Enter]. Tente por exemplo armazenar a instrução MOV AZ,2 a partir da memória 200h.

Os números que antecedem a instrução indica a localização em memória onde o código de máquina correspondente será armazenado. Por exemplo, a instrução add ax,bx está armazenada a partir de 1175:0106 (o primeiro número é o endereço base do segmento de código e o segundo é o deslocamento neste segmento). O número de byte que ocupa uma instrução é dependente do tipo de instrução e de seus operandos. É fácil observar que a instrução mov ax,0002 ocupa 3 bytes (100h a 102h), pois ela está armazenada do endereço 1175:1175:0100 até 1175:0102. Como nós trataremos apenas programas .COM, nós podemos por simplificação eliminar o endereço de base do segmento de código e indicar unicamente o offset. Assim podemos dizer que a instrução nop tem um tamanho de 1 byte e está armazenada em 108.

Para ver o código de máquina gerado por nosso programa nós podemos utilizar a instrução "u". Esta instrução desassembla uma certa região de memória indicada nos parâmetros. Como nosso programa está armazenado entre 100h e 108h, passamos estes dois endereços como parâmetro da instrução "u".

-a
1175:0100 B80200  MOV AX,0002
1175:0103 BB0400  MOV BX,0004
1175:0106 01D8    ADD AX,BX
1175:0108 90      NOP

Aqui podemos ver, por exemplo, que o código de máquina gerado pela instrução MOV AX,0002 são os 3 bytes B8.02.00. Para ver o código de máquina em memória sem ver o correspondente simbólico é somente usar o comando "d 100 108".

5. Teste do Programa

O Debug permite depurar programas através da execução passo-a-passo do programa. Isto é poderemos testar o programa executando instrução a instrução. Assim podemos acompanhar os valores dos registros e dos conteúdos das memórias envolvidas.

Inicialmente, antes de executarmos o passo-a-passo, você deve verificar se o valor do IP é 100h. Isto pois este registro, como vimos anteriormente, indica a próxima instrução a ser executada. Verifique então o valor de IP e se necessário atualize o valor para 100h. Após isso Ddigite o comando "t" (trace), para executar passo-a-passo este programa, assim:

-t
AX=0002 BX=0000 CX=0000 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000
DS=1175 ES=1175 SS=1175 CS=1175 IP=0103 NV UP EI PL NZ NA PO NC
6897:0100 BB0400 MOV BX,0004

Você pode ver que o valor 2 é movido para o registro AX. Note também que o valor de IP passa de 0100 para 0103, isto é, ele passa a apontar para a próxima instrução a ser executada. Digite o comando "t" novamente e você verá a segunda instrução se executar.

-t
AX=0002 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 Sl=0000 Dl=0000
DS=l175 ES=l175 SS=l175 CS=1175 IP=0106 NV UP EI PL NZ NA PO NC
6897:0100 01D8 ADD AX,BX

Digite o comando "t" novamente para ver a instrução adição ser executada, você verá a seguinte linha:

-t
AX=0006 BX=0004 CX=0000 DX=0000 SP=FFFE BP=0000 Sl=0000 Dl=0000
DS=1175 ES=1175 SS=1175 CS=1175 IP=0108 NV UP EI PL NZ NA PO NC
6897:0100 90 NOP

Existe a possibilidade de que os registros contenham valores diferentes dos apresentados, mas AX e BX deverão ter os mesmos valores, desde que eles são os únicos que nós modificamos.A instrução NOP não realiza nenhuma operação, ela foi colocada aqui para indicar o fim de nosso programa.

Para sair do Debug use o comando "q" (quit)

6. Acesso a Memória

Na memória, cada byte tem um endereço único que vai de 00000h a FFFFFh. Dois bytes consecutivos são chamados de palavra (word) e poderá começar em endereço par ou impar da memória. Uma regra definida pela Intel (construtora do 8088), o byte mais significativo de um work é armazenado no endereço maior e o byte menos significativo no endereço menor. Execute o programa abaixo e veja as alterações na memória e registro.

Teste o programa abaixo.

MOV AH,[200]    ; Movimenta o byte contido em 200h para o registro AH
SUB AH,2        ; Subtrai de 2 o valor do registro AH
MOV [201],AH    ; Armazena conteúdo de AH na memória DS:201h
MOV AX,[200]    ; Movimenta o word contido em 200h para o registro AH
INC AX          ; Incrementa de 1 o valor do registro AH
MOV [205],AX    ; Armazena conteúdo de AH na memória DS:205h

7. Exercício

Faça um programa em assembly que realize as seguintes operacoes matemática:

Para tal, considere que A esteja na posição de memória 200h, B na posição 202h e C na posição 203h