Logo Passei Direto
Buscar
Material
páginas com resultados encontrados.
páginas com resultados encontrados.

Prévia do material em texto

Unidade IV
Acessando Unidades Funcionais Básicas 
em Assembly
Linguagem de 
Montagem
Diretor Executivo 
DAVID LIRA STEPHEN BARROS
Gerente Editorial 
ALESSANDRA VANESSA FERREIRA DOS SANTOS
Projeto Gráfico 
TIAGO DA ROCHA
Autoria 
GISELLE AZEVEDO PINTO
AUTORIA
Giselle Azevedo Pinto
Olá. Sou formada em Sistemas de Informação e pós-graduada em 
Cibersegurança e em Produção e Sistemas, mestra em Engenharia de 
Produção, com experiência técnico-profissional de mais de 20 anos na 
área de Tecnologia da Informação. Sou apaixonada pelo que faço e adoro 
transmitir minha experiência de vida àqueles que estão iniciando em suas 
profissões. Por isso, fui convidada pela Editora Telesapiens a integrar seu 
elenco de autores independentes. Estou muito feliz em poder ajudar você 
nesta fase de muito estudo e trabalho. Conte comigo!
ICONOGRÁFICOS
Olá. Esses ícones irão aparecer em sua trilha de aprendizagem toda vez 
que:
OBJETIVO:
para o início do 
desenvolvimento 
de uma nova 
competência;
DEFINIÇÃO:
houver necessidade 
de apresentar um 
novo conceito;
NOTA:
quando necessárias 
observações ou 
complementações 
para o seu 
conhecimento;
IMPORTANTE:
as observações 
escritas tiveram que 
ser priorizadas para 
você;
EXPLICANDO 
MELHOR: 
algo precisa ser 
melhor explicado ou 
detalhado;
VOCÊ SABIA?
curiosidades e 
indagações lúdicas 
sobre o tema em 
estudo, se forem 
necessárias;
SAIBA MAIS: 
textos, referências 
bibliográficas 
e links para 
aprofundamento do 
seu conhecimento;
REFLITA:
se houver a 
necessidade de 
chamar a atenção 
sobre algo a ser 
refletido ou discutido;
ACESSE: 
se for preciso acessar 
um ou mais sites 
para fazer download, 
assistir vídeos, ler 
textos, ouvir podcast;
RESUMINDO:
quando for preciso 
fazer um resumo 
acumulativo das 
últimas abordagens;
ATIVIDADES: 
quando alguma 
atividade de 
autoaprendizagem 
for aplicada;
TESTANDO:
quando uma 
competência for 
concluída e questões 
forem explicadas;
SUMÁRIO
Manipulando registradores em linguagem Assembly ................ 10
Registradores Gerais ..................................................................................................................... 13
Registradores de ponteiro ........................................................................................................ 16
Acesso às portas lógicas em Assembly ............................................. 21
O que é uma porta? .......................................................................................................................25
Acessando uma porta em Assembly ................................................................................27
Utilização da memória em Assembly .................................................36
Organização da memória e segmentos .........................................................................37
Endereçamento ............................................................................................................................... 39
Aplicação de macro em linguagem Assembly ...............................48
Definindo uma macro .................................................................................................................. 49
Sintaxe de uma macro .................................................................................................................52
Biblioteca de macros ....................................................................................................................55
7
UNIDADE
04
Linguagem de Montagem
8
INTRODUÇÃO
Você sabia que a área de linguagem de montagem é uma das 
mais demandadas na indústria e será a responsável pela geração de 
muitos empregos nos próximos 10 anos? Isso mesmo. A linguagem de 
montagem está presente em todas as máquinas de uma empresa, 
indústria ou fábrica, independentemente do tipo de fabricante, pois se 
trata de uma linguagem universal para o ambiente tecnológico. Nesta 
unidade, iremos estudar sobre: o funcionamento dos registradores em 
programas em Assembly; a aplicação de comandos para acesso a portas 
lógicas utilizando a linguagem de montagem; a manipulação de dados em 
memória por meio da linguagem de montagem Assembly, identificando o 
propósito dos recursos; e, para finalizar, implementaremos uma macro em 
linguagem de montagem Assembly. Entendeu? Ao longo desta unidade 
letiva, você vai mergulhar neste universo!
Linguagem de Montagem
9
OBJETIVOS
Olá. Seja muito bem-vindo à Unidade 4. Nosso objetivo é auxiliar 
você no desenvolvimento das seguintes competências profissionais até o 
término desta etapa de estudos:
1. Entender o funcionamento dos registradores em programas em 
Assembly.
2. Aplicar os comandos de acesso a portas lógicas utilizando a 
linguagem de montagem.
3. Manipular dados em memória por meio da linguagem de 
montagem Assembly e identificar o propósito dos recursos.
4. Implementar uma macro em linguagem de montagem Assembly.
Linguagem de Montagem
10
Manipulando registradores em linguagem 
Assembly
OBJETIVO:
Ao término deste capítulo, você será capaz de entender 
o funcionamento dos registradores em programas em 
Assembly. E então? Motivado para desenvolver essa 
competência? Então, vamos lá. Avante!
Quando usamos computadores, não podemos deixar de falar 
no componente que é responsável pelo processamento dos dados. 
Conhecido como CPU ou unidade central de processamento, é composto 
por unidade de controle e também pela unidade de lógica e aritmética.
A função da CPU é fazer a leitura e escrita de dados nas células de 
memória, regular o tráfego de dados existente nas células de memória e 
registradores especiais. Além disso, também tem a função de decodificar 
e executar instruções relacionadas a um programa.
Figura 1 – CPU
Fonte: Pixabay
O processador possui células de memória que são usadas 
frequentemente, sendo assim, são partes da CPU. Essas células são 
chamadas de registradores. Um processador do tipo desktop, por 
exemplo, possui uma média de 14 registradores.
Linguagem de Montagem
11
A seguir temos a listagem dos 14 registradores:
 • AX, que é um registrador acumulador.
 • BX, que é um registrador base.
 • CX, que é um registrador contador.
 • DX, que é um registrador de dados.
 • DS, que é um registrador de segmento de dados.
 • ES, que é um registrador de segmento extra.
 • SS, que é um registrador de segmento de pilha.
 • CS, que é um registrador de segmento de código.
 • BP, que é um registrador apontador da base.
 • SI, que é um registrador de índice-fonte.
 • DI, que é um registrador de índice destino.
 • SP, que é um registrador apontador de pilha.
 • IP, que é um registrador apontador da próxima instrução.
 • F, que é um registrador de flag.
Com o avanço da tecnologia os PCs também têm sofrido evolução. 
Veremos que podemos manipular registradores de 16 ou 32 bits. 
A CPU pode realizar operações relacionadas ao cálculo simbólico e 
ao cálculo numérico. Essas operações podem ser operações elementares, 
como adição, subtração com dois números, multiplicação e divisão de 
dados numéricos inteiros, manuseando bits de registradores e comparando 
as informações e os conteúdos referentes a dois registradores.
Em linguagem de montagem Assembly, utilizamos dois tipos de 
registradores: 
 • Registradores gerais. 
 • Registradores de ponteiros e índices.
