Sei sulla pagina 1di 62

Linguagem de

Montagem
Assembly

Disciplina: Arquitetura de Computadores


Prof. Ms. Rafael Carvalho de Mendonça
Conceitos Básicos de
Assembly

O que é Assembly?


Por que usar Assembly?


Por que aprender Assembly?


Uso no dia a dia


O que é um Sistema Computacional?


Qual suas partes?

Processador cental

Memória Principal

Unidades de Entrada e Saída

Unidades de Memórias Auxiliares
Conceitos Básicos de
Assembly – Informações no
Computadores


Unidades de informação


Conversão de números binários para decimais


Conversão de decimais para binários


Sistema Hexadecimal
Conceitos Básicos de
Assembly – Métodos de
Representação de Dados

➔Representação de dados
➔ASCII
➔BCD
➔Ponto Flutuante
Conceitos Básicos de
Assembly – DEBUG

Existe um programa DEBUG para Assembly?


Quais comandos que podem ser executados no DEBUG?

A - montar instruções simbólicas em código de máquina

D – mostrar o conteúdo de uma área de memória

E – entrar dados na memória, iniciando num endereço
específico

G – rodar um programa executável na memória

N – dar nome a um programa

P – proceder, ou executar um conjunto de instruções
relacionadas

Q – sair do programa debug

R – mostrar o conteúdo de um ou mais registradores

T – executar passo a passo as instruções

U – desmontar o código de máquina em instruções simbólicas

W – gravar um programa em disco
Conceitos Básicos de
Assembly – Estrutura

Nas linhas de código em Linguagem Assembly há duas partes: a
primeira é o nome da instrução a ser executada; a segunda, os
parâmetros do comando.

Por exemplo: add ah bh


Conceitos Básicos de
Assembly – Registradores

Registradores

Lista de registradores

AX Registrador Acumulador

BX Registrador Base

CX Registrador Contador

DX Registrador de Dados

DS Registrador de Segmentos de Dados

ES Registrador de Segmento Exta

SS Registrador de Segmento de Pilha

CS Registrador de Segmento de Código

BP Registrador Apontador da Base

SI Registrador de Índice Fonte

DI Registrador de Índice Destino

SP Registrador Apontador de Pilha

IP Registrador Apontador da Próxima Instrução

F Registrador de Flag
Conceitos Básicos de
Assembly – Comandos
Básicos

MOV (local 1), (local 2) copia o conteúdo do local 2 para o local
1


Exemplos:

MOV EAX, 7770

MOV EAX, EBX


INC (registrador) incrementa “soma” o valor do registrador em
1


Exemplos:

INC EAX

INC EBX
Conceitos Básicos de
Assembly – Comandos
Básicos

Comandos de saltos


JUMP – obtém o endereço da próxima execução baseado em
uma condição


JZ, JNZ, JS, JNS, JNO <LABEL>


Exemplos:

Laco1:

INC EAX

JNO Laco1
Programação em
Linguagem de Montagem
Todo computador tem uma ISA (Instruction Set Architecture –
arquitetura do conjunto de instruções), que é um conjunto de
registradores, instruções e outras características visíveis para
seus programadores de baixo nível. Essa iSA costuma ser
denominada linguagem de máquina, embora o termo não seja
de todo exato.

Um programa nesse nível de abstração é uma longa lista de


números binários, um por instrução, que informa quais instruções
executar e quais são seus operandos. Programar com números
binários é muito difícil, portanto, todas as máquinas têm uma
linguagem de montagem (ou assembly), uma representação
simbólica da arquitetura do conjunto de instruções com nomes
simbólicos como ADD, SUB e MUL, em vez de números binários
Programação em
Linguagem de Montagem

O objetivo deste estudo é fazer com que o aluno


possa aprender sobre arquitetura de computadores
por meio de experiência prática. Assim, foi escolhida a
máquina Intel 8088 como exemplo de trabalho.
Embora hoje as 8088s sejam raramente encontradas
todo Core i7 é capaz de executar programas 8088,
portanto, as lições aprendidas aqui ainda se aplicam
às máquinas modernas.
Linguagem de Montagem

Todo assembler usa mnemônicos, isto é, palavras curtas como


