Buscar

8 - Assembly x86

Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original

*
*
Prof. Dr. Remy Eskinazi
IFPE / UPE 
Programação Assembly 8086/8088
*
*
Introdução
Assembly - linguagem que surgiu para representar as instruções por símbolos e não por números (linguagem simbólica), conhecida como linguagem de montagem. 
Qual o mais fácil de lembrar 10101011 ou ADD ?
Necessidade de conversão dos símbolos para linguagem de máquina, linguagem que o µP entende. O processo de conversão (tradução) é chamado de montagem e é realizada por um programa denominado Montador (assembler).
*
*
Montagem de Programa
*
*
Montagem de Programa
Principais funções:
substituir código de operações simbólicas
substituir nomes simbólicos de endereços
reservar espaço de memória
converter constantes
examinar a correção de cada instrução
*
*
Características da Programação Assembly
Declaração e uso de label (corresponde a uma posição de memória e substitui um endereço);
Existência de diretivas do montador (pseudo instruções ou comandos do montador)
Existem diversos montadores para uma mesma arquitetura - MASM, TASM, EMU8086 ...
Definição de áreas de memória (código, dados, etc)
Segmentação de memória
*
*
Segmentação de Memória
A arquitetura dos processadores x86 usa segmentos de memória para gerenciar a informação, o tamanho destes segmentos é de 64Kb.
O tamanho máximo de um número que o processador pode gerenciar é dado por uma palavra de 16 bits ou registrador, não sendo possível acessar mais do que 64k locais da memória apenas com um destes registradores. 
Sendo a memória do PC dividida em grupos de segmentos, cada um com 64k locais, e podemos usar um endereço ou registrador exclusivo para encontrar cada segmento, e ainda fazemos cada endereço com dois registradores. É possível acessar a quantidade de 4.294.967.296 bytes de memória. 
Para que o montador seja capaz de gerenciar os dados, é necessário que cada informação ou instrução se encontre na área correspondente ao seu segmento. O endereço do segmento é fornecido ao montador pelos registradores DS, ES, SS e CS. 
*
*
Segmentação de Memória
*
*
Registradores IA32 / X86
15
8
7
0
EAX
AH
AL
EBX
BH
BL
ECX
CH
CL
EDX
DH
DL
ESP
EBP
ESI
EDI
EIP
EF
CS
DS
SS
ES
FS
GS
16
31
acumulador
base
contador
dado
ponteiro para pilha
ponteiro base
índice fonte
índice destino
apontador de instruções
flags
segmento de código
segmento de dados
segmento de pilha
segmento extra
segmento extra
segmento extra
AX:
BX:
CX:
DX:
*
*
Registradores IA32 / X86
1) Os registradores de uso geral são registradores de 16 bits e podem ser divididos em dois registradores de 8 bits. São eles: 
AX - acumulador AH AL 
BX - base BH BL (utilizado em modos de endereçamento). 
CX - contador CH CL (utilizado como contador de operações de string) 
DX - dados DH DL 
*
*
Registradores IA32 / X86
2) Os registradores de ponteiros e endereços são: 
SP - stack pointer 
BP - base pointer - utilizados como apontador para acesso a diversos tipos de dados. 
SI - source index (índice e origem) 
DI - destination index - utilizados para acessar dados no segmento de dados. 
*
*
Registradores IA32 / X86
3) Os registradores de segmento de 16 bits são: 
CS - code segment - segmento de código corrente 
DS - data segment - segmento de dados 
SS - stack segment - segmento da pilha 
ES - extra segment - segmento extra utilizado como registrador. 
*
*
Registradores IA32 / X86
4) Flags são utilizados para armazenar informações sobre o status do processador. Normalmente são utilizados para setar dados após a execução de instruções lógicas e aritméticas. São eles: 
CF - carry flag 1 - ocorreu carry 0 - não 
PF - parity flag 1 - número par de 1 0 - ímpar 
AF - auxiliar flag 1 - ocorreu carry em operação bcd no dígito menos significativo. 0 - não 
ZF - zero flag 1 - resultado é zero 0 - não 
SF - signal flag 1 - negativo 0 - + 
OF - overflow flag 1 - ocorreu overflow 0 - não 
TF - trap flag - executa um programa passo a passo 
IF - interrupt flag 1 - interrupções habilitadas 0 - não 
DF direction flag 1 - crescente 0 - decrescente 
*
*
Modos de Endereçamento
Imediato: operando é uma constante que segue o código de instrução. ex: mov bl,100 
Registrador: operandos são registradores. ex: mov bl,ah 
Direto: operando localiza-se em um endereço específico na instrução (uma variável criada pelo programador) ex: add ax, varnum 
Indireto: operando localiza-se em um endereço apontado por um registrador base ou índice (BP,SI,DI). ex: mov cx,[di] 
Base: o endereço é dado pela soma do registrador base BP mais o deslocamento. ex: add ax,[bp+deslocamento] 
Indexado: o endereço é dado pela soma do registrador de indice SI ou DI mais um deslocamento. ex: add ax,[si + deslocamento] 
Indireto com base e índice: o endereço é dado pela soma de um registrador de segmento mais um registrador de base mais um registrador de índice. ex add ax,[bp+di+deslocamento].
*
*
Exercício:
Baseado no trecho de código indicado na coluna Programa
e nos dados de registradores, variáveis e memória,
 complete as colunas ax e Modo End. (endereçamento):