Linguagem de Montagem
12
IMPORTANTE:
Os registradores têm o objetivo de armazenar valores. Assim 
como em programação de alto nível, usamos variáveis (x e 
y, por exemplo), em linguagem de montagem, utilizamos 
registradores. 
Os processadores possuem em seus chips uma área física reservada 
para armazenamento de dados, a qual chamamos de registradores. Esse 
nome é devido ao fato deles registrarem ou salvarem informação por 
tempo indeterminado.
Os registradores podem manipular dados de diversas formas 
e tamanhos, pois podem possuir o mesmo tamanho da palavra de 
um processador, ou seja, se temosum processador de 32 bits, temos 
registradores que possuem o mesmo tamanho.
Na tabela que se segue, podemos ver os registradores da Intel 
x86, que, mesmo sendo classificados como registradores gerais, há uma 
convenção em relação a eles que deve ser seguida.
Quadro 1 – Os oito registradores de uso geral da Intel x86
Registrador Significado Uso sugerido
EAX Accumulator Usado em operações aritméticas
EBX Base Ponteiro para dados
ECX Counter Contador em repetições
EDX Data Usado em operações de E/S
ESI Source Index Ponteiro para uma string de 
origem
EDI Destination Index Ponteiro para uma string de 
destino
ESP Stack Pointer Ponteiro para o topo da pilha
EBP Base Pointer Ponteiro para a base do stack 
frame
Fonte: Mente binária (s.d., online).
Linguagem de Montagem
13
Registradores gerais
IMPORTANTE:
Sobre os registradores classificados como gerais, que são 
os registradores do primeiro grupo, temos os registradores 
AX, BX, CX e DX. 
O primeiro do grupo de registradores gerais é o registrador AX, que 
podemos classificar como registrador acumulador. Usamos o AX para 
coletar os resultados referentes às comutações. O registrador AX recebe 
muitas instruções e, mesmo que cada registrador consiga executar muitas 
tarefas, instruções como a de multiplicação, por exemplo, possuem 
destino implícito para AX.
O segundo do grupo de registradores gerais é o registrador BX, que 
podemos classificar como registrador de base. Em muitas aplicações, 
podemos utilizar o registrador BX da mesma forma que o registrador AX. 
Porém, o registrador BX tem um poder que o registrador AX não possui. 
Podemos colocar um endereço de memória no registrador BX e 
executar um comando de instrução operando o que vem do endereço de 
memória que está em BX. Ou seja, o registrador BX possui um ponteiro 
para a memória, e o registrador AX não tem esse recurso. Para exemplificar, 
vamos comparar duas instruções. 
Quadro 2 – Instrução MOV
INSTRUÇÃO OBJETIVO
MOV AX,BX Copiar para AX o conteúdo de BX. 
BX contém o operando-fonte.
MOV AX,(BX) Copiar para AX o conteúdo da palavra 
de memória cujo endereço está 
contido em BX. 
BX aponta para o operando-fonte.
Fonte: Elaborado pela autora (2022).
Linguagem de Montagem
14
REFLITA:
No quadro precedente, podemos observar que o comando 
MOV possui uma fonte e um destino, e o destino está sendo 
indicado antes da fonte. Ou seja, no momento de escrever o 
comando MOV, colocamos em seguida o destino e depois 
a fonte. Por exemplo, em “MOV AX, BX”, podemos ler “mova 
para AX o que está em BX”.
O registrador CX é o que podemos classificar como registrador 
contador. O registrador CX realiza diversas tarefas, mas sua função principal 
é contar os laços de repetição. O registrador CX é automaticamente 
decrementado na instrução LOOP. E, na linguagem de montagem, os 
laços costumam ser finalizados quando CX tem valor zero.
O quarto registrador geral é o registrador DX, que podemos 
classificar como registrador de dados. O registrador DX pode ser usado 
com o registrador AX para instruções referentes ao comprimento de 
palavra dupla, ou seja, 32 bits. O registrador DX possui 16 bits de ordem 
alta e o registrador AX possui 16 bits de ordem baixa.
IMPORTANTE:
Os registradores gerais podem ser referenciados e usados 
como um registrador de 16 bits ou como 2 registradores de 
8 bits.
O processador 8088, por exemplo, possui oito registradores de 8 
bits, que são usados em instruções do tipo byte e do tipo caracteres.
IMPORTANTE:
Somente os registradores gerais podem ser divididos em 
metades de 8 bits. 
Em algumas instruções, usamos o registrador por completo, ou 
seja, inteiro, como no caso do AX, mas temos outras instruções que usam 
apenas uma parte (metade) de um registrador, como AL ou AH. 
Linguagem de Montagem
15
Durante a programação em Assembly, quando são realizadas 
as operações de soma ou subtração, usamos registradores de 16 bits, 
porém, normalmente, são usados registradores e 8 bits. Ou seja, se não 
houver contas de soma, ou subtração ou multiplicação ou outra conta 
aritmética, será usado o registrador de 8 bits. Quando colocamos um valor 
em AX, por exemplo, alteramos as partes AH e AL de AX, dependendo do 
tamanho dos dados. 
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. (TANENBAUM; 
AUSTIN, 2013, p. 546)
Para exemplificar como o registrador AX, AH e AL funcionam e 
interagem, vamos considerar a instrução:
MOV AX,258
Que irá carregar AX com o valor 258 (decimal). Em seguida, AH (de 
bytes) contém o valor 1, e AL contém o número 2. 
Figura 2 – Representação binária do decimal 258
256 (decimal) 
AH AL
2 (decimal) 
00000001  00000010
Fonte: Elaborada pela autora (2022).
Na notação apresentada, foram acionados os bits ativando o 
segundo bit em AL (que é referente ao número 2 em decimal) e ativando 
o primeiro bit em AH (que é referente ao número 256 em decimal). Os bits 
Linguagem de Montagem
16
ativados geram o número 258 em notação decimal, conforme a tabela 
binária.
Na figura a seguir, podemos ver os registradores do modelo 8088 e 
observar os grupos de registradores.
Figura 3 – Registradores do 8088
Fonte: Tanenbaum e Austin (2013, p. 545).
Registradores de ponteiro
Em relação ao segundo grupo de registradores, temos os 
registradores de ponteiros e índices. Em relação a esse grupo, o registrador 
mais importante do segundo grupo de registradores é o ponteiro de pilha, 
para o qual utilizamos a nomenclatura SP. 
O conceito de pilha é bastante usado e aplicado em diversas 
linguagens de programação. Alguns jogos, como a “Torre de Hanói”, foram 
desenvolvidos com base nesse conceito. A pilha armazena valores na 
memória para serem acessados em outro momento, como procedimentos 
que foram executados pela máquina ou alguma informação de controle 
interno do sistema.
Linguagem de Montagem
17
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. 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. 
(TANENBAUM; AUSTIN, 2013, p. 547)
REFLITA:
Quando temos um procedimento acionado que chama 
outro, o sistema coloca um quadro de pilha adicional (que 
é alocado) que fica geralmente logo abaixo do quadro 
atual. As pilhas geralmente crescem para baixo, ou seja, 
de endereços altos para endereços baixos. Contudo, o 
endereço numérico de valor mais baixo que é ocupado na 
pilha é denominado o topo da pilha.
Podemos utilizar as pilhas para conter as variáveis locais e também 
para conter os resultados que são temporários. O processador 8088 
possui uma instrução (PUSH) que posiciona uma palavra no formato de 16 
bits no topo da pilha. A instrução POP pode retirar uma palavra de 16 bits 
do topo da pilha. Ou seja, o registrador SP pode apontar para o topo da 
pilha e pode ser modificado pelas instruções PUSH, CALL e POP, sendo 
incrementado por POP, decrementado por PUSH, e decrementado por 
CALL.
O segundo registrador desse grupo é BP, que é o registrador de 
base. Ele possui um endereço na pilha e, se o registro SP aponta para o 
topo, o registrador BP tem o poder de apontar para qualquer local que 
esteja dentro da pilha. Um uso comum para o registrador BP é apontar 
para o início da pilha do procedimento atual de formaque fique fácil achar 
as variáveis do procedimento. Dessa maneira, o registrador BP aponta para 
a parte de baixo da pilha atual (o endereço numérico maior) e o registrador 
SP aponta para o topo da pilha (o endereço numérico menor). Ou seja, a 
pilha atual tem os limites sinalizados por BP e SP.
Linguagem de Montagem
18
IMPORTANTE:
Nesse grupo de registradores de ponteiros, temos também 
o registrador SI, que é identificado como o índice de 
origem, e o registrador DI, que é identificado como o índice 
de destino. 
Os registradores SI e DI são usados em combinação com o 
registrador “BP para endereçar dados na pilha, ou com BX para calcular os 
endereços de localização de dados de memória” (TANENBAUM; AUSTIN, 
2013, p. 547).
Vamos falar agora sobre os quatro registradores no grupo de 
registradores de segmentos. Vale recordar que, quando falamos em 
pilha, tanto os dados quanto os códigos de instrução ficam na memória 
principal, porém, em partes diferentes.
IMPORTANTE:
Os registradores de segmentos comandam as partes 
diferentes da memória, as quais classificamos como 
segmentos. 
Nos registradores de segmentos, temos: 
 • O registrador CS, que é responsável pelos segmentos de código. 
 • O registrador DS, que é responsável pelos segmentos de dados. 
 • O registrador SS, que é responsável pelos segmentos de pilha. 
 • O registrador ES, que é responsável pelos segmentos extras. 
Durante o procedimento de execução de um programa, os 
registradores possuem os valores ajustados durante todo o tempo ou a 
maior parte do tempo. Ou seja, os valores nos registradores DS, CS, ES e 
SS estão sempre sendo alterados.
Linguagem de Montagem
19
IMPORTANTE:
O segmento de dados (DS) e o segmento de pilha (SS), que 
são os registradores de segmentos, usam a mesma parte 
da memória.
Para manipular os dados em programação Assembly em uma pilha, 
o primeiro dado a entrar é o último a sair, por exemplo:
 PUSH AX
 PUSH BX
 PUSH CX
Em Assembly, quando queremos retornar os valores da pilha 
referente a cada registrador, executamos o seguinte programa:
 POP CX
 POP BX
 POP AX