ADD, SUB e MUL para instruções de máquina como somar,
subtrair e multiplicar para que fiquem mais fáceis de lembrar.
Além disso, assemblers permitem a utilização de nomes
simbólicos para constantes e rótulos para indicar endereços de
instrução e memória. Ademais, grande parte dos assemblers
suporta certo número de pseudoinstruções, que não são
traduzidas para instruções ISA, mas que são comandos para o
assembler que direcionam o processo de montagem.
Linguagem de Montagem


Quando um programa em linguagem de
montagem é alimentado em um programa
denominado assembler, este o converte em um
programa binário adequado para a execução
propriamente dita. Então, ele pode ser
executado no hardware em questão.


Simulador, interpretador ou rastreador (debug)
Linguagem de Montagem

No slide a seguir é mostrado um programa simples


em linguagem de montagem para o 8088. Os
números após os pontos de exclamação são os
números das linhas da fonte, para facilitar a
referência às partes do programa.

Esse programa de montagemtêm o sufixo .s, que


indica que ele é um programa-fonte de linguagem de
montagem.
Linguagem de Montagem
! Simple "hello world" program
! See section 9.8.1.

_EXIT =1 ! 1
_WRITE = 4 ! 2
_STDOUT = 1 ! 3
.SECT .TEXT ! 4
start: ! 5
MOV CX,de-hw ! 6
PUSH CX ! 7
PUSH hw ! 8
PUSH _STDOUT ! 9
PUSH _WRITE ! 10
SYS ! 11
ADD SP,8 ! 12
SUB CX,AX ! 13
PUSH CX ! 14
PUSH _EXIT ! 15
SYS ! 16
.SECT .DATA ! 17
hw: ! 18
.ASCII "Hello World\n" ! 19
de: .BYTE 0 ! 20
.SECT .BSS
Linguagem de Montagem
A tela do rastreador, mostrada na figura abaixo,
contém sete janelas, cada uma com informações
diferentes sobre o estado do programa binário que
está sendo executado.
Linguagem de Montagem

Na parte de cima, há três janelas, duas maiores e


uma menor no meio. A janela na parte superior
esquerda mostra o conteúdo do processador, que
consiste nos valores correntes dos registradores de
segmentos, CS, DS, SS e ES, dos registradores
aritméticos, AH, AL, AX, e de outros.
Linguagem de Montagem
A janela do meio nessa linha de cima contém a pilha,
uma área de memória usada para valores
temporários.

A janela à direita nessa parte superior contém um


fragmento do programa em linguagem de montagem
e a seta indica qual instrução está sendo executada
no momento em questão. À medida que o programa é
executado, a instrução corrente muda e a seta se
move para apontá-la. A força do rastreador é que,
acionando a tecla de Return (Enter, nos teclados de
PCs), uma única instrução é executada e todas as
janelas são atualizadas, o que possibilita executar o
programa em câmera lenta.
Linguagem de Montagem

Abaixo da janela à esquerda há outra janela que


contém a pilha de chamadas de sub-rotina que, em
nosso exemplo, está vazia. Abaixo dela estão
comandos para o próprio rastreador. À direita dessas
duas janelas há uma janela para entrada, saída e
mensagens de erro.
Linguagem de Montagem

Embaixo dessas janelas há outra que mostra uma


parte da memória. Essas janelas serão discutidas com
mais detalhes mais à frente, mas a ideia básica deve
estar clara: o rastreador mostra o programa-fonte, os
registradores da máquina e uma boa quantidade de
informações sobre o estado do programa que está em
execução. À medida que cada instrução é executada,
a informação é atualizada, o que permite ao usuário
ver, com grande detalhe, o que o programa está
fazendo.
Processador 8088

Cada processador, incluindo o 8088, tem um estado


interno, no qual mantém certas informações
fundamentais. Para essa finalidade, o processador
tem um conjunto de registradores nos quais essas
informações podem ser armazenadas e processadas.
Provavelmente o mais importante deles é o PC
(Program Counter – contador de programa) que
contém a localização de memória, isto é, o endereço,
da próxima instrução a ser executada. Esse
registrador também é denominado IP (Instruction
Pointer – ponteiro de instrução). Essa instrução está
localizada em uma parte da memória principal
denominada segmento de código.
Processador 8088

A memória principal no 8088 pode ter até um pouco