bp = 0 0 0 2h
=
( Definido na área de dados )
*
*
Tipos de Instrução
Movimento de dados
move dados na memória e em registradores da CPU;
Operações lógicas e aritméticas
Saltos, laços e procedimentos
*
*
Instruções Assembly
adc - adicionar dois operandos mais o carry e coloca o resultado no primeiro. ex add ax,bx
add - somar dois operandos e coloca o resultado no primeiro. 
 Ex. add ax,bx 
and - E lógico bit a bit, coloca o resultado no primeiro operando. 				 Ex. and ax,FFFF 
cld - zera o flag de direção e segue em ordem crescente. 
cli - inibe interrupções. 
call - chama uma subrotina. Ex. call le_num 
cmp - compara dois operandos. Não altera o resultado dos operandos (subtrai e joga fora o resultado). Ex. cmp ax,bx 
dec - decrementa de '1' um registrador. Ex. dec ax 
div - divide dois operandos. Coloca o quociente em dl e o resto em dh. 
inc - incrementa de '1' um registrador. 		Ex. inc ax 
int - chama uma interrupção do S.O. 		Ex. int 21 
As instruções em linguagem Assembly no programa fonte devem obrigatoriamente serem escritas por uma linha no formato:
[label:] [operação] [operandos] [;comentários]
*
*
Instruções Assembly
jc - desvia se ocorreu carry. 	Ex. jc fim obs.: fim é um label
je - desvia se resultado igual a zero. 	Ex. je fim 
jmp - desvio incondicional. 		Ex. jmp fim 
jl - desvia se resultado é menor. 	Ex. jl fim 
jle - desvia se resultado é menor ou igual.	 Ex. jle fim 
jg - desvia se resultado é maior. 	Ex. jg fim 
jge - desvia se resultado é maior ou igual. 	Ex. jge fim 
jz - desvia se resultado igual a zero. 	Ex. jz fim 
jne - desvia se for diferente. 		Ex. jne fim 
jnl - desvia se resultado maior ou igual. 		Ex. jnl fim 
*
*
Instruções Assembly
jng - desvia se resultado menor ou igual. Ex. jng fim 
jnz - desvia se resultado não for zero. Ex. jnz fim 
lahf - carrega flags no ah 
lea– Carrega endereço efetivo
loop - repete um laço cx vezes 
mov - move dados entre registradores. ex mov ax,bx 
mul - multiplica AX * operando. Coloca o resultado em DX:AX. Ex. mul bx 
neg - troca o sinal 
nop – nenhuma operação
not - inverte os bits 
offset - atribui a um registrador o endereço de memória de uma instrução. Ex. mov di,offset string 
*
*
Instruções Assembly
or - ou lógico bit a bit. Coloca o resultado no primeiro operando. Ex. : or ax,ax 
pop - retira o operando da pilha. Ex. pop ax 
popf - retira os flags da pilha. Ex. popf 
push - coloca o operando na pilha. Ex. push ax 
pushf - coloca os flags na pilha. Ex. pushf 
ret n - retorna para a próxima linha da chamada. O parâmetro n determina o número de bytes a serem desempilhados no retorno além do endereço de retorno. Ex. ret ou ret 4. 
rcl - rotaciona para a esquerda com carry. 
rcr - rotaciona para a direita com carry. 
rol
- rotaciona para a esquerda. Ex. rol ax,cx rol ax,1 
*
*
Instruções Assembly
ror - rotaciona para a direita. 		Ex. ror ax,cx ror ax,1 
sahf - seta flags à partir do ah 
sbb - subtrai dois operandos e o carry colocando o resultado no primeiro. 				Ex. sub ax,bx 
shl - deslocamento para a esquerda, colocando o bit deslocado no carry e insere zero. 
shr - deslocamento para a direita, colocando o bit deslocado no carry e insere zero. 
std - seta o flag de direção em ordem decrescente. 
sub - subtrai dois operandos colocando o resultado no primeiro. 					Ex. sub ax,bx 
xor - ou exclusivo bit a bit, coloca o resultado no primeiro operando. 					Ex. xor ax,ax
*
*
Instruções Assembly
Exercícios:
1 – Escrever um programa para gerar o complemento de 2 de AL
2 – Escrever um programa que determine se existe um byte 0 em AL ou BL ou CL ou DL. Sinalize com AH = 1 caso isto ocorra.
 