Linguagem de Montagem
20
RESUMINDO:
E então? Gostou do que lhe mostramos? Aprendeu mesmo 
tudinho? Agora, só para termos certeza de que você 
realmente entendeu o tema de estudo deste capítulo, vamos 
resumir tudo o que vimos. Você deve ter aprendido que os 
registradores desempenham uma parte muito importante 
na programação e, principalmente, na programação de 
baixo nível, que é a linguagem de montagem. Temos os 
registradores gerais e os registradores de ponteiros e índice. 
Os registradores gerais são os acumuladores, contadores, de 
dados e de base. O registrador acumulador AX, por exemplo, 
utiliza a parte alta (AH) ou a parte baixa (AL), dependendo 
do tipo de instrução. Os registradores de ponteiro utilizam 
registradores específicos para manipular pilhas, por exemplo. 
Como registradores de ponteiro, temos registradores 
responsáveis pelo segmento de código, outros pelo de 
dados. Temos o SS, que é responsável pelo segmento de 
pilha, e outro pelos segmentos extras. Todos eles sempre 
sofrem diversas alterações durante o uso da máquina.
Linguagem de Montagem
21
Acesso às portas lógicas em Assembly
OBJETIVO:
Ao término deste capítulo, você será capaz de aplicar os 
comandos de acesso a portas lógicas utilizando a linguagem 
de montagem. E então? Motivado para desenvolver essa 
competência? Então, vamos lá. Avante!
Quando falamos em acessar um meio digital ou um computador 
digital, referimo-nos aos meios de acesso ao equipamento, mediante 
programação, para envio ou recebimento de dados. Para acessar 
digitalmente um computador, usamos portas e memória. Uma porta 
lógica pode ser implementada por instruções AND ou IF, por exemplo, 
as quais podem gerar um resultado TRUE ou FALSE. As portas podem 
controlar as informações que são recebidas e enviadas. 
A memória armazena o bit de dados, podendo ser 0 ou 1, que são os 
possíveis estados em que o dispositivo pode estar, sendo eles: habilitado 
ou desabilitado. Com esses dois componentes (porta e memória), quando 
ligados a outros do mesmo tipo, ou seja, a outras portas e memórias, 
podemos ter um computador. 
A base fundamental de um computador são: portas, para a 
comunicação com outras portas e envio de dados; e memória, para 
armazenar as portas que devem ser habilitadas e as portas que devem 
ser desabilitadas.
Os elementos básicos de um computador digital, como 
sabemos, precisam realizar funções de armazenamento, 
movimentação, processamento e controle. Somente dois 
tipos fundamentais de componentes são necessários: 
portas e células de memória. Uma porta é um dispositivo 
que implementa uma função booleana ou lógica simples, 
como IF A AND B ARE TRUE THEN C IS TRUE (porta 
AND). Esses dispositivos são chamados de portas porque 
controlam o fluxo de dados de modo semelhante às 
portas de canal. A célula de memória é um dispositivo que 
pode armazenar um bit de dados; ou seja, o dispositivo 
pode estar em um de dois estados estáveis de cada vez. 
Interconectando grandes quantidades desses dispositivos 
Linguagem de Montagem
22
fundamentais, podemos construir um computador. 
(STALLINGS, 2010, p. 22)
Figura 4 – Porta paralela
Fonte: SCHMIDT (2003, p. 4).
Em relação a impressoras, por exemplo, alguns modelos utilizam 
porta paralela, que, por usa vez, utilizam os registradores AX e DX, em 
que: 
 AH = 01H
 DX = Porta
Em relação aos registradores de retorno, temos:
 AH = Status da impressora
Em que a porta do registrador DX pode ser os valores: 
LPT1=0, 
LPT2=1 e assim por diante.
Em relação à porta paralela, o estado da impressora é codificado bit 
a bit, como nos dados seguintes.
Linguagem de Montagem
23
Quadro 3 – Porta paralela
valor do BIT 1 ou 0 SIGNIFICADO
0 1 Time-put
1 -
2 -
3 1 Informa o erro de entrada e saída
4 1 Impressora selecionada
5 1 Informa o fi m de papel
6 1 Informa o reconhecimento de 
comunicação
7 1 Informa que a impressora está 
pronta para o uso
*No quadro, os bits 1 e 2 bits não são relevantes.
Fonte: Elaborado pela autora (2022).
Podemos usar as portas para fazer comunicação com diversos 
dispositivos externos, usando comando de saída OUT para enviar 
informações para uma porta específica e também o comando de entrada 
IN para receber dados ou informação de uma porta específica.
Para exemplificar, temos um exemplo de comando de saída:
OUT DX,AX
Em que usamos o DX com o valor da porta para ser usada e para se 
comunicar com AX, que possui a informação que será enviada.
Outro exemplo é o comando de entrada:
IN AX,DX
Em que usamos AX como registrador de informação para armazenar 
o DX que possui o endereço da porta com a informação que vai chegar.
Linguagem de Montagem
24
O comando IN pode ler byte ou word de uma porta de E/S, e o 
objetivo é efetuar a transferência de dados (podendo ser byte ou word) de 
uma porta de entrada para o destino, que é o acumulador AL ou AX. 
A porta IN pode ser identificada com um valor de 8 bits, e esse valor 
pode permitir o acesso a portas de endereços que variam de 0 a 255. 
Usando o registrador DX, se este for de 16 bits, podemos especificar 
o endereço de portas, que podem variar de 0 a 65535. 
O formato do comando é: 
 IN acumulador, porta ou 
 IN acumulador, DX 
Para exemplificar, usaremos:
 IN AL, 38H 
 IN AX,DX 