mais de 1 MB de tamanho, mas o segmento de código
corrente tem apenas 64 KB. O registrador CS na
figura do rastreador informa onde o segmento de
código de 64 KB começa dentro da memória de 1 MB.
Um novo segmento de código pode ser ativado pela
simples mudança do valor no registrador CS. De
modo semelhante, também há um segmento de
dados de 64 KB, que informa onde os dados
começam.
Processador 8088

Na figura do rastreador, sua origem é dada pelo


registrador DS, que também pode ser alterado
conforme necessário para acessar dados fora do
segmento de dados corrente. Os registradores CS e
DS são necessários porque o 8088 tem registradores
de 16 bits, portanto, eles não podem conter,
diretamente, os endereços de 20 bits necessários
para referenciar toda a memória de 1 MB. É por isso
que os registradores de segmentos de dados e de
código foram introduzidos.
Processador 8088

Os outros registradores contêm dados ou ponteiros


para dados na memória principal. Em programas em
linguagem de montagem, esses registradores podem
ser acessados diretamente. À parte desses
registradores, o processador também contém todo o
equipamento necessário para executar as instruções,
mas essas partes estão disponíveis para o
programador somente por meio de instruções.
O ciclo do Processador
A operação do 8088 (e de todos os outros
computadores) consiste em executar instruções, uma
após a outra. A execução de uma única instrução
pode ser subdividida nas seguintes etapas:
1.Buscar a instrução na memória no segmento
de código usando o PC.
2.incrementar o contador de programa.
3.Decodificar a instrução buscada.
4.Buscar os dados necessários na memória e/ou
nos registradores do processador.
5.Executar a instrução.
6.Armazenar os resultados da instrução na
memória e/ou registradores.
7.voltar à etapa 1 para iniciar a instrução
seguinte.
O ciclo do Processador

Do ponto de vista de um programador em linguagem


de montagem, o 8088 tem um conjunto de 14
registradores.
Eles são, de certo modo, o bloco de rascunho onde as
instruções operam, e estão em constante uso, embora
os resultados neles armazenados sejam muito
voláteis. A figura a seguir dá uma visão geral desses
14 registradores. É claro que essa figura e a janela de
registradores do rastreador da figura anterior são
muito semelhantes, pois representam a mesma
informação.
Os registradores do 8088
Os registradores do 8088

Os registradores do 8088 têm 16 bits de largura. Não


existem dois registradores que sejam completamente
equivalentes em termos funcionais, porém alguns
deles compartilham certas características, portanto,
são divididos em grupos na figura. Agora, vamos
discutir os diferentes grupos.
Os registradores gerais

Os registradores do primeiro grupo, AX, BX, CX e


DX, são os registradores gerais. O primeiro desse
grupo, AX, é denominado registrador acumulador. Ele
é usado para coletar resultados de computações e é o
alvo de muitas das instruções. Embora cada
registrador possa executar grande quantidade de
tarefas, em algumas instruções, esse AX é o destino
implícito, por exemplo, na multiplicação.
Os registradores gerais

O segundo registrador é o BX, o registrador de


base. Para muitas finalidades, o BX pode ser usado
da mesma maneira que o AX, mas ele tem um poder
que o AX não possui. É possível colocar um endereço
de memória em BX e então executar uma instrução
cujo operando vem do endereço de memória contido
em BX. Em outras palavras, BX pode conter um
ponteiro para a memória, mas AX não. Para mostrar
isso, comparamos duas instruções.
Os registradores gerais

Em primeiro lugar, temos


MOV AX,BX
que copia para AX o conteúdo de BX. Em segundo
lugar, temos
MOV AX,(BX)
que copia para AX o conteúdo da palavra de memória
cujo endereço está contido em BX. No primeiro
exemplo, BX contém o operando fonte; no segundo,
ele aponta para o operando fonte. Em ambos os
exemplos, note que a instrução MOV tem um
operando fonte e um destino, e que o destino está
escrito antes da fonte.
Os registradores gerais

O próximo é CX, o registrador contador. Além de


realizar muitas outras tarefas, é usado em especial
para conter contadores para laços. Ele é
automaticamente decrementado na instrução LOOP,
e os laços costumam ser encerrados quando CX
chega a zero.
Os registradores gerais