3 –Escrever um programa para determinar o maior valor entre AL, BL, CL e DL e escreve-lo em AH.
4 – Escrever um programa para converter um byte em AL em seu ASCII e escreve-lo na tela
5 –Escreva um programa para ler um dígito hexadecimal de A a F (maiúsculo) e exibi-lo em decimal na próxima linha. Utilize mensagens convenientes.
Exemplo:
Entre um digito hexa: D 
O seu valor decimal vale: 14
*
*
Complemento a 2
Complemento a 2: regra prática
Considere X = 0000 1000, o complemento a 2 de X será:
-X = 1111 1000
*
*
Conversão ASCII Algoritmo
Considere NH um número hexadecimal de dois dígitos, com valores entre 00 e FFH. Na conversão para ASCII, os dois dígitos são separados e cada dígito é convertido separadamente para o seu respectivo codigo ASCII. O algoritmo a seguir exemplifica a conversão para o número A8H:
separa-se o número A8H de dois dígitos. 
0AH 
08H. 
(Observe que ambos dígitos ocupam a parte menos significativa do byte).
 
converte-se cada número para o seu respectivo código ASCII.
0AH é convertido para 41H (0A > 09 => 0A+37 = 41)
08H é convertido para 38H (08 ≤ 09 => 08+30 = 38 )
*
*
Tabela ASCII
*
*
TABELAS DE EQUIVALÊNCIA
Cada uma das partes numa linha de código assembly é conhecida como token:
MOV AX,Var - Aqui temos três tokens:
Instrução MOV, operador AX e operador VAR.
O montador lê cada um dos tokens e procurar a equivalência em código de máquina em tabelas correspondentes, seja de palavras reservadas, tabela de códigos de operação, tabela de símbolos, tabela de literais, onde o significado dos mnemônicos e os endereços dos símbolos que usamos serão encontrados.
O montador lê MOV e encontra na tabela de códigos de operação o seu equivalente na linguagem de máquina. 
Lê AX e encontra-o na tabela correspondente como sendo um registrador. 
O processo para Var é um pouco diferenciado, o montador verifica que ela não é uma palavra reservada, então procura na tabela de símbolos, lá encontrando-a ele designa o endereço correspondente, mas se não encontrou ele, insere na tabela para que ela possa receber um endereço. 
*
*
Programação Assembler
É importante incluir as seguintes diretivas de montador:
.MODEL - Define o modelo de memória usado no programa
Modelos de memória possíveis: Ex.: .MODEL small
Tiny: um segmento de 64k para acomodar código, pilha de dados e programa (usados para programas .com) 
Small: Todo código em 1 segmento, enquanto que outros dados estarão em outro;
Compact: código não > que 64k mas dados podem usar mais de um segmento
Large: Tanto programa, quanto dados podem ser > 64k
Huge: semelhante ao Large, mas permite criação de tabelas e matrizes de dados maiores que 64k;
Obs.: para a grande maioria das aplicações o small é suficiente;
.CODE - Define as instruções do programa, relacionado ao segmento de código
.DATA – Reserva uma área de dados para o programa
.STACK - Reserva espaço de memória para as instruções de programa na pilha
DB – Define Byte – Define um valor na posição de memória indicada. Ex: Byte1 DB 01H, Msg DB ‘Mensagem”
END - Finaliza um programa assembly
*
*
Interrupções
Interrupção por Hardware
Interrupção por Exceção
Interrupção por Software
*
*
Interrupções por Software
Programas em assembly podem usar serviços do SO para realizar E/S.
Essas funções são chamadas pela interrupção INT 21h
Os parâmetros dessa subrotina são passados pelos registradores AH, AL, DL;
AH determina qual a função esta sendo selecionada. Exemplos:
AH			Função
1		Entrada de teclado - espera uma caractere ser
		digitado, mostra-o na tela e guarda seu ASCII em AL;