No código apresentado, a primeira linha de comando transfere para 
AL o byte na porta de entrada 38H e, na segunda linha de comandos, 
ocorre a transferência para AX, da word na porta de entrada que foi 
especificada pelo registrador DX.
O comando OUT, por sua vez, pode escrever byte ou word em uma 
porta de E/S (entrada/saída) e tem o objetivo de efetuar a transferência de 
um byte ou uma word, presente no acumulador AL ou AX, respectivamente, 
para uma porta de saída. 
A porta OUT pode ser identificada com um valor de 8 bits que 
permite o acesso a portasem que os endereços podem variar 0 a 255, 
ou com o uso de DX que, como é de 16 bits, a qual permite especificar os 
endereços de portas que pode variar de 0 até 65535. 
O formato da porta é:
OUT porta, acumulador ou 
OUT DX, acumulador 
Para exemplificar, temos o comando:
Linguagem de Montagem
25
OUT 61H,AL ; Transfere para a porta de saída 61H, o byte em AL. 
OUT DX,AL ; Transfere para a porta de saída especificada em DX, o 
byte gravado em AL. 
Em que, com a execução da primeira linha, ocorre a transferência 
para a porta de saída 61H, o byte em AL. Na segunda linha de comando, 
ocorre a transferência para a porta de saída especificada em DX, o byte 
gravado em AL. 
O que é uma porta?
Em linguagem de programação de baixo nível, as portas (ou gates) 
são importantes, por poderem ser montadas com transistores ou outros 
componentes analógicos. Porém, podem ser modeladas como um 
dispositivo digital com bastante precisão. Como vimos, as portas podem 
ter uma ou várias entradas digitais, que são representadas em formatos 
de 0 ou 1.
A porta pode calcular a saída usando instruções bem simples 
que geram um resultado TRUE ou FALSE, como o AND ou OR. Cada 
porta pode ser composta por alguns transistores. Quando combinamos 
algumas portas, podemos formar uma memória no tamanho de 1 bit, para 
armazenar os valores 0 ou 1. 
Essas memórias de 1 bit, por sua vez, podem ser combinadas com 
outras memórias, formando grupos de 16 bits, 32 bits ou 64 bits, formando, 
assim, os registradores (como os registradores que estudamos AX e BX). 
Quando combinamos as portas, podemos formar um computador, ou 
seja, um equipamento com um mecanismo de computação.
os objetos interessantes são chamados de portas (ou gates). 
Embora montadas a partir de componentes analógicos, 
como transistores, podem ser modeladas com precisão 
como dispositivos digitais. Cada porta tem uma ou mais 
entradas digitais (sinais representando 0 ou 1) e calcula 
como saída alguma função simples dessas entradas, 
como AND (E) ou OR (OU). Cada porta é composta de no 
máximo alguns transistores. Um pequeno número de 
portas podem ser combinadas para formar uma memória 
de 1 bit, que consegue armazenar um 0 ou um 1. As 
Linguagem de Montagem
26
memórias de 1 bit podem ser combinadas em grupos de 
(por exemplo) 16, 32 ou 64 para formar registradores. Cada 
registrador pode manter um único número binário até 
algum máximo. As portas também podem ser combinadas 
para formar o próprio mecanismo de computação principal. 
(TANENBAUM; AUSTIN, 2013, p. 4)
Para Stallings (2010, p. 609), “porta lógica é um circuito eletrônico 
que produz um sinal de saída que é uma operação booleana simples de 
seus sinais de entrada”.
VOCÊ SABIA?
As portas são a base dos computadores digitais, pois 
formam a base do hardware, e todos os computadores são 
construídos a partir dessa base.
Quando usamos os processadores AVR, dizemos que a porta 
é o caminho entre a CPU (unidade central de processamento) e os 
componentes externos de hardware e software. 
A CPU pode se comunicar com os componentes, obtendo ou lendo 
deles ou escrevendo neles. Nesse processo, a porta mais utilizada é o 
registrador de flag, pois os resultados das operações executadas são 
escritos e também onde as condições ou decisões são feitas.
VOCÊ SABIA?
Podemos contabilizar 64 portas diferentes em 
processadores AVR, por exemplo. 
Dependendo “do espaço de armazenamento e outros hardwares 
internos, as portas podem estar disponíveis e acessíveis ou não. A lista de 
portas que podem ser usadas está listada nos data sheets do processador” 
(SCHMIDT, 2003, p. 16).
Nos processadores AVR, por exemplo, as portas possuem endereço 
fixo, onde a CPU se comunica, e o endereço não varia de uma AVR para 
outra, ou seja, é independente do tipo de AVR. Isto é, se uma porta C 
possui um endereço 0x17 (o 0x indica que é uma notação hexadecimal, 
Linguagem de Montagem
27
então 0x17 está no formato hexadecimal). Esse endereço sempre será 
usado pela porta C, e não por outra porta como A ou B.
Os endereços podem ter uma nomenclatura ou “apelidos” para 
facilitar a chamada pelo sistema. Esses nomes são declarados no arquivo 
de cabeçalho (os includes), nos quais cada tipo de processador possui a 
lista de nomes que é definida pelo fabricante.
Nos arquivos do tipo include, temos uma linha que define o 
endereço da porta B, como:
.EQU PORTB, 0x18
Precisamos lembrar somente do nome da porta B, não 
necessariamente de sua localização de E/S do chip. O arquivo de include 
8515def.inc pode ser usado na programação Assembly: 
.INCLUDE “C:\Somewhere\8515def.inc”
Dessa forma, todos os registradores de 8515 podem ser definidos 
e acessíveis.
Acessando uma porta em Assembly
Em processadores AVR, assim como em outros processadores, as 
portas geralmente são organizadas em 8 bits, mas podemos manipular 8 
bits individuais que não interferem uns com os outros. 
Caso esses bits possuam significado, podemos associar no arquivo 
include, permitindo a manipulação desse bit. Devido à convenção dos 
nomes, podemos também lembrar a posição desses bits. 
Os nomes são inseridos nos data sheets (cabeçalhos) e estão 
incluídos nos arquivos include. Eles são fornecidos nas tabelas das portas.
Linguagem de Montagem
28
Figura 5 – Tabela de portas do AVR
Componente
Nome da 
porta
Registrador da Porta
Acumulador SREG Registrador de Status
Pilha (stack) SPL/SPH
Stackpointer (apontador de 
pilha)
SRAM Externa/
Interrupção Externa
MCUCR
Registrador de Controle 
Geral MCU
Interrupção Externa
GIMSK
Registrador de Interrupção 
Mascarado
GIFR
Registrador de Flag de 
Interrupção
Interrupção de 
Timer
TIMSK
Registrador de Interrupção 
de Timer Mascarada
TIFR
Registrador de Interrupção 
de Flag de Timer
Timer 0
TCCR0
Registrador controle de de 
Timer/Contador 0
TCNT0 Timer/Contador 0
Timer 1
TCCR1A
Registrador controle de 
Timer/Contador 1 A
TCCR1B
Registrador controle de 
Timer/Contador 1 B
TCNT1 Timer/Contador 1
OCR1A
Registrador Comparador de 
Saída 1 A
OCR1B
Registrador Comparador de 
Saída 1 B
ICR1L/H
Registrador de Captura de 
Entrada
Linguagem de Montagem
29
Timer Watchdog WDTCR
Registrador de Controle do 
Timer Watchdog
EEPROM
EEAR
Registrador de endereço da 
EEPROM
EEDR
Registrador de dados da 
EEPROM
EECR
Registrador de controle da 
EEPROM
SPI
SPCR
Registrador de controle de 
periféricos Seriais
SPSR
Registrador de status de 
periféricos Seriais
SPDR
Registrador de dados de 
periféricos Seriais
UART
UDR
Registrador de dados da 
UART
USR
Registrador de status da 
UART
UCR
Registrador de controle da 
UART
UBRR
Registrador de velocidade 
(baud rate) da UART
Comparador 
analógico
ACSR
Registrador de status e 
controle do comparador 
analógico
Portas de E/S
PORTx
Registrador de porta de 
saída
DDRx
Registrador de direção da 
porta
PINx
Registrador de porta de 
entrada
Fonte: Schmidt (2003, p. 17).
Para exemplificar, o registrador de controle geral MCU, também 
chamado MCUCR, é um número de bits de controle de forma individual 
que controla características gerais do chip. 
Linguagem de Montagem
30
.DEF MeuRegistrador = R16
LDI MeuRegistrador, 0b00100000
OUT MCUCR, MeuRegistrador
SLEEP
O comando anterior coloca o processador para “dormir”.
No código apresentado, a instrução OUT envia o conteúdo do 
registrador, um bit Sleep-Enable chamado SE, para a porta MCUCR e seta 
o processador AVR, para entrar em repouso, caso tenha uma instrução 
SLEEP em execução. Já que todos os bits do MCUCR foram setados na 
instrução acima, e o bit SM (Sleep Mode) teve o valor zero, ocorreu um 
modo que chamamos meio-repouso, ou seja, não houve execução de 
outro comando, porém o chip ainda reage a instruções timers e outras 
interrupções de hardware. No entanto, esses eventos externos podem 
interromper “o sono” do processador (CPU) caso eles achem necessário 
enviar uma notificação.Figura 6 – Porta paralela
Fonte: Schmidt (2003, p. 4).
Na figura anterior, temos uma porta paralela que pode ser acessada 
por comandos de linguagem Assembly.
Para ler o conteúdo de uma porta, podemos utilizar o comando IN. 
.DEF MeuRegistrador = R16
IN MeuRegistrador, MCUCR 
Linguagem de Montagem
31
A sequência precedente consegue ler os dados da porta MCUCR 
feita para o registrador. Como geralmente muitas portas são usadas em 
parte ou às vezes não utilizadas, os dados lidos são zeros.
Na figura adiante, temos os principais comandos para acesso às 
portas em linguagem Assembly utilizadas nos processadores AVR.
VOCÊ SABIA?
Portas não são fabricadas nem vendidas individualmente, 
mas em unidades denominadas circuitos integrados, muitas 
vezes denominados ICs ou chips. Um IC é um pedaço 
quadrado de silício de tamanho variado, dependendo 
de quantas portas são necessárias para executar os 
componentes do chip. Substratos pequenos medirão cerca 
de 2 × 2 mm, enquanto os maiores podem ter até 18 × 18 
mm. ICs costumam ser montados em pacotes retangulares 
de plástico ou cerâmica, que podem ser muito maiores 
que os substratos que eles abrigam, se forem necessários 
muitos pinos para conectar o chip ao mundo exterior. Cada 
pino se conecta com a entrada ou saída de alguma porta 
no chip ou à fonte de energia, ou ao terra. (TANENBAUM; 
AUSTIN, 2013, p. 124)
A porta mais usada é o registrador de status com 8 bits. O acesso à 
porta “é feito somente por alteração dos bits pela CPU ou acumulador. A 
maioria destes bits é alterada por operações de teste de bit, comparação 
ou cálculos” (SCHMIDT, 2003, p. 17).
A seguinte lista tem todos os comandos em Assembly que podem 
alterar os bits de status, dependendo do resultado da execução.
Linguagem de Montagem
32
Figura 7 – Comandos Assembly que podem alterar os bits de status
Bit Cálculo Lógico Comparação Bits Rolagem Outro
Z
ADD, ADC, 
ADIW, DEC,
INC, SUB, 
SUBI, SBC,
SBCI, SBIW
AND, 
ANDI, 
OR,
ORI, 
EOR, 
COM,
NEG, 
SBR, 
CBR
CP, CPC, CPI
BCLR Z,
BSET Z,
CLZ, SEZ,
TST
ASR, LSL,
LSR, ROL,
ROR
CLR
C
ADD, ADC, 
ADIW, SUB,
SUBI, SBC, 
SBCI, SBIW
COM, 
NEG
CP, CPC, CPI
BCLR C,
BSET C,
CLC, SEC
ASR, LSL,
LSR, ROL,
ROR
-
N
ADD, ADC, 
ADIW, DEC,
INC, SUB, 
SUBI, SBC,
SBCI, SBIW
AND, 
ANDI, 
OR,
ORI, 
EOR, 
COM,
NEG, 
SBR, 
CBR
CP, CPC, CPI
BCLR N,
BSET N,
CLN, 
SEN,
TST
ASR, LSL,
LSR, ROL,
ROR
CLR
V
ADD, ADC, 
ADIW, DEC,
INC, SUB, 
SUBI, SBC,
SBCI, SBIW
AND, 
ANDI, 
OR,
ORI, 
EOR, 
COM,
NEG, 
SBR, 
CBR
CP, CPC, CPI
BCLR V,
BSET V,
CLV, SEV,
TST
ASR, LSL,
LSR, ROL,
ROR
CLR
S SBIW - -
BCLR S,
BSET S,
CLS, SES
- -
H
ADD, ADC, 
SUB, SUBI,
SBC, SBCI
NEG CP, CPC, CPI
BCLR H,
BSET H,
CLH, SEH
- -
T - - -
BCLR T,
BSET T,
BST, CLT,
SET
- -
I - - -
BCLR I,
BSET I,
CLI, SEI
- RETI
Fonte: Schmidt (2003, p. 18).
Linguagem de Montagem
33
Tão importante quanto ler os 8 bits de uma porta, o processador 
deve reagir a certos status de uma porta. Então, podemos ler a porta toda 
e, se for o caso, isolar o bit que interessa.
Alguns comandos executam o procedimento dependendo do 
estado do bit. Podemos também setar ou zerar bits sem ter de ler e 
escrever outros bits na porta. Para esse procedimento, usamos dois 
comandos: SBI e CBI.
A linha de código é: 
.EQU BitAtivo=0 ; O bit que será mudado
SBI PortB, BitAtivo ; O bit será setado para um
CBI PortB, BitAtivo ; O bit será setado para zero
IMPORTANTE:
As portas elencadas têm uma limitação: somente as portas 
que possuem endereço inferior a 0x20 conseguem ser 
manipuladas dessa forma.
Na figura subsequente, temos as portas de entrada e saída dos 
comandos de acesso para serem utilizados em linguagem Assembly, 
para processadores AVR.
Linguagem de Montagem
34
Figura 8 – Portas de entrada e saída do AVR
PORTAS E/S
Port Register Função
Endereço da
Porta
Endereço 
da
RAM
A
PORTA
Registrador de 
Dados
0x1B 0x3B
DDRA
Registrador da 
Direção
dos Dados 
0x1A 0x3A
PINA
Endereço dos Pinos 
de Entrada 
0x19 0x39
B
PORTB
Registrador de 
Dados
0x18 0x38
DDRB
Registrador da 
Direção
dos Dados 
0x17 0x37
PINB
Endereço dos Pinos 
de Entrada 
0x16 0x36
C
PORTC
Registrador de 
Dados
0x15 0x35
DDRC
Registrador da 
Direção dos Dados 
0x14 0x34
PINC
Endereço dos Pinos 
de Entrada 
0x13 0x33
D
PORTD
Registrador de 
Dados
0x12 0x32
DDRD
Registrador da 
Direção dos Dados 
0x11 0x31
PIND
Endereço dos Pinos 
de Entrada 
0x10 0x30
Fonte: Schmidt (2003, p. 59).
Linguagem de Montagem
35
RESUMINDO:
E então? Gostou do que lhe mostramos? Aprendeu mesmo 
tudinho? Agora, só para termos certeza de que você 
realmente entendeu o tema de estudo deste capítulo, 
vamos resumir tudo o que vimos. Você deve ter aprendido 
que a linguagem de montagem Assembly permite que 
possamos manipular diversas portas com comandos 
específicos. Vimos também que cada porta tem um 
registrador de porta e ocupa um endereço, e que algumas 
portas podem ser manipuladas de modo específico, 
dependendo do endereço de acesso. Vimos ainda que 
os endereços referentes aos recursos classificados como 
porta (independentemente de serem portas simples ou 
não) possuem endereços fixos, ou seja, eles não alteram 
como as outras informações que vimos até aqui. Cada porta 
possui um endereço que pode ser acessado por linhas 
de código em Assembly. Os endereços de memória são 
indicados em notação hexadecimal. 2
Linguagem de Montagem
36
Utilização da memória em Assembly
OBJETIVO:
Ao término deste capítulo, você será capaz de manipular 
dados em memória por meio da linguagem de montagem 
Assembly e identificar o propósito dos recursos. E então? 
Motivado para desenvolver essa competência? Então, 
vamos lá. Avante!
Sabemos que os computadores fazem uso da memória para 
armazenar os dados e buscá-los em outro momento, ou como uma fonte 
de consulta, ou para armazenamento. 
Em linguagem de montagem, podemos manipular os dados que 
estão na memória do computador e movimentá-los de acordo com os 
objetivos do projeto.
VOCÊ SABIA?
“Um componente essencial de todo computador é sua 
memória. Sem ela não poderiam existir os computadores 
que conhecemos. A memória é usada para armazenar 
instruções a serem executadas e dados” (TANENBAUM; 
AUSTIN, 2013, p. 133).
Figura 9 – Memórias em forma de papel no mural
Fonte: Pixabay 
Linguagem de Montagem
37
O processador 8088, por exemplo, possui uma organização de 
memória diferenciada, em que, para 1 MB de memória, utilizamos 20 bits 
para representar o endereço relacionado à memória. Isso torna inviável o 
armazenamento do ponteiro para memória em registradores no formato 
de 16 bits. 
Para resolver esse problema, a memória é organizada em segmentos 
de 64 KB, nos quais um endereço que fique dentro de um segmento pode 
ser representado em formato de 16 bits.
Organização da memória e segmentos
A memória do processador 8088 (que é um vetor de bytes de 8 
bits e endereçáveis) é usada para o armazenamento de instruções, 
armazenamento de dados e armazenamento de pilhas. Para organizar e 
separar a memória usada para esse objetivo, o processador 8088 utiliza 
segmentos. 
O segmento tem 65.536 bytes consecutivos no processador 8088. 
São quatro segmentos: segmento de código, segmento de dados, 
segmento de pilha e segmento extra.
 • Segmento de código: é a parte que contém as instruções 