O quarto registrador do grupo geral é DX, o


registrador de dados. Ele é usado junto com AX em
instruções de comprimento de palavra dupla (isto é,
32 bits). Nesse caso, DX contém os 16 bits de ordem
alta e AX possui os 16 bits de ordem baixa. Os
inteiros de 32 bits costumam ser indicados pelo
termo longo. O termo duplo é normalmente
reservado para valores de ponto flutuante de 64 bits,
embora há quem use “duplo” para inteiros de 32 bits.
Os registradores gerais

Todos esses registradores gerais podem ser


entendidos como um registrador de 16 bits ou como
um par de registradores de 8 bits. Desse modo, o
8088 tem exatos oito registradores diferentes de 8
bits, que podem ser usados em instruções de byte e
de caracteres. Nenhum dos outros registradores pode
ser dividido em metades de 8 bits. Algumas
instruções usam um registrador inteiro, como AX,
porém outras instruções usam apenas metade de
um registrador, como AL ou AH.
Os registradores gerais

Em geral, instruções que efetuam aritmética usam os


registradores completos de 16 bits, mas as que lidam
com caracteres em geral usam os de 8 bits. Todavia,
é importante entender que AL e AH são apenas
nomes para ambas as metades de AX. Quando AX é
carregado com um novo valor, tanto AL quanto
AH são mudados, respectivamente, para as metades
inferior e superior do número de 16 bits colocado em
AX.
Os registradores gerais
Para ver como AX, AH e AL interagem, considere a
instrução
MOV AX,258
que carrega o registrador AX com o valor decimal
258. Após essa instrução, o registrador de bytes AH
contém o valor 1, e o registrador de bytes AL contém
o número 2. Se essa instrução for seguida pela de
soma de bytes
ADDB AH,AL
então o registrador de bytes AH é incrementado pelo
valor em AL (2), de modo que, agora, ele contém 3.
O efeito dessa ação sobre o registrador AX é que seu
valor agora é 770, o que equivale a 00000011
00000010 em notação binária, ou a 0x03 0x02 em
notação hexadecimal.
Os registradores gerais

Os registradores de oito bytes de largura são quase


intercambiáveis, com a exceção que AL sempre
contém um dos operandos na instrução MULB, e é o
destino implícito dessa operação, junto com AH.
DIVB também usa o par AH : AL para o dividendo. O
byte mais baixo do registrador de contador CL pode
ser usado para conter o número de ciclos em
instruções de deslocamento e rotação.
Registradores de ponteiros

O segundo grupo de registradores consiste nos


registradores de ponteiros e índices. O registrador
mais importante desse grupo é o ponteiro de pilha,
que é indicado por SP. Pilhas são importantes na
maioria das linguagens de programação. A pilha é um
segmento de memória que contém certas informações
de contexto sobre o programa em execução.
Registradores de ponteiros

Em geral, quando um procedimento é chamado, parte


da pilha é reservada para conter as variáveis locais do
procedimento, o endereço para onde retornar quando
o procedimento estiver concluído e outras
informações de controle. A porção da pilha relativa a
um procedimento é denominada seu quadro de
pilha.
Registradores de ponteiros

Quando um procedimento chamado chama outro, um


quadro de pilha adicional é alocado, em geral logo
abaixo do quadro corrente. Chamadas adicionais
alocam quadros de pilha adicionais abaixo dos atuais.
Embora não seja obrigatório, pilhas quase sempre
crescem para baixo, de endereços altos para baixos.
Não obstante, o endereço numérico mais baixo
ocupado na pilha é sempre denominado o topo dela.
Registradores de ponteiros

Além de utilizadas para conter variáveis locais, pilhas


também podem conter resultados temporários. O
8088 tem uma instrução, PUSH, que coloca uma
palavra de 16 bits no topo da pilha. Essa instrução
primeiro decrementa SP de 2, então armazena seu
operando no endereço que SP está apontando agora.
De modo semelhante, a instrução POP retira uma
palavra de 16 bits do topo da pilha buscando o valor
no topo e então incrementando SP em 2. O
registrador SP aponta para o topo e é modificado por
instruções PUSH, POP e CALL, sendo decrementado
por PUSH, incrementado por POP e decrementado
por CALL.
Registradores de ponteiros