8		Entrada de teclado sem eco - espera a digitação e guarda seu ASCII em AL
2		Saída na tela - mostra na tela os caracteres (ASCII) armazenados em DL:
9		Saída de string na tela - mostra o string apontado por DS:DX (o ultimo
		caractere deve ser $)
4Ch 	retorno ao SO. Sai do programa;
*
*
Exemplo de Programa Assembly
; *******Exemplo de uma estrutura de programa assembly *********
TITLE nome_do_programa
.MODEL	SMALL .STACK	100h
.DATA
;
;definição dos dados: variáveis e constantes
;
.CODE
EXEMPLO PROC
;
;seqüência de instruções
;
EXEMPLO ENDP
;
;segue outras procedures
;
END EXEMPLO
Obs: 
na primeira linha tem-se a diretiva TITLE seguida do nome do programa;
na última linha tem-se a diretiva END, seguida do nome da procedure principal;
se não houver definição de procedure, usa-se apenas END.
*
*
Programação Assembler
; multi-segment executable file template.
data segment
 ; add your data here!
 pkey db "press any key...$"
ends
stack segment
 dw 128 dup(0)
ends
code segment
start:
; set segment registers:
 mov ax, data
 mov ds, ax
 mov es, ax
 ; add your code here
 
 lea dx, pkey
 mov ah, 9
 int 21h ; output string at ds:dx
 
 ; wait for any key.... 
 mov ah, 1
 int 21h
 
 mov ax, 4c00h ; exit to operating system.
 int 21h 
ends
end start ; set entry point and stop the assembler.
*
*
Tela Inicial EMU8086
*
*
Tela Inicial EMU8086
*
*
Simulador EMU8086
*
*
Exemplo1.asm 
imprime “R” na tela
.model small
.stack
.code
 mov ah,2h ;Prepara função 2 (imprime caracter na tela) da int 21
 mov dl,52h ; mov dl, ‘R’ - move o valor 52h para o registrador dl
 ;(é o valor ASCII do caractere “R”)
 int 21h ;interrupção 21h: Mostra “R” na tela
 mov ah,4ch ;função 4ch, sai para o sistema operacional
 int 21h ;interrupção 21h
end ;finaliza o programa
*
*
*
Imprime nome
.model small
.stack
.code
mov dl,'R' ; move o valor R para o registrador dl 
call print_caracter; imprime caracter
mov dl, 'e' ; move o valor e para o registrador dl
call print_caracter; imprime caracter
mov dl, 'm' ; move o valor ‘m. para o registrador dl
call print_caracter; imprime caracter
mov dl,'y' ;move o valor y para o registrador dl
call print_caracter; imprime caracter
Jmp fim
	Print_caracter proc
 		mov ah,2h 	;função 2h, imprime caracter
 		int 21h 	;imprime o caracter que está em dl
 		ret 	;retorna o controle ao procedimento que chamou
	 Print_caracter endp
Fim: mov ah,4ch ;função 4ch, sai para o sistema operacional
 	 int 21h ;interrupção 21h
end ;finaliza o programa
*
*
Programa Imprime String
Use qualquer editor para criar o programa fonte. Entre com as seguintes linhas:
Use ; para fazer comentários
.MODEL small
.STACK 100h ;reserva uma área de pilha, embora não seja usada neste exemplo
.DATA
 mensagem1 DB 'Meu primeiro programa funcionou!!',13,10,'$'
.CODE
mov ax,data
mov ds,ax 	;seta DS para apontar para o segmento de dados
lea dx,mensagem1	;aponta para “Meu primeiro programa funcionou"
mov ah,9 	;interrupção do SO para imprimir a string
int 21h ;mostra "Meu primeiro programa funcionou!!"
mov ah,4ch ;Interrupção para terminar o programa
int 21h ;termina o programa
END
Este programa assembly imprime a string da área de dados na tela.
*
*
Exemplo4.asm
Este programa mostra os caracteres ABCDEFGHIJ na tela.
.model small
.stack
.code
PRINT_A_J PROC
 MOV DL,'A' 	;move o character A para o registrador DL
 MOV CX,10 	;move o valor decimal 10 para o registrador CX
 		;este valor é usado para fazer laço com 10 interações
PRINT_LOOP:
 CALL WRITE_CHAR 	;Imprime o caracter em DL
 INC DL 	;Incrementa o valor do registrador DL
 LOOP PRINT_LOOP 	;Laço para imprimir 10 caracteres
 MOV AH,4Ch 	;Função 4Ch, para sair ao DOS
 INT 21h 	 ;Interrupção 21h