referentes ao programa. Os dados são interpretados como 
endereço de memória. Aqui no segmento de código, o valor 0 (zero) 
não é o endereço absoluto de memória, mas, sim, uma referência 
ao endereço mais baixo que está no segmento de código. 
 • Segmento de dados: referente aos dados inicializados e não 
inicializados. BX contém um ponteiro que aponta para esse 
segmento de dados. 
 • Segmento de pilha: variáveis locais e resultados passados para 
a pilha. Os endereços que estão nos registradores SP e BP estão 
nesse segmento. 
 • Segmento extra: segmentos avulsos podem ser colocados em 
qualquer lugarda memória conforme desejar ou for necessário.
Cada segmento tem um registrador de 16 bits: CS, DS, SS e ES. 
Linguagem de Montagem
38
Esses registradores sempre usam múltiplos de 16, em endereços 
de 20 bits. 
Figura 10 – Registradores de segmentos
Registradores de segmentos
CS Segmento de código
DS Segmento de dados
SS Segmento de pilha
ES Segmento extra
15
Fonte: Tanenbaum e Austin (2013, p. 545).
Quando temos um registrador de segmentos, ele sempre vai 
apontar para a base do segmento.
IMPORTANTE:
Qualquer referência usada na memória utiliza os 
registradores de segmentos para gerar o endereço de 
memória. 
Se por acaso aparecer instrução sem referência a nenhum dos 
registradores, esse endereço vai ficar na parte de segmento de dados, 
que é o registrador DS, muito usado para a base do segmento.
VOCÊ SABIA?
Podemos achar o endereço físico na memória do próximo 
código de instrução deslocando o que estiver no registrador 
CS por quatro casas binárias e depois somando o valor do 
contador de programa. 
Quando temos um segmento de pilha, dizemos que ele é composto 
por palavras de 2 bytes. Por isso, o ponteiro de pilha do registrador SP 
sempre possui um número par. Então, a pilha pode ser preenchida dos 
endereços altos em direção aos endereços baixos.
Linguagem de Montagem
39
Usamos o comando PUSH para diminuir o ponteiro de pilha em 2 e 
depois armazenar o operando no endereço de memória que será indicado 
e calculado a partir dos registradores SS e SP. 
Usamos também a instrução POP para recuperar o valor e 
incrementar o registrador SP em 2.
VOCÊ SABIA?
Temos endereços livres, e eles são os endereços do 
segmento de pilha de valor mais baixo do que os indicados 
pelo registrador SP. Sendo assim, podemos limpar a pilha, 
conseguindo, desso modo, aumentar o registrador SP. 
Na verdade, os registradores DS e SS serão iguais. Caso os 
registradores DS e SS sejam diferentes, precisamos de um décimo sétimo 
bit para cada ponteiro, com a finalidade de diferenciar os ponteiros para o 
segmento de dados e os ponteiros para o segmento de pilha. 
Quando terminamos a compilação do programa, o tamanho 
do código de programa passa a ser conhecido. Nesse momento, é 
interessante começar os segmentos de dados e os segmentos de pilha 
no primeiro múltiplo de 16 depois da última instrução. 
Podemos concluir que os segmentos de código e dados nunca 
usarão os mesmos endereços físicos (TANENBAUM; AUSTIN, 2013, p. 549).
Endereçamento
Instruções precisam de dados, podendo ser da memória ou dos 
registradores. Muitos comandos têm dois operandos, chamados de 
destino e de origem. Por exemplo, a instrução de cópia, ou a instrução 
de adição:
MOV AX,BX
ou
ADD CX,20
Linguagem de Montagem
40
Nos comandos apresentados, o primeiro operando é destino e o 
segundo é origem. O destino deve ser um lugar em que a informação 
pode ser armazenada. Ou seja, sempre teremos origens, mas nem sempre 
destinos.
Temos casos em que os operandos não são mencionados, como na 
instrução MULB, na qual o registrador AX tem poder suficiente para agir 
como um destino.
Temos várias instruções de um só operando, por exemplo: 
incrementos, deslocamentos, negações, entre outros. Para esses, 
não temos requisito de registrador, e o resultado da diferença entre as 
operações de palavras e bytes fica deduzido pelos opcodes (que são tipos 
de instrução).
O processador 8088, por exemplo, pode suportar quatro tipos de 
dados:
 • Byte: o tipo byte tem o tamanho de 1 byte. 
 • Palavra: o tipo palavra possui o tamanho de 2 bytes. 
 • Longo: o tipo longo possui o tamanho de 4 bytes. 
 • Decimal codificado em binário: é o tipo de dado em que os dois 
