5596.9 ARQUITETURA DE
COMPUTADORES
PROGRAMAÇÃO ASSEMBLY NA
ARQUITETURA X86
Aécio Fróes / CP05241-67 / [email protected] Bolsista CNPq/PIBIT
LACMO: Aprendizado Computacional e Métodos de Otimização
Visão geral
2

Motivação

Aplicações reais

Introdução

Arquitetura x86

Ferramentas de programação

Processo de programação

Diretivas do Turbo Assembler

Instruções da arquitetura x86

API do MS-DOS e BIOS PC

Exemplos de código-fonte

Referências

Perguntas e Discussões
Motivação
3

Sistemas operacionais


Segurança de aplicativos e sistemas


Identificação e correção de erros (patches) através de depuração e
engenharia reversa, análise de vírus para construção de vacinas através de
assinatura (virus signature)
Construção de ferramentas de programação


Rotinas de carga (bootloaders), partes do núcleo do sistema (kernel),
sistemas de tempo real (realtime systems), sistemas embarcados (embedded
systems), drivers de dispositivos (device drivers)
Compiladores, Montadores (Assemblers), Linkers
Rotinas de alto desempenho em aplicações

Sistemas gráficos, jogos de computador, criptografia
Aplicações reais
4


Initial Program Loader do QNX RTOS (http://www.qnx.com)
bootsect.s do Linux (http://tldp.org/HOWTO/Linux-i386-BootCode-HOWTO/bootsect.html)

ZSNES: emulador de jogos do Super Nintendo

SoftICE Debugger, da Nu-Mega Technologies

Vírus Chernobyl (CIH), por Chen Ing-Hau em 1998

UPX Packer: compactador de executáveis

Maioria dos firmwares de IBM-PC (e.g. AWARD, AMI)

Hotfix para o Windows Metafile, por Ilfak Guilfanov
(http://www.hexblog.com/2005/12/wmf_vuln.html)

IDA Pro Disassembler, por Ilfak Guilfanov

FASM: Assembler escrito em Assembly (http://flatassembler.net)
Introdução
5






Assembly utiliza mnemônicos curtos para representar as operações
fundamentais que a UCP (Unidade Central de Processamento) pode
executar
Nesse contexto, um mnemônico é um código, usualmente entre 1 e 5
letras, que representa um opcode
O código Assembly é de baixo nível e específico de um circuito,
máquina ou arquitetura
Um Assembler tradicional efetua um mapeamento do tipo um-paraum dos mnemônicos para as instruções e dados correspondentes
Assemblers modernos incluem suporte a macros e recursos de alto
nível, como controle de fluxo, funções, tipos abstratos de dados e
até suporte a programação orientada a objetos
Existem diversas sintaxes de Assembly, para a arquitetura x86
destacam-se a sintaxe Intel e a sintaxe AT&T. Não é case sensitive
Arquitetura x86
6

Intel 4004: primeiro microprocessador em um único chip

Surgiu em 1978 (Intel 8086/8088)

Arquitetura de 16, 32 e/ou 64 bits


x86-16 (16 bits)

x86-32/IA-32 (32 bits)

x86-64/EM64T, Intel64, AMD64 (64 bits)
Inicialmente CISC (Complex Instruction Set Computer), mas
atualmente os processadores são híbridos de RISC e CISC

Tamanho de instrução variável

Palavras são armazenadas na memória em ordenação little-endian

Código objeto criado para os processadores de 1978 ainda
executam nos últimos processadores da arquitetura x86
Arquitetura x86
7

Diagrama de blocos do 8086
Arquitetura x86
8


Modos de operação

Modo real

Modo protegido e “modo” virtual-8086
Modelos de memória

No modelo flat, a memória é vista como um simples e contínuo espaço de
endereçamento. Código, dados e pilha estão todos contidos nesse espaço

No modelo segmentado, a memória é, no contexto de um programa, um
grupo de espaços de endereçamento independentes chamados de
segmentos. Para endereçar um byte em um segmento, o programa utiliza
um endereço lógico composto de um seletor de segmento e um
deslocamento (offset) nesse segmento

O modelo de memória utilizado no modo real, que é o modelo do 8086, é
uma implementação específica do modelo segmentado onde cada
segmento tem o mesmo tamanho, com tamanho máximo de até 64KB

Modos de operação vs. Modelo de memória
Arquitetura x86
9

Registradores do 8086

AX: acumulador para operandos e resultados

BX: ponteiro para dados no segmento DS

CX: contador para operações com string e loops

DX: ponteiro para E/S

SI: ponteiro para origem em operações com strings

DI: ponteiro para destino em operações com strings

SP: ponteiro de pilha, no segmento SS

BP: ponteiro base de dados na pilha, no segmento SS

IP: ponteiro de instrução no segmento CS

CS: segmento de código

DS: segmento de dados

ES: segmento extra

SS: segmento de pilha
Arquitetura x86
10

Registrador de flags
Arquitetura x86
11

Modos de endereçamento do 8086

Os modos de endereçamento para os processadores de 16 bits da
arquitetura x86 podem ser resumidos pela seguinte fórmula:
Arquitetura x86
12

Tipos de dados fundamentais
Arquitetura x86
13

Organização dos dados na memória
Arquitetura x86
14

Tipos de dados numéricos
Ferramentas de programação
15

Editor de Texto




MS-DOS Editor, vi, emacs, Microsoft Bloco de Notas, Notepad++
Assembler

TASM: Borland Turbo Assembler

MASM: Microsoft Macro Assembler

NASM: The Netwide Assembler
Linker

TLINK: Borland Turbo Link

LINK: Microsoft Overlay Linker

ld: The GNU linker
Debugger

TD: Borland Turbo Debugger

DEBUG: Debug do Microsoft DOS/Windows
Processo de programação
16

Passo 1: criação de um ou mais arquivos de texto contendo
mnemônicos e diretivas (arquivo geralmente com a extensão .asm,
ou .inc em caso de include)


Passo 2: montagem através de um assembler, que produzirá, em
caso de sucesso, um ou mais arquivos objeto (extensão .obj)


edit relogio.asm
tasm relogio[.asm]
Passo 3: ligação (linkedição) dos vários arquivos objeto com
eventuais bibliotecas (extensão .lib) que produzirá o executável
final (arquivo .exe ou .com)

tlink relogio[.obj]
Diretivas do Turbo Assembler
17

.8086P


Habilita montagem das instruções do processador 8086 e do coprocessador numérico 8087. Este é o modo de instruções padrão do Turbo
Assembler.
END [expressão]

Delimita o fim de um módulo. Todo o conteúdo após essa diretiva é
ignorado. O argumento expressão, se presente, indica o ponto de entrada
do programa: o endereço em que o programa inicia sua execução. Um
programa pode conter vários módulos, mas apenas um deve definir um
ponto de entrada (e este módulo é chamado de módulo principal).
Diretivas do Turbo Assembler
18

.MODEL modelo

Configura o modelo de memória para diretivas de segmentação
simplificadas. Os modelos de memória definem os limites de código e
dados do seu programa. Eles determinam quando o Assembler deve
considerar referências para dados e códigos como NEAR ou FAR. Você
deve utilizar a diretiva MODEL antes de utilizar as diretivas de segmento
simplificadas como .CODE e .DATA. Modelos clássicos: TINY (dados e código
combinados em um único grupo, utilizado para binários .COM); SMALL
(código contido em um único segmento, modelo mais comum de binários do
tipo .EXE)
Diretivas do Turbo Assembler
19

.CODE


.DATA


Inicia ou continua o segmento de código do módulo, quando utilizada com a
diretiva .MODEL
Define o início do segmento de dados inicializado do módulo
.STACK [tamanho]

Inicia ou continua um segmento de pilha. O parâmetro opcional tamanho
indica a quantidade de pilha para reservar, em bytes. O valor padrão é
400h (1024 bytes).
Diretivas do Turbo Assembler
20

ORG expressão


Define o contador de posição do Assembler como sendo o valor de
expressão. É possível utilizar a diretiva ORG para associar um LABEL com
um endereço absoluto específico.
INCLUDE arquivo

Faz com que o Assembler processe código-fonte de um arquivo externo.
Pode ser utilizado para incluir uma biblioteca de MACROS ou
PROCEDURES.
Diretivas do Turbo Assembler
21

nome EQU valor

Permite associar um valor numérico a um nome

nome DB expressão [,expressão] ...

nome DW expressão [,expressão] ...

nome DD expressão [,expressão] ...

Aloca um Byte/Word/Doubleword e associa um nome que pode ser
utilizado posteriormente para referenciar o dado.

Em todos os casos, expressão pode ser ? (uma interrogação, que inicializa o
dado com valores indeterminados), DUP (uma expressão duplicada, que
repete a operação de alocação através de um contador), uma constante
com faixa de valores de acordo com o tamanho, uma expressão relativa.
Exemplo:

mensagem DB 'Pressione qualquer tecla para continuar. . . $'
Diretivas do Turbo Assembler
22

PROC nome


ENDP [nome]


Define uma macro que será expandida depois quando o seu nome é
encontrado
ENDM [nome]


Marca o fim de uma procedure (PROC)
MACRO nome


Define o início de uma procedure e associa um nome
Termina uma definição de macro
@data

Segmento que DS deve assumir quando é utilizada a diretiva .DATA
Instruções da arquitetura x86
23

AAA: ASCII Adjust After Addition

Sintaxe: AAA

Função: ajusta a soma de dois valores BCD não-compactados para criar um
BCD não-compactado em AX. Exemplo:

MOV AH,00H ;AH=0

MOV AL,33H ;AL = '3'

MOV DL,38H ;DL = '8'

ADD AL,DL ; AL = 6B

AAA ; AH = 1, AL = 1

AAD: ASCII Adjust AX Before Division

AAM: ASCII Adjust AX After Multiply

AAS: ASCII Adjust AL After Subtraction
Instruções da arquitetura x86
24


ADC: adição com carry flag

Sintaxe: ADC memória|registrador, memória|registrador|imediato

Função: adiciona o primeiro operando, o segundo e o carry flag
armazenando o resultado no primeiro operando. Exemplo:

MOV AH,30H ; AH = 30H

STC ; CF = 1

ADC AH,00H ; AH = 31H
ADD: adição

Sintaxe: ADD memória|registrador, memória|registrador|imediato

Função: adiciona o primeiro operando e o segundo, armazenando o
resultado no primeiro operando. Exemplo:

ADD AX,AX ; AX = AX+AX
Instruções da arquitetura x86
25



AND: AND lógico

Sintaxe: AND memória|registrador, memória|registrador|imediato

Função: efetua um AND lógico bit-a-bit e armazena o resultado no primeiro
operando. Exemplo:

MOV DL,39H ; DL = '9'

AND DL, 0FH ; DL = 9
CALL: chama função ou subrotina

Sintaxe: CALL memória|registrador|imediato

Função: chamada de função ou subrotina. Armazena [CS]:IP na pilha para
o retorno através da instrução RET.
CBW: converte byte para word

Sintaxe: CBW

Função: converte o byte em AL em uma word em AX, considerando o bit de
sinal em AL
Instruções da arquitetura x86
26



CLI: limpa flag de interrupção

Sintaxe: CLI

Função: zera o flag de interrupção (IF = 0, "desativa" interrupções)
CMP: compara dois operandos

Sintaxe: CMP memória|registrador, memória|registrador|imediato

Função: efetua a subtração operando1-operando2, descartando o
resultado porém ativando os flags. Exemplo:

CMP DL,39H ; DL - 39H

JZ fim ; JUMP se o flag de zero estiver ativado (i.e. se DL == 39H)
CWD

Sintaxe: CWD

Função: converte a word em AX em uma doubleword em DX:AX,
considerando o bit de sinal em AX
Instruções da arquitetura x86
27



DEC: decremento de 1

Sintaxe: DEC registrador|memória

Função: efetua um decremento de uma unidade do operando e salva o
resultado no operando. Exemplo:

MOV DL,0AH ; DL = 0AH

DEC DL ; DL = 09H
DIV: divisão sem sinal

Sintaxe: DIV registrador|memória

Função: se o operando é de 8 bits, AL = AX / operando e AH = AX %
operando, e se é de 16 bits, AX = DX:AX / operando e DX = DX:AX %
operando. Com resultados sem tratar o bit MSB como sendo de sinal
IDIV: divisão com sinal

Sintaxe e função iguais as da instrução DIV, porém considera o bit MSB
como sendo de sinal
Instruções da arquitetura x86
28

IMUL: multiplicação com sinal



Sintaxe e função iguais as da instrução MUL, porém considera o bit MSB
como sendo de sinal
IN: entrada de dados de uma porta

Sintaxe: IN AL|AX, DX|imediato de 8 bits

Função: efetua a leitura de um byte (resultado em AL) ou word (resultado
em AX) de uma porta
INC: incremento de 1




Sintaxe: INC registrador|memória
Função: efetua um incremento de uma unidade do operando e salva o
resultado no operando. Exemplo:
MOV DL,0FFH ; DL = FFH
INC DL ; DL = 00H
Instruções da arquitetura x86
29



INT: gera uma chamada de interrupção

Sintaxe: INT imediato de 8 bits

Função: PUSHF, PUSH CS, PUSH IP
IRET: retorno de uma rotina de tratamento de interrupção

Sintaxe: IRET

Função: efetua POP IP, POP CS e POPF nesta ordem
JXX|JNXX: deslocamento condicional

Sintaxe: JXX|JNXX deslocamento imediato de 8 bits

Função: efetua um deslocamento (salto) para execução de uma instrução em
outra posição de memória

O próprio assembler irá calcular o deslocamento, quando necessário,
baseado na posição atual $. Como o operando é de 8 bits, o deslocamento
está limitado entre -127 e 128 bytes.
Instruções da arquitetura x86
30

JXX|JNXX: deslocamento condicional

JA: jump se acima (operador > sem sinal)

JAE: jump se maior ou igual (operador >= sem sinal)

JB: jump se abaixo (operador < sem sinal)

JBE: jump se abaixo ou igual (operador <= sem sinal)

JE: jump se igual (operador ==)

JG: jump se maior (operador > com sinal)

JGE: jump se maior ou igual (operador >= com sinal)

JL: jump se menor (operador < com sinal)

JLE: jump se menor ou igual (operador <= com sinal)

Os deslocamentos também podem ser a negação dos acima vistos (i.e. JNA,
JNAE, JNB, JNBE, JNE, JNG, JNGE, JNL, JNLE
Instruções da arquitetura x86
31



JMP: deslocamento incondicional

Sintaxe: JMP deslocamento imediato|memória 16 bits|segmento:offset

Função: efetua o deslocamento (salto) para execução de uma instrução em
outra posição de memória
LEA: Load Effective Address

Sintaxe: LEA registrador 16 bits, referência na memória

Função: armazena no registrador o offset da referência na memória.
Exemplo:

MOV BX,4040H ; BX = 4040H

LEA SI,[BX+2] ; SI = 4042H
MOV: mover dados

Sintaxe: MOV registrador|memória, registrador|memória|imediato

Função: copiar o segundo operando para o primeiro operando. Exemplo:

MOV [BP+10H], CL
Instruções da arquitetura x86
32



MUL: Multiplicação sem sinal

Sintaxe: MUL registrador|memória

Função: se o operando é de 8 bits, AL = AX / operando e AH = AX %
operando, e se é de 16 bits, AX = DX:AX / operando e DX = DX:AX %
operando. Com resultados sem tratar o bit MSB como sendo de sinal
NEG: negação pelo complemento de 2

Sintaxe: NEG registrador|memória

Função: utilizada para tornar o operando negativo (i.e. operando = zero
– operando). Exemplo:

MOV AH,02H ; AH = 02H

NEG AH ; AH = 0FEH
NOP: código para não-operação

Sintaxe: NOP

Função: utilizada para não executar nenhuma operação
Instruções da arquitetura x86
33


NOT: negação pelo complemento de 1

Sintaxe: NOT registrador|memória

Função: utilizada para inverter os bits do operando (i.e. negação lógica).
Exemplo:

MOV AL, 0FH ; AL = 0FH

NOT AL ; AL = 0F0H
OR: operação de OR lógico

Sintaxe: OR registrador|memória, registrador|memória|imediato

Função: efetua um OR lógico bit-a-bit entre o primeiro operando e o
segundo, armazenando o resultado no primeiro operando. Exemplo:

MOV CL, 02H ; CL = 02H

OR CL, 01H ; CL = 03H
Instruções da arquitetura x86
34



OUT: escreve um valor em uma porta de E/S

Sintaxe: OUT DX|imediato, AX|AL

Função: escreve um byte (segundo operando AL) ou uma word (segundo
operando AX) em uma porta de E/S
PUSH: salva uma word na pilha

Sintaxe: PUSH registrador|memória

Função: salva o operando de 16 bits na pilha (SP = SP-2, SS:[SP] =
operando)
POP: restaura uma word da pilha

Sintaxe: POP registrador|memória

Função: restaura para o operando o valor de 16 bits do topo da pilha
(operando = SS:[SP], SP = SP+2)

PUSHF: salva o registrador de flags na pilha

POPF: restaura o registrador de flags da pilha
Instruções da arquitetura x86
35



RET: retorno de uma subrotina ou função

Sintaxe: RET

Função: copia a word do topo da pilha para o registrador IP, geralmente
utilizada para retornar de uma subrotina chamada através de CALL
SHL: efetua o deslocamento dos bits para esquerda

Sintaxe: SHL registrador|memória, 1|CL

Função: efetua os deslocamentos de bits para a esquerda indicados no
segundo operando. Exemplo:

MOV AH,01H ; AH = 01H

MOV CL,02H ; CL = 02H

SHL AH,CL ; AH = 04H
SHR: efetua o deslocamento dos bits para direita

Sintaxe e função idênticas a SHL, alterando apenas o sentido do
deslocamento
Instruções da arquitetura x86
36



SBB: subtração com empréstimo (carry)

Sintaxe: SBB registrador|memória, registrador|memória|imediato

Função: efetua subtração entre o primeiro operando e o segundo operando
mais o carry, armazenando o resultado no primeiro operando
STI: ativa o flag de interrupção (IF=1)

Sintaxe: STI

Função: ativa o flag de interrupção, ativando assim as interrupções
SUB: subtração

Sintaxe: SUB registrador|memória, registrador|memória|imediato

Função: efetua subtração entre o primeiro operando e o segundo,
armazenando o resultado no primeiro operando. Exemplo:

MOV AX,0002H ; AX = 02H

SUB AX,0002H ; AX = 00H, ZF = 1
Instruções da arquitetura x86
37


TEST: comparação lógica

Sintaxe: TEST registrador|memória,registrador|memória|imediato

Função: efetua um AND lógico bit-a-bit entre o primeiro operando e o
segundo, ativando os devidos flags mas descartando o resultado. Exemplo:

MOV AX,0000H ; AX = 0H, ZF = 0

TEST AX,AX ; AX = 0H, ZF = 1
XOR: efetua o XOR lógico

Sintaxe: XOR registrador|memória,registrador|memória|imediato

Função: efetua um XOR lógico bit-a-bit entre o primeiro operando e o
segundo, armazenando o resultado no primeiro operando. Exemplo:

XOR AX,AX
API do MS-DOS e BIOS IBM PC
38

INT 10H: funções da BIOS para o vídeo

Função 00H: altera o modo de vídeo

Função 0FH: obtém o modo de vídeo atual

Função 01H: altera o tamanho do cursor

Função 02H: altera a posição do cursor

Função 03H: altera a posição e o tamanho do cursor

Função 05H: altera a página do vídeo ativa

Função 08H: obtém caractere e atributo na posição do cursor
API do MS-DOS e BIOS IBM PC
39

INT 16H: interrupção do teclado

Função 00: lê um caractere do teclado



Chamada: AH = 00H

Retorna: AH = scan code, AL = caractere ASCII
Função 01: obtém o status do teclado

Chamada: AH = 01H

Retorna: ZF = 1 se não tem um caractere disponível para leitura

Retorna: ZF = 0, AH = scan code, AL = caractere ASCII caso contrário
Função 02: obtém os flags do teclado

Chamada: AH = 02H

Retorna: AL = flags (armazenados em 0000:0417H)
API do MS-DOS e BIOS IBM PC
40


INT 20H: termina processo

Chamada: CS = endereço de segmento do PSP

Retorna: nada
Outros métodos para terminar processo no MS-DOS:

INT 21H, função 00H

INT 21H, função 31H

INT 21H, função 4CH

INT 27H

As funções 31H e 4CH da INT 21H são os métodos mais utilizados, pois
permitem que um código de retorno seja passado para o processo pai
API do MS-DOS e BIOS IBM PC
41

INT 21H: API do MS-DOS

Função 01H: entrada de caractere com echo


Chamada: AH = 01H

Retorna: AL = código ASCII do caractere
Função 02H: saída de caractere



Chamada: AH = 02H, DL = código ASCII do caractere
Função 07H: entrada de caractere sem echo

Chamada: AH = 07H

Retorna: AL = código ASCII do caractere
Função 08H: entrada de caractere sem echo (CTRL+C)

Chamada: AH = 08H

Retorna: AL = código ASCII do caractere
API do MS-DOS e BIOS IBM PC
42

INT 21H: API do MS-DOS

Função 09H: exibe string



Chamada: AH = 09H, DS:DX = segmento:offset da string

Retorna: nada
Função 0AH: entrada bufferizada do teclado

Chamada: AH = 0AH, DS:DX = segmento:offset do buffer

Retorna: dados armazenados no buffer

Obs: o primeiro byte do buffer deve conter seu tamanho máximo
Função 4CH: termina processo com código de retorno

Chamada: AH = 4CH, AL = código de retorno

Retorna: nada (memória é liberada, arquivos são fechados, etc.)
Exemplos de código-fonte
43

Exemplo clássico de entrada e saída

Relogio residente

Calculadora em ponto flutuante

Dump de uma área da memória

Tabela de dados na memória
Referências
44




STALLINGS, W. Arquitetura e Organização de Computadores, 8ed.
Pearson Education, 2009.
DUNCAN, R. Advanced MS-DOS Programming. Microsoft Press,
1986.
IA-32 Intel Architecture Software Developer’s Manual. Intel Press,
2005.
HYDE, R. Art of Assembly Language Programming and HLA. No
Starch Press, 2003.

http://en.wikipedia.org/wiki/X86_assembly_language

Turbo Assembler Help. Borland, 1996.
Perguntas e Discussão
45

Dúvidas mailto:[email protected]
Download

5596.9 arquitetura de computadores programação