PRINT_A_J ENDP 	;Finaliza o procedimento
WRITE_CHAR PROC
 MOV AH,2h 	;Função 2h, imprime caracter
 INT 21h 	;Imprime o caracter que está em DL
 RET 	;Retorna o controle ao procedimento que chamou
WRITE_CHAR ENDP 	;Finaliza o procedimento
 END PRINT_A_J 	;Finaliza o programa
*
*
Exemplo5.asm
Imprime Alfabeto Maiúsculo e Minúsculo
; outro modo de programa			
.model small
.stack
.data
 mensagem1 DB 13,10,'$'
.code
Title PRINT_A_J
 			 MOV DL,'A' 	;move o character A para o registrador DL
 			 MOV CX,23 	;move o valor decimal 10 para o registrador CX
			CALL PRINT_LOOP
			mov ax,data
			mov ds,ax 	;seta DS para apontar para o segmento de dados
			lea dx,mensagem1	;aponta para “Meu primeiro programa funcionou"
			mov ah,9 	;interrupção do SO para imprimir a string
			int 21h 
			MOV DL, ‘a’
 			MOV CX,23 	 	;move o valor decimal 10 para o registrador CX
			CALL PRINT_LOOP
			 MOV AH,4Ch 	;Função 4Ch, para sair ao DOS
 			 INT 21h 		;Interrupção 21h
					;Finaliza o procedimento
 				;este valor é usado para fazer laço com 10 interações
PRINT_LOOP: 	CALL WRITE_CHAR 	;Imprime o caracter em DL
 			INC DL 		;Incrementa o valor do registrador DL
 			LOOP PRINT_LOOP 	;Laço para imprimir 10 caracteres
 			RET
WRITE_CHAR:	MOV AH,2h 	;Função 2h, imprime caracter
 			INT 21h 	;Imprime o caracter que está em DL
 			RET 		;Retorna o controle ao procedimento que chamou
			END		;Finaliza o programa
*
*
Exemplo5.asm
Este programa mostra na tela o valor dos 256 caracteres do código ASCII.
.model small
.stack
.code
PRINT_ASCII PROC
 MOV DL,00h ;move o valor 00h para o registrador DL
 MOV CX,255 ;move o valor decimal 255 para o registrador CX
 ;usado para fazer um laço com 255 interações
PRINT_LOOP:
 CALL WRITE_CHAR ;Chama o procedimento que imprime
 INC DL ;Incrementa o valor do registrador DL
 LOOP PRINT_LOOP ;Loop para imprimir 10 caracteres
 MOV AH,4Ch ;Função 4Ch
 INT 21h ;Interrupção 21h
PRINT_ASCII ENDP ;Finaliza o procedimento
WRITE_CHAR PROC
 MOV AH,2h ;Função 2h para imprimir um caracter
 INT 21h ;Imprime o caracter que está em DL
 RET ;Retorna o controle ao procedimento que chamou
WRITE_CHAR ENDP ;Finaliza o procedimento
 END PRINT_ASCII ;Finaliza o programa
*
*
Exemplo6.asm
Este programa lê dois caracteres e os imprime na tela.
;nome do programa: one.asm
;
.model small
.stack
.code
 mov AH,1h ;Função 1 do DOS
 int 21h ;lê caracter e retorna código ASCII ao registrador AL
 mov DL,AL ;move o código ASCII para o registrador DL
 sub DL,30h ;subtrai de 30h para converter a um dígito de 0 a 9
 cmp DL,9h ;compara se o dígito está entre 0 e 9
 jle digit1 ;se verdadeiro obtém o primeiro número (4 bits)
 sub DL,7h ;se falso, subtrai de 7h para converter a uma letra A-F 
digit1:
 mov CL,4h ;prepara para multiplicar por 16
 shl DL,CL ;multiplica para converter dentro dos 4 bits mais altos
 int 21h ;obtém o próximo caracter
 sub AL,30h ;repete a operação de conversão
 cmp AL,9h ;compara o valor 9h com o conteúdo do registrador AL 
 jle digit2 ;se verdadeiro, obtém o segundo dígito
 sub AL,7h ;se falso, subtrai de 7h 
digit2:
 add DL,AL ;adiciona o segundo dígito
 mov AH,4Ch ;função 4Ch do DOS (exit)
 Int 21h ;interrupção 21h
 End ;finaliza o programa
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Outros materiais