dígitos no formato decimal podem ser agrupados (empacotados) 
em uma palavra. 
O tipo de dado decimal codificado em binários não é suportado 
pelo interpretador.
Sempre temos um endereço de memória que referencia um byte. 
Quando temos uma palavra ou um longo, os locais de memória logo 
acima do byte que é indicado também serão referenciados. 
Por exemplo, se a palavra 20 está na memória nos locais 20 e 21; 
então o longo no endereço 24 ocupará os endereços 24, 25, 26 e 27. 
Em linguagem de montagem Assembly, são os rótulos que 
representam os locais de memória, e não valores numéricos, e a conversão 
pode ser realizada durante o processo de montagem, ou seja, no tempo 
de montagem.
Linguagem de Montagem
41
As instruções CALL e JMP também podem ser armazenadas na 
memória por um rótulo. Os parênteses nos rótulos são essenciais, pois
ADD CX,20
é uma instrução, mas também significa somar a constante 20 a CX, 
e não somente somar o conteúdo da palavra de memória 20.
IMPORTANTE:
Se temos um endereço indireto de registrador, 
armazenamos o endereço do operando nos registradores 
BX, SI ou DI. 
Podemos também colocar a base no registrador BX e separar 
o registrador SI ou o registrador DI para efetuar a contagem. A esse 
processo chamamos de endereçamento de registrador com índice. 
Vamos exemplificar:
PUSH (BX)(DI)
A instrução precedente pesquisa o dado do local do segmento de 
dados em que o endereço é fornecido pela soma do registrador BX com o 
registrador DI. Em seguida, o resultado é transferido para a pilha. 
Podemos pegar os dois últimos endereços e combiná-los para 
conseguir o endereçamento de registrador que tem o índice e o 
deslocamento, como:
NOT 20(BX)(DI)
O comando apresentado complementa a palavra de memória das 
seguintes formas: BX + DI + 20 e BX + DI + 21.
Temos também o modo de endereçamento pelo qual o operando 
é um valor constante de byte ou de palavra, usada na instrução, o qual 
chamamos de endereçamento imediato. Por exemplo:
CMP AX,50
Esse comando compara AX com a constante 50 e depois ajusta os 
bits no registrador de flags de acordo com os resultados.
Linguagem de Montagem
42
Finalmente, temos algumas das instruções de endereçamento 
implícito, em que o operando está implícito na instrução. Por exemplo:
PUSH AX
O comando anterior passa o conteúdo do registrador AX para a 
pilha, decrementando o registrador SP. Em seguida, copia o registrador 
AX para o local apontado pelo registrador SP. 
Por isso, o registrador SP não é indicado na instrução, pois a 
instrução PUSH implica que SP deve ser usado. 
Figura 11 – Endereçamento de operandos
Modo Operando Exemplos
Endereçamento de 
registrador
Registrador de bytes
Registrador de 
palavras
Registrador de bytes
Registrador de 
palavras
AH, AL, BH, BL, CH, 
CL, DH, DL
AX, BX, CX, DX, SP, 
BP, SI, DI
Endereçamento de 
segmentos de dados
Endereço direto
Indireto de registrador
Deslocamento de 
registrador
Registrador com índice
Registrador com índice 
e deslocamento
Endereço vem após 
opcode
Endereço em 
registrador
Endereço em 
registrador + desloc.
Endereço é BX + SI/
DI
BX + SI DI + 
deslocamento
(#)
(SI), (DI), (BX)
#(SI), #(DI), #(BX)
(BX)(SI), (BX)(DI)
#(BX)(SI), #(BX)(DI)
Endereço de 
segmento de pilha
Indireto de ponteiro de 
base
Deslocamento de 
ponteiro de base
Ponteiro de base com 
índice
Desloc. de índice de 
ponteiro de base
Endereço em 
registrador
Endereço é BP + 
deslocamento
Endereço é BP + SI/
DI
BP + SI/DI + 
deslocamento
(BP)
#(BP)
(BP)(SI), (BP)(DI)
#(BP)(SI), #(BP)(DI)
Dados imediatos
Byte/palavra imediato 
Dados são parte da 
instrução
#
Endereço implícito
Instrução push/pop
Flags de load/store
Traduzir XLAT
Instruções de cadeias 
repetidas
Instruções de E/S
Converte byte, palavra
Endereço indireto 
(SP)
Registrador de fl ag 
de status
AL, BX
(SI), (DI), (CX)
AX, AL
AL, AX, DX
PUSH, POP, 
PUSHF, POPF
LAHF, STC, CLC, 
CMC
XLAT
MOVS, CMPS, 
SCAS
IN #, OUT #
CBW, CWD
Linguagem de Montagem
43
Modo Operando Exemplos
Endereçamento de 
registrador
Registrador de bytes
Registrador de 
palavras
Registrador de bytes
Registrador de 
palavras
AH, AL, BH, BL, CH, 
CL, DH, DL
AX, BX, CX, DX, SP, 
BP, SI, DI
Endereçamento de 
segmentos de dadosEndereço direto
Indireto de registrador
Deslocamento de 
registrador
Registrador com índice
Registrador com índice 
e deslocamento
Endereço vem após 
opcode
Endereço em 
registrador
Endereço em 
registrador + desloc.
Endereço é BX + SI/
DI
BX + SI DI + 
deslocamento
(#)
(SI), (DI), (BX)
#(SI), #(DI), #(BX)
(BX)(SI), (BX)(DI)
#(BX)(SI), #(BX)(DI)
Endereço de 
segmento de pilha
Indireto de ponteiro de 
base
Deslocamento de 
ponteiro de base
Ponteiro de base com 
índice
Desloc. de índice de 
ponteiro de base
Endereço em 
registrador
Endereço é BP + 
deslocamento
Endereço é BP + SI/
DI
BP + SI/DI + 
deslocamento
(BP)
#(BP)
(BP)(SI), (BP)(DI)
#(BP)(SI), #(BP)(DI)
Dados imediatos
Byte/palavra imediato 
Dados são parte da 
instrução
#
Endereço implícito
Instrução push/pop
Flags de load/store
Traduzir XLAT
Instruções de cadeias 
repetidas
Instruções de E/S
Converte byte, palavra
Endereço indireto 
(SP)
Registrador de fl ag 
de status
AL, BX
(SI), (DI), (CX)
AX, AL
AL, AX, DX
PUSH, POP, 
PUSHF, POPF
LAHF, STC, CLC, 
CMC
XLAT
MOVS, CMPS, 
SCAS
IN #, OUT #
CBW, CWD
Modos de endereçamento de operandos. O símbolo # indica um valor numérico ou rótulo.
Fonte: Tanenbaum e Austin (2013, p. 550).
O processador 8088 pode usar instruções específicas para mover 
(MOVS), comparar (CMPS) ou também para examinar (SCAS) cadeias de 
caracteres.
Para exemplificar o uso de pilha, vamos analisar um jogo chamado 
Torre de Hanói. 
“Torres de Hanói” é um antigo problema que tem solução 
simples envolvendo recursão. Em certo mosteiro em 
Hanói, havia três estacas de ouro. Ao redor da primeira 
havia uma série de 64 discos concêntricos de ouro, cada 
um com um orifício no meio para a estaca. Cada disco tem 
um diâmetro um pouco menor do que o que está abaixo 
dele. A segunda e terceira estacas estavam inicialmente 
vazias. Os monges desse mosteiro estão muito ocupados 
transferindo todos os discos para a estaca 3, um por vez, 
mas nunca um disco maior pode ficar por cima de um 
menor. Diz a lenda que, quando eles terminarem, o mundo 
acaba. Se você quiser fazer uma experiência prática, pode 
usar discos de plástico e em número menor, mas, quando 
resolver o problema, nada acontecerá. Para conseguir o 
efeito do fim do mundo, você precisa ter 64 discos, e de 
ouro. (TANENBAUM; AUSTIN, 2013, p. 321)
Linguagem de Montagem
44
Figura 12 – Torres de Hanói com cinco discos
Fonte: Tanenbaum e Austin (2013, p. 321).
A seguir, temos um código de resolução do problema de Torres 
de Hanói para um processador Core i7, em linguagem de montagem 
Assembly.
.686 ; compile para processador da classe Core i7
.MODEL FLAT
PUBLIC _torres ; exporte ‘torres’
EXTERN _printf:NEAR ; importe printf
.CODE
_torres: PUSH EBP ; salve EBP (ponteiro de quadro) e decremente 
ESP
MOV EBP, ESP ; ajuste novo ponteiro de quadro acima de ESP
CMP [EBP+8], 1 ; se (n == 1)
JNE L1 ; desvie se n não for 1
MOV EAX, [EBP+16] ; printf(“ ...”, i, j);
PUSH EAX ; note que os parâmetros i, j e a cadeia
MOV EAX, [EBP+12] ; de formato são passados para a pilha em ordem
PUSH EAX ; inversa. Essa é a convenção de chamada em C
PUSH OFFSET FLAT:format ; offset flat significa endereço de formato
Linguagem de Montagem
45
CALL _printf ; chame printf
ADD ESP, 12 ; retire parâmetros da pilha
JMP Fim ; terminamos
L1: MOV EAX, 6 ; inicie k = 6 − i − j
SUB EAX, [EBP+12] ; EAX = 6 − i
SUB EAX, [EBP+16] ; EAX = 6 − i − j
MOV [EBP+20], EAX ; k = EAX
PUSH EAX ; inicie torres(n − 1, i, k)
MOV EAX, [EBP+12] ; EAX = i
PUSH EAX ; passe i
MOV EAX, [EBP+8] ; EAX = n
DEC EAX ; EAX = n − 1
PUSH EAX ; passe n − 1
CALL _torres ; chame torres(n − 1, i, 6 − i − j)
ADD ESP, 12; retire parâmetros da pilha
MOV EAX, [EBP+16] ; inicie torres(1, i, j)
PUSH EAX ; passe j
MOV EAX, [EBP+12] ; EAX = i
PUSH EAX ; passe i
PUSH 1 ; passe 1
CALL _torres ; chame torres(1, i, j)
ADD ESP, 12 ; retire parâmetros da pilha
MOV EAX, [EBP+12] ; inicie torres(n − 1, 6 − i − j, i)
PUSH EAX ; passe i
MOV EAX, [EBP+20] ; EAX = k
Linguagem de Montagem
46
PUSH EAX ; passe k
MOV EAX, [EBP+8] ; EAX = n
DEC EAX ; EAX = n − 1
PUSH EAX ; passe n − 1
CALL _torres ; chame torres(n − 1, 6 − i − j, i)
ADD ESP, 12 ; ajuste ponteiro de pilha
Fim: LEAVE ; prepare para sair
 RET 0 ; retorne ao chamador
.DATA 
format DB “Mova disco de %d para %d\n” ; cadeia de formato
END 
No código apresentado, foram usados comandos recursivos (que 
chamam ele mesmo) e analisando o código recursivo em linguagem de 
máquina, podemos observar que eles são diretos.
Linguagem de Montagem
47
RESUMINDO:
E então? Gostou do que lhe mostramos? Aprendeu mesmo 
tudinho? Agora, só para termos certeza de que você 
realmente entendeu o tema de estudo deste capítulo, 
vamos resumir tudo o que vimos. Você deve ter aprendido 
que a memória pode ser arrumada em segmentos, como 
segmento de código, de dados, de pilha e extra. Cada 
segmento tem um registrador, mesmo sendo de memória, 
e são de 16 bits. Podemos usar comandos específicos 
para manipular dados da memória, pois temos segmentos 
distintos, como segmento de dados, segmento de pilha, 
segmento de código e segmento extra. Cada segmento tem 
uma função específica e utiliza o Assembly utiliza instruções 
para acessar esses segmentos que possuem registradores 
específicos, como o CS, DS, SS e ES. Os segmentos de 
ponteiro também utilizam registradores específicos, que 
são o SP, BP, SI e DI. Os comandos POP e PUSH podem 
manipular os valores da pilha, aumentando e diminuindo 
os valores do ponteiro, em que o PUSH incrementa dados 
na pilha e o POP retira. Vale lembrar que a pilha cresce para 
baixo; então, os valores de memória diminuem à medida 
que a pilha cresce.
Linguagem de Montagem
48
Aplicação de macro em linguagem 
Assembly
OBJETIVO:
Ao término deste capítulo, você será capaz de implementar 
uma macro em linguagem de montagem Assembly. E 
então? Motivado para desenvolver essa competência? 
Então, vamos lá. Avante!
A macro é um recurso muito usado em ambientes de programação 
e produtividade. O recurso de macro permite executar procedimentos 
repetitivos com menos esforço. Em planilha eletrônica, por exemplo, 
podemos usar o recurso de macro para otimizar procedimentos, 
aumentando, assim, a produtividade.
Em linguagem de programação, tanto na linguagem de alto nível como 
na linguagem de montagem, que é considerada de baixo nível, podemos 
usar o recurso de macro para otimizar rotinas e procedimentos também, 
executando os comandos da macro por meio da chamada à macro.
Programadores de linguagem de montagem com frequência 
precisam repetir sequências de instruções várias vezes 
dentro de um programa. O modo mais óbvio de fazer isso 
é escrever as instruções requeridas onde quer que sejam 
necessárias. Se uma sequência for longa, entretanto, ou tiver 
de ser usada muitas vezes, escrevê-la repetidas vezes torna-
se tedioso. (TANENBAUM; AUSTIN, 2013, p. 413)
Figura 13 – Destacando procedimentos
Fonte: Pixabay 
Linguagem de Montagem
49
Definindo uma macro
Em alguns momentos, durante o processo de elaboração de um 
programa de montagem, podemos elaborar algum procedimento com o 
objetivo de deixar o código enxuto e otimizado. A macro pode ser usada 
para otimizar um programa, em que instruções podem ser executadas 
fazendo uso de um nome.
Uma definição de macro é um modo de dar um nome 
a um pedaço de texto. Após uma macro ser definida, 
o programador pode escrever o nome dela em vez do 
pedaço de programa. Uma macro é, na verdade, uma 
abreviatura para um pedaço de texto. (TANENBAUM; 
AUSTIN, 2013, p. 413)
Podemos definir uma macro como um grupo de instruções 
repetitivas que estão em um programa e que são codificadas apenas uma 
vez, permitindo poupar espaço de memória, além de ser possível utilizar 
várias.
IMPORTANTE:
Procedimento e macro são diferentes. Procedimento é uma 
extensão de um programa para realizar tarefas. A macro é 
um móduloque possui funções e pode ser utilizado por 
diversos programas.
Procedimento e macro são diferentes. Para efetuar uma chamada a 
um procedimento, podemos usar a instrução CALL; e para fazer chamada 
a uma macro em Assembly, podemos usar as instruções normais, comuns 
na programação de linguagem de montagem. 
Quando uma macro é definida e encontrada durante a execução 
do programa, o sistema armazena o nome da macro em uma tabela para 
futuros acessos, a qual irá substituir pelo conteúdo da macro sempre que 
o nome da macro for encontrado durante a execução do programa.
Quando o assembler encontra uma definição de macro, ele 
a salva em uma tabela de definição para uso subsequente. 
Desse ponto em diante, sempre que o nome da macro 
aparecer como um opcode, o assembler o substitui pelo 
Linguagem de Montagem
50
corpo da macro. A utilização de um nome de macro como 
um opcode é conhecida como chamada de macro e sua 
substituição pelo corpo da macro é denominada expansão 
de macro. (TANENBAUM; AUSTIN, 2013, p. 414)
Podemos definir um procedimento como uma coleção de instruções 
na qual é possível direcionar o curso de um programa. Quando a execução 
dessas instruções do procedimento acabarem, o controle volta para linha 
que segue à que solicitou o procedimento.
Os procedimentos podem nos ajudar a criar programas legíveis 
e também fáceis de ajustar. No momento em que chamamos um 
procedimento, é mantido na pilha o endereço da instrução seguinte, que 
é utilizado quando o programa retorna da execução do procedimento. 
Ou seja, após executar um procedimento, o programa retorna ao ponto 
anterior para continuar a execução das instruções.
Temos dois tipos de procedimentos: 
 • Intrassegmentos: que se localizam no mesmo segmento de 
origem da instrução que o chama. 
 • Intersegmentos: que podem estar localizados em diferentes 
segmentos de memória.
No momento em que os procedimentos intersegmentos são 
usados, temos o valor de IP, que é armazenado na pilha, e quando os 
procedimentos intersegmentos são usados, temos o valor de CS:IP, que 
é armazenado. 
Vale lembrar que o registrador CS pode indicar qual é o segmento 
de código.
O comando para chamar um procedimento é como segue (sintaxe):
CALL NomedoProcedimento
Em que as partes que compõem o procedimento são:
 • Declaração do procedimento.
 • Código do procedimento.
 • Diretiva de retorno.
Linguagem de Montagem
51
 • Término do procedimento.
Para exemplificar, se quisermos somar dois bytes que estão 
armazenados nas partes AH e AL, teremos o resultado da soma em BX:
Soma Proc Near ; Declaração do Procedimento
Mov BX, 0 ; Conteúdo do Procedimento...
Mov BL, AH
Mov AH, 00
Add BX, AX
Ret ; Diretiva de retorno
Soma EndP ; Fim do Procedimento
No código apresentado, temos a primeira palavra, Soma, que 
corresponde ao nome do procedimento. O comando “Proc” declara-o e a 
palavra “Near” indica o procedimento como sendo do tipo intrassegmento, 
ou seja, no mesmo segmento. 
Temos também a diretiva “Ret” que tem o IP com o endereço 
armazenado para a pilha, e então retornar ao programa que chamou. 
Finalmente, temos o comando “Soma EndP”, que indica ao programa o 
fim do procedimento.
Para estabelecer o momento de declaração de um procedimento 
intersegmento, basta substituir a palavra Near para FAR.
Para efetuar a chamada a esse procedimento, usamos a linha de 
comando feito de modo idêntico:
Call Soma
IMPORTANTE:
O uso de macros permite ao programador otimizar o 
programa, deixando o código mais enxuto e flexível em 
relação ao procedimento.
Linguagem de Montagem
52
Sintaxe de uma macro
As macros podem ser compostas pelas seguintes partes:
 • Declaração da macro.
 • Código da macro.
 • Diretiva de término da macro.
Podemos declarar uma macro assim:
NomeMacro MACRO [parametro1, parametro2...]
Assim como podemos usar parâmetros, também podemos criar 
uma macro sem eles.
IMPORTANTE:
Para finalizar uma macro, usamos o comando: ENDM.
Chamadas de
macro não devem ser confundidas com chamadas de 
procedimento. A diferença básica é que a primeira é uma 
instrução para o assembler substituir o nome da macro 
pelo corpo dela. Uma chamada de procedimento é 
uma instrução de máquina que é inserida no programa-
objeto e que mais tarde será executada para chamar o 
procedimento. (TANENBAUM; AUSTIN, 2013, p. 414)
VOCÊ SABIA?
MACRO e ENDM são instruções que indicam início e fim de 
uma macro.
Mesmo que o formato da linguagem de montagem mude de 
acordo com os tipos de processadores, a programação de macro possui 
um padrão, independentemente de ser uma programação para o Core 
Linguagem de Montagem
53
da Intel ou um ARM. Ou seja, todos requerem as mesmas estruturas ou 
partes básicas no momento de definição de macro:
 • É necessário possuir um cabeçalho de macro, com o nome da 
macro que está sendo criada ou definida.
 • Possuir um texto que abranja toda a estrutura da macro.
 • Uma finalização, ou uma pseudoinstrução que delimite o final da 
definição (por exemplo, ENDM).
Quadro 4 – Comparação de chamadas de macro e chamadas de procedimento
ITEM Chamada de 
macro 
Chamada de 
procedimento
Quando a chamada 
é feita?
Durante a 
montagem
Durante a execução do 
programa
O corpo é inserido 
no programa-
objeto em todos os 
lugares em que a 
chamada é feita?
SIM NÃO
Uma instrução 
de chamada de 
procedimento 
é inserida no 
programa-objeto 
e executada mais 
tarde?
NÃO SIM
Deve ser usada 
uma instrução 
de retorno após 
a conclusão da 
chamada?
NÃO SIM
Quantas cópias do 
corpo aparecem no 
programa-objeto?
Uma por 
chamada de 
macro
Uma
Fonte: Tanenbaum e Austin (2013, p. 414).
Para exemplificar, vamos usar uma macro para colocar o cursor em 
uma determinada posição da tela:
Linguagem de Montagem
54
Pos MACRO Linha, Coluna
 PUSH AX
 PUSH BX
 PUSH DX
 MOV AH, 02H
 MOV DH, Linha
 MOV DL, Coluna
 MOV BH, 0
 INT 10H
 POP DX
 POP BX
 POP AX
ENDM
Aqui em linguagem de montagem, assim como nas linguagens de 
alto nível, para usar uma macro é necessário chamar pelo nome. 
Adiante temos um exemplo de macro com a estrutura condicional 
IF (TANENBAUM; AUSTIN, 2013, p. 416):
M1 MACRO
 IF WORDSIZE GT 16
M2 MACRO
 ...
 ENDM
 ELSE
M2 MACRO
 …
ENDM
Linguagem de Montagem
55
 ENDIF
 ENDM
Na figura que se segue, temos um comparativo de um código com 
uso de macro e o mesmo código sem o uso de macro.
Figura 14 – Sequências de instruções com e sem uso da macro – (a) Sem uma macro; (b) 
Com uma macro
MOV EAX,P CHANGE MACRO P1, P2
MOV EBX,Q MOV EAX,P1
MOV Q,EAX MOV EBX,P2
MOV P,EBX MOV EBX,P2
MOV P1,EBX
MOV EAX,R ENDM
MOV EBX,S
MOV S,EAX CHANGE P, Q
MOV R,EBX
CHANGE R, S
(a) (b)
Fonte: Tanenbaum e Austin (2013, p. 415).
Biblioteca de macros
Ao usar o recurso de macro, uma das facilidades é que podemos 
criar bibliotecas, que são conjuntos de macros, pelo qual podemos incluir 
em um programa diferentes arquivos.
Para criar bibliotecas, é bastante simples. É necessário criar um 
arquivo com todas as macros necessárias e salvar como um arquivo do 
tipo texto. Para incluir a biblioteca em um programa, precisamos colocar a 
instrução Include NomedoArquivo no início do programa, antes de ocorrer 
a declaração do modelo de memória.
Linguagem de Montagem
56
Para exemplificar, vamos supor que o arquivo de macros tenha sido 
salvo com o nome de MACROS.TXT, a instrução Include poderia ser usada 
da seguinte maneira:
 ;Início do programa
 Include MACROS.TXT
 .MODEL SMALL
 .DATA
 ;Os dados vão aqui
 .CODE
 Inicio:
 ;O código do programa começa aqui
 .STACK
 ;A pilha é declarada
 End Inicio
 ;Fim do programa
A seguir, temos outro exemplo de macro:
 PrintX MACRO
 mov al,’X’
 call WriteChar
 ENDM
Para chamar a macro anterior em Assembly, usamos o comando 
que se segue:
.code
PrintX
Quando o processador chamar o programa, vai descobrir que temde chamar PrintX.
Linguagem de Montagem
57
Por fim, macros podem chamar outras macros, incluindo 
elas mesmas. Se uma macro for recursiva, isto é, chamar 
a si mesma, deve passar para si mesma um parâmetro 
que é trocado a cada expansão, e a macro deve testar o 
parâmetro e encerrar a recursão quando alcançar certo 
valor. Caso contrário, o assembler pode ser colocado em 
um laço infinito. Se isso acontecer, o Assembly deve ser 
terminado explicitamente pelo usuário. (TANENBAUM; 
AUSTIN, 2013, p. 416)
A seguir temos um exemplo de macro em formato NASM (Netwide 
Assembly), que é um tipo de montador de código-fonte aberto.
Figura 15 – Macro em NASM
%MACRO PROLOGUE 1
 PUSH EBP ; coloca conteúdo de EBP na pilha
 ; apontada por ESP e
 ; decrementa conteúdo de ESP em 4
 MOV EBP, ESP ; copia conteúdo de ESP para EBP
 SUB ESP, %1 ; subtrai o valor do primeiro parâmetro de ESP
 %ENOMACRO
Fonte: Stalling (2010, p. 587).
“O número 1 depois do nome da macro na linha %MACRO define o 
número de parâmetros que a macro espera receber. O uso de %1 dentro 
da definição da macro refere-se ao primeiro parâmetro da chamada da 
macro” (STALLING, 2010, p. 588).
Então, quando chamamos a macro PROLOGUE
MYFUNC: PROLOGUE 12
Será expandido as linhas de código subsequente:
MYFUNC: PUSH EBP
 MOV EBP, ESP
 SUB ESP, 12
Muitos programas de linguagem de montagem fazem uso do 
recurso de macro permitindo que o programador possa dar nomes 
simbólicos para cada sequência de código, além de ser muito usada 
para inclusão subsequente. De forma geral, o uso de macros pode ser 
Linguagem de Montagem
58
parametrizado em um formato direto. As macros podem ser executadas 
por um algoritmo de processamento literal de cadeias (TANENBAUM; 
AUSTIN, 2013, p. 433).
RESUMINDO:
E então? Gostou do que lhe mostramos? Aprendeu mesmo 
tudinho? Agora, só para termos certeza de que você 
realmente entendeu o tema de estudo deste capítulo, 
vamos resumir tudo o que vimos. Você deve ter aprendido 
que podemos usar a macro para otimizar procedimentos. 
As macros são utilizadas em diversos programas e podem 
ser utilizadas no programa Assembly também. Para otimizar 
ainda mais os procedimentos de programação, podemos 
fazer uso da biblioteca de macros para deixar o código 
elegante e arrumado. Para incluir esse arquivo de macro, 
em formato de biblioteca, nos programas desenvolvidos em 
Assembly, podemos usar os comandos “Include”. Essa linha 
de programação deve ser inserida no início do programa. As 
chamadas de macro podem ocorrer durante todo o código 
do programa, basta chamar a macro pelo nome, e todos os 
procedimentos que estão na macro serão executados. Para 
finalizar a macro, usamos comando específico, o “ENDM”, 
por exemplo, podendo ser alterado de acordo com o 
processador que estamos programando, como o NASM, 
no qual finalizamos com o comando “%ENOMACRO”.
Linguagem de Montagem
59
REFERÊNCIAS
MENTE BINÁRIA. Fundamentos da engenharia reversa, [s.d.]. 
Disponível em: https://mentebinaria.gitbook.io/engenharia-reversa/
assembly/registradores. Acesso em: 15 maio 2022.
SCHMIDT, G. Introdução para o iniciante à Linguagem Assembly 
dos microprocessadores ATMEL-AVR, 2003. Disponível em: www.avr-
asm-tutorial.net. Acesso em: 20 abr. 2022.
STALLINGS, W. Arquitetura e organização de computadores. 
8. ed. São Paulo: Pearson, 2002. Disponível em: http://www.telecom.uff.
br/orgarqcomp/arq/arquitetura-e-organizacao-computadores-8a.pdf. 
Acesso em: 07 abr. 2022.
TANENBAUM, A.; AUSTIN, T. Organização estruturada de 
computadores. 6. ed. São Paulo: Pearson, 2013.
Linguagem de Montagem
http://www.telecom.uff.br/orgarqcomp/arq/arquitetura-e-organizacao-computadores-8a.pdf
http://www.telecom.uff.br/orgarqcomp/arq/arquitetura-e-organizacao-computadores-8a.pdf

Mais conteúdos dessa disciplina