O próximo nesse grupo é BP, o registrador de base.


Em geral, ele contém um endereço na pilha. Enquanto
SP sempre aponta para o topo, BP pode apontar para
qualquer local dentro da pilha. Na prática, um uso
comum para BP é apontar para o início do quadro de
pilha do procedimento corrente, de modo a ficar mais
fácil achar as variáveis locais do procedimento.
Registradores de ponteiros

Assim, BP aponta para a parte de baixo do quadro de


pilha corrente (a palavra de quadro de pilha que tem
o endereço numérico mais alto) e SP aponta para o
topo (a palavra de quadro de pilha corrente que tem o
endereço numérico mais baixo). Assim, o quadro de
pilha corrente é delimitado por BP e SP.
Registradores de ponteiros

Nesse grupo, há dois registradores de índice: SI, o


índice de origem, e DI, o índice de destino. Eles
costumam ser usados em combinação com BP para
endereçar dados na pilha, ou com BX para calcular os
endereços de localização de dados de memória.
Deixamos o tratamento mais extensivo desses
registradores para a seção que trata de modos de
endereçamento.
Registradores de ponteiros

Um dos registradores mais importantes, que é um


grupo em si, é o ponteiro de instrução, nome que a
intel dá para o contador de programa (PC). Ele não
é endereçado diretamente pelas instruções, mas
contém um endereço no segmento de código de
programa da memória. O ciclo de instrução do
processador começa pela busca da instrução apontada
pelo PC. Então, esse registrador é incrementado
antes que o restante da instrução seja executado.
Desse modo, esse contador de programa aponta para
a primeira após a instrução corrente.
Registradores de ponteiros

O registrador de flag ou registrador de código de


condição é, na verdade, um conjunto de
registradores de um único bit. Alguns dos bits são
marcados por instruções aritméticas e estão
relacionados com o resultado, como segue:

Z – resultado é zero
S – resultado é negativo (bit de sinal)
V – resultado gerou um excesso
C – resultado gerou um vai-um
A – vai-um auxiliar (vai-um do bit 3)
P – paridade do resultado
Registradores de ponteiros

Outros bits nesse registrador controlam a operação de


certos aspectos do processador. O bit i habilita
interrupções. O bit T habilita o modo de
rastreamento, que é usado para depuração. Por fim, o
bit D controla a direção das operações de cadeia de
caracteres (string). Nem todos os 16 bits desse
registrador de flag são utilizados; os que não são,
estão ligados eletricamente a zero.
Registradores de ponteiros
Há quatro registradores no grupo de registradores de
segmentos. Lembre-se de que a pilha, os dados e
os códigos de instrução, todos residem na memória
principal, mas, geralmente, em partes diferentes. Os
registradores de segmentos comandam essas partes
diferentes da memória, que são denominadas
segmentos. Esses registradores são denominados CS
para o de segmentos de código, DS para o de
segmentos de dados, SS para o de segmentos de
pilha e ES para o de segmentos extras. Na maior
parte do tempo, seus valores não são alterados.
Na prática, o segmento de dados e o de pilha usam a
mesma parte da memória, e os dados ficam na parte
inferior do segmento e a pilha no topo.
Memória e endereçamento

O 8088 tem uma organização de memória um tanto


deselegante por combinar uma memória de 1 MB com
registradores de 16 bits. Com uma memória de 1 MB,
são necessários 20 bits para representar um endereço
de memória. Assim, é impossível armazenar um
ponteiro para memória em qualquer dos registradores
de 16 bits. Para contornar esse problema, a memória
é organizada como segmentos, cada um deles de 64
KB, de modo que um endereço dentro de um
segmento pode ser representado em 16 bits. Agora,
vamos entrar em mais detalhes sobre a arquitetura
da memória do 8088.
Organização da memória e
segmentos
A memória do 8088, que consiste apenas em um
vetor de bytes de 8 bits endereçáveis, é usada para o
armazenamento de instruções, bem como para o
armazenamento de dados e para a pilha. Para separar
as partes da memória que são usadas para essas
diferentes finalidades, o 8088 usa segmentos que
são partes destacadas para certos usos. No 8088, tal
segmento consiste em 65.536 bytes consecutivos.
Organização da memória e
segmentos
Há quatro segmentos:

