Programação assembly
Variáveis
São abstrações para endereços de memória contendo
dados
Independente da linguagem (e.g. C, assembly, Java)
Ao invés de utilizar um número para referir-se ao
endereço de memória contendo dados, utiliza-se uma
variável com um nome significativo no contexto do
programa Comentários
LDA 128 ; AC ← MEM(128) sintáticos
ADD 129 ; AC ← AC + MEM(129)
ADD 130 ; AC ← AC + MEM(130)
STA 131 ; MEM(131) ← AC LDA a ; AC ← a
HLT ; Pára o processador ADD b ; AC ← AC + b
ADD c ; AC ← AC + c
Utilização
STA res ; res ← AC
de variáveis
HLT ; Pára o processador
Programação assembly
Variáveis
A declaração de variáveis reserva espaço em memória
para o armazenamento de dados
; Definição de variáveis no NeanderWin
org 128 ; Indica o endereço de início da área de dados (variáveis)
a : db 1 ; Variável 'a' alocada no endereço 128 e inicializada com 1
b : db 2 ; Variável 'b' alocada no endereço 129 e inicializada com 2
c : db 3 ; Variável 'c' alocada no endereço 130 e inicializada com 3
res : db 0 ; Variável 'res' alocada no endereço 131 e inicializada com 0
org (origin) e db (define byte) são diretivas. Diretivas NÃO SÃO instruções.
Fazem parte do compilador/montador. Especificam como o
compilador/montador deve processar o código fonte.
Programação assembly
Exemplo 1: Versão 2 (variáveis)
Programa que soma o conteúdo de 3 posições de
memórias (variáveis) consecutivas (128, 129 e 130) e
armazena o resultado na posição seguinte (131)
org 0 ; Indica o endereço de início da área de instruções
LDA a ; AC ← a
ADD b ; AC ← AC + b
ADD c ; AC ← AC + c No processo de montagem, as
STA res ; res ← AC variáveis são substituídas pelo
endereço correspondente
HLT ; Pára o processador
; Definição de variáveis
org 128 ; Indica o endereço de início da área de dados
a: db 1 ; MEM(128) ← 1
b: db 2 ; MEM(129) ← 2
c: db 3 ; MEM(130) ← 3
res: db 0 ; MEM(131) ← 0
Programação assembly
Exemplo 1: Versão 2
NeanderWin
Programação assembly
Constantes podem estar na base hexadecimal
em qualquer parte do código assembly
org 0 ; Indica o endereço de início da área de instruções
LDA a ; AC ← a
ADD b ; AC ← AC + b Se o início da área de dados não
ADD c ; AC ← AC + c for específicado utilizando a
STA res ; res ← AC diretiva org, ela inicia logo após
a última instrução do programa
HLT ; Pára o processador
; Definição de variáveis
org 80h ; Indica o endereço de início da área de dados
a: db 0A2h ; MEM(128) ← 0xA2 Constantes hexadecimais
b: db 2 ; MEM(129) ← 2 iniciando com letra, devem ser
precedidas de 0
c: db 3 ; MEM(130) ← 3
res: db 0 ; MEM(131) ← 0
Programação assembly
Constantes podem estar na base hexadecimal
em qualquer parte do código assembly
org 0 ; Indica o endereço de início da área de instruções
LDA a ; AC ← a
ADD b ; AC ← AC + b
ADD c ; AC ← AC + c
STA res ; res ← AC
HLT ; Pára o processador
; Definição de variáveis
org 80h ; Indica o endereço de início da área de dados
a: db 0A2h ; MEM(9) ← 0xA2
b: db 2 ; MEM(10) ← 2
c: db 3 ; MEM(11) ← 3
res: db 0 ; MEM(12) ← 0
Programação assembly
void main() {
Exemplo 1: Versão 2 char a=0xA2, b=2, c=3, res=0;
res = a + b + c;
Em linguagem C }
org 0 ; Indica o endereço de início da área de instruções
LDA a ; AC ← a
ADD b ; AC ← AC + b Como o processador
ADD c ; AC ← AC + c diferencia dado e instrução ?
STA res ; res ← AC - ins_vs_data.asm
HLT ; Pára o processador
; Definição de variáveis
org 80h ; Indica o endereço de início da área de dados
a: db 0A2h ; MEM(9) ← 0xA2
b: db 2 ; MEM(10) ← 2
char: 8 bits
c: db 3 ; MEM(11) ← 3
res: db 0 ; MEM(12) ← 0
Programação assembly
Geração de código binário para o Neander
Código fonte em C
Infelizmente não há um
void main() { compilador que gere código
char a=1, b=2, c=3, res=0; assembly para o Neander!
res = a + b + c;
}
Compilador
Código fonte em assembly (Neander)
org 0
LDA a ; AC ← a
ADD b ; AC ← AC + b 00100000 Código binário
ADD c ; AC ← AC + c
10000000 (linguagem de
STA res ; res ← AC Montador 00110000 máquina)
HLT ; Pára o processador (e.g. NeanderWin) 10000001
; Definição de variáveis 00110000
org 128 ; Área de dados 10000010
a: db 1 ; a = MEM(128) ← 1 00010000
b: db 2 ; b = MEM(129) ← 2
10000011
c: db 3 ; c = MEM(130) ← 3
res: db 0 ; res = MEM(131) ← 0
11110000
Programação assembly
Labels (nomes de linha)
Também são abstrações para endereços de memória contendo
instruções
Utilizados em instruções de salto (e.g. JMP, JZ e JN)
Ao invés de utilizar um número para referir-se ao endereço de
memória onde se encontra uma instrução, utiliza-se um label
com um nome significativo no contexto do programa
org 0 ; Endereço de início do programa
LDA a ; AC ← a
ADD b ; AC ← AC + b
Comentários
Qual instrução será ADD c ; AC ← AC + c
sintáticos
executada depois de STA res ; res ← AC
JMP 4 ? JMP 4 ; Salta para o endereço 4
HLT ; Pára o processador
E se fosse JMP 5 ?
O processador é ingênuo!
Programação assembly
Labels (nomes de linha)
Também são abstrações para endereços de memória contendo
instruções
Utilizados em instruções de salto (e.g. JMP, JZ e JN)
Ao invés de utilizar um número para referir-se ao endereço de
memória onde se encontra uma instrução, utiliza-se um label
com um nome significativo no contexto do programa
O label abstrai o
endereço da org 0 ; Endereço de início do programa
instrução que inicio: ; inicio = endereço 0
O label indica o destino
aparece logo em LDA a ; AC ← a
do salto nas instruções de
seguida ADD b ; AC ← AC + b
jump
loop: ; loop = endereço 4
ADD c ; AC ← AC + c
STA loop ? No processo de
STA res ; res ← AC
montagem, os labels
O processador é JMP loop ; Salta para o label ‘loop’ (JMP 4) são substituídas pelo
muito ingênuo! fim: ; fim = endereço 10 endereço
HLT ; Pára o processador correspondente
Programação assembly
Labels (nomes de linha)
NeanderWin
Programação assembly
Labels (nomes de linha)
Também são abstrações para endereços de memória
contendo instruções
Utilizados em instruções de salto (e.g. JMP, JZ e JN)
Ao invés de utilizar um número para referir-se ao
endereço de memória, utiliza-se um label com um nome
significativo no contexto do programa
O label abstrai o org 0 ; Endereço de início do programa
endereço da inicio: ; inicio = endereço 0
instrução que LDA a ; AC ← a O label indica o destino
aparece logo em ADD b ; AC ← AC + b do salto nas instruções de
seguida loop: ; loop = endereço 4 jump
ADD c ; AC ← AC + c
STA res ; res ← AC
JMP a ?
JMP loop ; Salta para o label ‘loop’ (JMP 4)
O processador é
fim: ; fim = endereço 10
ingênuo demais!
HLT ; Pára o processador
Programação assembly
Labels (nomes de linha)
Também são abstrações para endereços de memória
contendo instruções
Utilizados em instruções de salto (e.g. JMP, JZ e JN)
Ao invés de utilizar um número para referir-se ao
endereço de memória, utiliza-se um label com um nome
significativo no contexto do programa
org 0 ; Endereço de início do programa
inicio: LDA a ; AC ← a
Labels podem ser
colocados ao lado ADD b ; AC ← AC + b
das instruções loop: ADD c ; AC ← AC + c
STA res ; res ← AC
JMP loop ; Salta para o label ‘loop’ (JMP 4)
fim: HLT ; Pára o processador
Programação assembly
Indentação de código
Melhora a legibilidade e o entendimento independente da
linguagem
Indentar usando 4 espaços (NÃO USAR TAB)
Código indentado
org 0 Código não indentado
inicio: LDA a org 0
ADD b
inicio: LDA a
loop: ADD c Estruturar código ADD b
STA res em blocos loop: ADD c
JMP loop STA res
JMP loop
fim: HLT fim: HLT
Programação assembly
Indentação de código
Melhora a legibilidade e o entendimento independente da
linguagem
Indentar usando 4 espaços (NÃO USAR TAB)
O que é indentação de Código? Qual é sua importância?
[Link]
qual-e-sua-importancia/#:~:text=Basicamente%20indentar%20%C3
%A9%20um%20termo,e%20o%20entendimento%20do%20programa
Prova
Prova Neander: 1/9
Conteúdo a partir dos slides de Introdução a
Arquitetura e Organização de computadores
Programação assembly
Exemplo 2
Verificar se um número é zero (código de condição Z)
Se AC = 0, então Z ← 1,
; Verifica se 'valor' é zero caso contrário Z ← 0 if (valor == 0)
lda valor ; Lê valor
jz valor_zero ; Salta se valor = 0 (Z = 1)
resultado = 1;
else
lda ZERO ; AC ← 0 (valor != 0) resultado = 0;
jmp fim ; Salta para o label ‘fim’
valor_zero:
lda UM ; AC ← 1 (valor = 0)
fim:
sta resultado ; Armazena resultado da verificação (AC) em ‘resultado’
hlt ; Pára o processador
; Definição de variáveis
org 80h ; Indica o endereço de início da área de dados
valor: db 0 ; Número a ser testado
resultado: db 0 ; '1' indica que valor = 0
; '0' indica que valor != 0
ZERO: db 0 ; Constante 0
UM: db 1 ; Constante 1
Programação assembly
Exemplo 2
NeanderWin
Programação assembly
Exemplo 3
Verificar se um número é negativo (código de condição N)
; Verifica se 'valor' é negativo Se AC[7] = 1, então N ← 1,
lda valor caso contrário N ← 0
; Lê valor if (valor < 0)
jn valor_negativo ; Salta se valor < 0, (N = 1)
resultado = 1;
lda ZERO ; AC ← 0 (valor >= 0) else
jmp fim ; Salta para o label 'fim' resultado = 0;
valor_negativo:
lda UM ; AC ← 1 (valor < 0)
fim:
sta resultado ; Armazena resultado da verificação (AC) em ‘resultado’
hlt ; Para o processador
; Definição de variáveis
org 128 ; Indica o endereço de início da área de dados
valor: db 0ffh ; Número a ser testado
resultado: db 0 ; '1' indica que valor < 0 Números negativos
; '0' indica que valor >= 0 representados em
ZERO: db 0 ; Constante 0 complemento de 2
UM: db 1 ; Constante 1
Programação assembly
Exemplo 3
NeanderWin
Programação assembly
Exemplo de utilização prática do flag Z na
arquitetura x86
[Link]
Programação assembly
Bare metal programming
Programação sem suporte de sistema operacional
O processador executa apenas o programa
desenvolvido
O programador define os endereços onde serão
armazenados programas e dados
Bastante comum em projetos envolvendo
microcontroladores
Programação assembly
Aviso importante
Assembly, como qualquer linguagem de
programação, só se aprende
programando
Programação assembly
Aviso importante
“A programação em linguagem de
montagem é difícil – não se iluda.”
Andrew Tanenbaum/Todd Austin
“Organização estruturada de computadores”
Programação assembly
Exercício 1: subtração c ← a – b
Neander não possui operação de subtração
c ← a – b ↔ c ← a + (–b)
-b = !b + 1 (complemento de 2)
; Exemplo 1
lda a ; AC ← a
add b ; AC ← AC + b
add c ; AC ← AC + c
sta res ; res ← AC
hlt ; Pára o processador
; Definição de variáveis
org 128 ;
a: db 1 ; a =1
b: db 2 ; b = 2
c: db 3 ; c = 3
res: db 0 ; res = 0
Programação assembly
Exercício 2: maior entre 2 números diferentes
c ← maior (a, b)
Se (a – b) < 0 então
c ← b (b é o maior)
Senão
c ← a (a é o maior) ; Exemplo 1
lda a ; AC ← a
add b ; AC ← AC + b
add c ; AC ← AC + c
sta res ; res ← AC
hlt ; Pára o processador
; Definição de variáveis
org 128 ;
a: db 1 ; a =1
b: db 2 ; b = 2
c: db 3 ; c = 3
res: db 0 ; res = 0
Programação assembly
Exercício 3: Verificar se uma variável é par
Se a variável é par então 11000010 11010011
resultado ← 1 and 00000001 and 00000001
Senão 00000000 00000001
par impar
resultado ← 0
; Exemplo 1
lda a ; AC ← a
add b ; AC ← AC + b
add c ; AC ← AC + c
sta res ; res ← AC
hlt ; Pára o processador
; Definição de variáveis
org 128 ;
a: db 1 ; a =1
b: db 2 ; b = 2
c: db 3 ; c = 3
res: db 0 ; res = 0
Programação assembly
Exercício 4: Valor absoluto de uma variável
c ← abs(a)
Se a < 0
c ← -a
Senão
; Exemplo 1
c←a
lda a ; AC ← a
add b ; AC ← AC + b
add c ; AC ← AC + c
sta res ; res ← AC
hlt ; Pára o processador
; Definição de variáveis
org 128 ;
a: db 1 ; a =1
b: db 2 ; b = 2
c: db 3 ; c = 3
res: db 0 ; res = 0
Programação assembly
Exercício 5: Triângulos
Dado 3 lados (a, b, c) verificar se é possível formar um
triângulo
Se (a < (b + c)) e (b < (a + c)) e (c < (a + b)) então
Triângulo ← 1
Senão
Triângulo ← 0
Programação assembly
Exercício 6: Calcular a distância Hamming entre 2
variáveis de 8 bits
Número total de bits onde as duas variáveis diferem
Exemplo: a = 89 e b = 26
010110012 (89)
000110102 (26)
Distância Hamming = 3
Programação assembly
Exercício 7: Somatório dos impares entre a e b
considerando a < b
c ← somatorio(a,b)
void main() {
char a = 3;
char b = 7;
char c = 0;
do {
if ((a % 2) != 0)
c = c + a;
a++;
} while (a <= b);
}
Programação assembly
Exercício 8: Somatório dos impares entre a e b
considerando a < b
c ← somatorio(a,b)
void main() {
char a = 3;
char b = 7;
char c = 0;
while (a <= b) {
if ((a % 2) != 0)
c = c + a;
a++;
}
}
Programação assembly
Exercício 9: multiplicação sem sinal (unsigned) por
somas sucessivas
c←a*b
Considerar que o resultado pode ser representado com 8 bits
void main() {
unsigned char a = 3;
unsigned char b = 5;
unsigned char c = 0;
while (a > 0) {
c = c + b;
a--;
}
}
Programação assembly
Exercício 10: multiplicação com sinal (signed -
complementos de 2) por somas sucessivas
c←a*b
Considerar que o resultado pode ser representado com 8 bits
Programação assembly
Exercício 11: divisão (unsigned) por subtrações
sucessivas
quociente ← a / b (parte inteira)
resto ← a % b
void main() {
unsigned char a = 10, b = 3;
unsigned char q = 0, r;
r = a;
while (r >= b) {
r = r - b;
q++;
}
}
Programação assembly
Exercício 12: divisão (signed – complemento de 2)
por subtrações sucessivas
quociente ← a / b (parte inteira)
resto ← a % b
Atenção ao sinal do resto
Programação assembly
Exercício 13: maior divisor comum
Ao final da execução, o maior divisor comum entre a e b
estará armazenado em a
void main() {
char a = 28, b = 32;
while (a != b)
if (a > b)
a = a - b;
else
b = b - a;
}
Programação assembly
Exercício 14: parte inteira da raiz quadrada
Ao final da execução, a parte inteira da raiz quadrada de
m estará armazenada em n
void main() {
char m = 120;
char n = 0, i = 1;
while (m >= i) {
m = m - i;
i = i + 2;
n = n + 1;
}
}
Programação assembly
Exercício 15: Detecção de overflow
Se c ← a + b gera overflow
overflow ← 1
Senão
overflow ← 0
Escrever um programa considerando a e b números com
sinal (signed – complemento de 2)
Escrever outro programa considerando a e b números
sem sinal (unsigned)
Dica: analisar a soma de binária no papel com números
de 3 bits
Programação assembly
Exercício 16: Soma de dois números de 16 bits
c←a+b
Os números a e b a serem somados devem ser
armazenados nos pares de variáveis ah:al e bh:bl
O resultado da soma deve ser armazenado no par ch:cl
; Definição de variáveis
... c Carry
; a = 1234h
ah al
ah: db 12h
al: db 34h
+ bh bl
ch cl
; b = 56EFh
bh: db 56h
bl: db 0EFh
; c = 0000
ch: db 0
cl: db 0
Programação assembly
Exercício 17: Soma de dois números de 32 bits
c←a+b
Os números a e b a serem somados devem ser
armazenados nas variáveis a3:a2:a1:a0 e b3:b2:b1:b0
O resultado da soma deve ser armazenado nas vaviáveis
c3:c2:c1:c0
; Definição de variáveis c c c Carry
... a3 a2 a1 a0
; a = 12345678h + a3 a2 b1 b0
a3: db 12h c3 c2 c1 c0
a2: db 34h
al: db 56h
a0: db 78h