1. O segmento de código.

2. O segmento de dados.

3. O segmento de pilha.

4. O segmento extra.
Organização da memória e
segmentos
O segmento de código contém as instruções do
programa. O conteúdo do registrador PC é sempre
interpretado como um endereço de memória no
segmento de código. Um valor de PC igual a 0 refere-
se ao endereço mais baixo no segmento de código e
não ao endereço absoluto de memória zero. O
segmento de dados contém os dados inicializados e
não inicializados para o programa.
Organização da memória e
segmentos

Quando BX contém um ponteiro, ele aponta para


esse segmento de dados. O segmento de pilha
contém variáveis locais e resultados intermediários
passados para a pilha. Endereços em SP e BP estão
sempre nesse segmento de pilha. O segmento extra é
um registrador de segmentos avulsos que pode ser
colocado em qualquer lugar da memória onde seja
necessário.
Organização da memória e
segmentos
Para cada um dos segmentos existe um registrador de
segmentos correspondente: os de 16 bits CS, DS,
SS e ES. O endereço de início de um segmento é o
inteiro de 20 bits sem sinal que é construído
deslocando o registrador de segmentos 4 bits para a
esquerda e colocando zeros nas quatro posições da
extrema direita. Isso significa que esses registradores
sempre indicam múltiplos de 16, em um espaço de
endereços de 20 bits.
Organização da memória e
segmentos

O registrador de segmentos aponta para a base do


segmento. Endereços dentro do segmento podem ser
construídos convertendo-se o valor de 16 bits do
registrador para seu verdadeiro endereço de 20 bits,
acrescentando quatro bits zero ao final, e somando o
deslocamento a esse resultado. Na verdade, um
endereço absoluto de memória é calculado
multiplicando-se o registrador de segmentos por 16 e
então somando o deslocamento ao resultado.
Organização da memória e
segmentos

Por exemplo, se DS for igual a 7, e BX for 12, então o


endereço indicado por BX é 7 × 16 + 12 = 124.
Em outras palavras, o endereço binário de 20 bits
implícito por DS = 7 é 00000000000001110000.
Somar o deslocamento de 16 bits 0000000000001100
(decimal 12) à origem do segmento dá o endereço de
20 bits 00000000000001111100 (decimal 124).
Os registradores gerais

Os registradores de oito bytes de largura são quase


intercambiáveis, com a exceção que AL sempre
contém um dos operandos na instrução MULB, e é o
destino implícito dessa operação, junto com AH.
DIVB também usa o par AH : AL para o dividendo. O
byte mais baixo do registrador de contador CL pode
ser usado para conter o número de ciclos em
instruções de deslocamento e rotação.
Os registradores gerais

Os registradores de oito bytes de largura são quase


intercambiáveis, com a exceção que AL sempre
contém um dos operandos na instrução MULB, e é o
destino implícito dessa operação, junto com AH.
DIVB também usa o par AH : AL para o dividendo. O
byte mais baixo do registrador de contador CL pode
ser usado para conter o número de ciclos em
instruções de deslocamento e rotação.
Os registradores gerais

Os registradores de oito bytes de largura são quase


intercambiáveis, com a exceção que AL sempre
contém um dos operandos na instrução MULB, e é o
destino implícito dessa operação, junto com AH.
DIVB também usa o par AH : AL para o dividendo. O
byte mais baixo do registrador de contador CL pode
ser usado para conter o número de ciclos em
instruções de deslocamento e rotação.
Compilação e Montagem

8088 Assembler and Tracer Toolkit:


https://github.com/StoDevX/as88


Compilar:
./as88 nome.s (não é necessário a extensão .s)


Executar código binário:
./s88 nome


Debug (debugger-tracer / rastreador):
./t88 nome
Compilação e Montagem

NASM - The Netwide Assembler:


http://www.nasm.us/pub/nasm/releasebuilds/
2.14rc0/

Compilar:
nasm -f elf nome.asm


Montando o código objeto:
ld -m elf_i386 nome.o -o nome


Executar código binário:
./nome
CRÉDITOS
NOME DO SETOR
NOMES DAS EQUIPES/CARGOS
E-MAILS
TELEFONES

Potrebbero piacerti anche