Title: 5596.9 ARQUITETURA DE COMPUTADORES PROGRAMA
15596.9 ARQUITETURA DE COMPUTADORES PROGRAMAÇÃO
ASSEMBLY NA ARQUITETURA X86
- Aécio Fróes / CP05241-67 / gaerity_at_gmail.com.
Bolsista CNPq/PIBIT - LACMO Aprendizado Computacional e Métodos de
Otimização
2Visão geral
- 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
3Motivação
- Sistemas operacionais
- 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) - 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
- Compiladores, Montadores (Assemblers), Linkers
- Rotinas de alto desempenho em aplicações
- Sistemas gráficos, jogos de computador,
criptografia
4Aplicações reais
- Initial Program Loader do QNX RTOS
(http//www.qnx.com) - bootsect.s do Linux (http//tldp.org/HOWTO/Linux-i
386-Boot-Code-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)
5Introdução
- 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-para-um 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 ATT. Não é case sensitive
6Arquitetura x86
- 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
7Arquitetura x86
- Diagrama de blocos do 8086
8Arquitetura x86
- 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
9Arquitetura x86
- 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
10Arquitetura x86
11Arquitetura x86
- 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
12Arquitetura x86
- Tipos de dados fundamentais
13Arquitetura x86
- Organização dos dados na memória
14Arquitetura x86
15Ferramentas de programação
- 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
16Processo de programação
- 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) - edit relogio.asm
- Passo 2 montagem através de um assembler, que
produzirá, em caso de sucesso, um ou mais
arquivos objeto (extensão .obj) - 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
17Diretivas do Turbo Assembler
- .8086P
- Habilita montagem das instruções do processador
8086 e do co-processador 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).
18Diretivas do Turbo Assembler
- .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)
19Diretivas do Turbo Assembler
- .CODE
- Inicia ou continua o segmento de código do
módulo, quando utilizada com a diretiva .MODEL - .DATA
- 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).
20Diretivas do Turbo Assembler
- 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.
21Diretivas do Turbo Assembler
- 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. . . '
22Diretivas do Turbo Assembler
- PROC nome
- Define o início de uma procedure e associa um
nome - ENDP nome
- Marca o fim de uma procedure (PROC)
- MACRO nome
- Define uma macro que será expandida depois quando
o seu nome é encontrado - ENDM nome
- Termina uma definição de macro
- _at_data
- Segmento que DS deve assumir quando é utilizada a
diretiva .DATA
23Instruções da arquitetura x86
- 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 AH0
- 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
24Instruções da arquitetura x86
- ADC adição com carry flag
- Sintaxe ADC memóriaregistrador,
memóriaregistradorimediato - 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óriaregistrador,
memóriaregistradorimediato - Função adiciona o primeiro operando e o segundo,
armazenando o resultado no primeiro operando.
Exemplo - ADD AX,AX AX AXAX
25Instruções da arquitetura x86
- AND AND lógico
- Sintaxe AND memóriaregistrador,
memóriaregistradorimediato - 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óriaregistradorimediato
- Função chamada de função ou subrotina. Armazena
CSIP 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
26Instruções da arquitetura x86
- 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óriaregistrador,
memóriaregistradorimediato - 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 DXAX, considerando o bit de sinal em AX
27Instruções da arquitetura x86
- DEC decremento de 1
- Sintaxe DEC registradormemó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 registradormemória
- Função se o operando é de 8 bits, AL AX /
operando e AH AX operando, e se é de 16 bits,
AX DXAX / operando e DX DXAX 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
28Instruções da arquitetura x86
- 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 ALAX, DXimediato 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 registradormemó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
29Instruções da arquitetura x86
- 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
- JXXJNXX deslocamento condicional
- Sintaxe JXXJNXX 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.
30Instruções da arquitetura x86
- JXXJNXX deslocamento condicional
- JA jump se acima (operador gt sem sinal)
- JAE jump se maior ou igual (operador gt sem
sinal) - JB jump se abaixo (operador lt sem sinal)
- JBE jump se abaixo ou igual (operador lt sem
sinal) - JE jump se igual (operador )
- JG jump se maior (operador gt com sinal)
- JGE jump se maior ou igual (operador gt com
sinal) - JL jump se menor (operador lt com sinal)
- JLE jump se menor ou igual (operador lt 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
31Instruções da arquitetura x86
- JMP deslocamento incondicional
- Sintaxe JMP deslocamento imediatomemória 16
bitssegmentooffset - 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,BX2 SI 4042H
- MOV mover dados
- Sintaxe MOV registradormemória,
registradormemóriaimediato - Função copiar o segundo operando para o primeiro
operando. Exemplo - MOV BP10H, CL
32Instruções da arquitetura x86
- MUL Multiplicação sem sinal
- Sintaxe MUL registradormemória
- Função se o operando é de 8 bits, AL AX /
operando e AH AX operando, e se é de 16 bits,
AX DXAX / operando e DX DXAX operando.
Com resultados sem tratar o bit MSB como sendo de
sinal - NEG negação pelo complemento de 2
- Sintaxe NEG registradormemó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
33Instruções da arquitetura x86
- NOT negação pelo complemento de 1
- Sintaxe NOT registradormemó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 registradormemória,
registradormemóriaimediato - 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
34Instruções da arquitetura x86
- OUT escreve um valor em uma porta de E/S
- Sintaxe OUT DXimediato, AXAL
- 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 registradormemória
- Função salva o operando de 16 bits na pilha (SP
SP-2, SSSP operando) - POP restaura uma word da pilha
- Sintaxe POP registradormemória
- Função restaura para o operando o valor de 16
bits do topo da pilha (operando SSSP, SP
SP2) - PUSHF salva o registrador de flags na pilha
- POPF restaura o registrador de flags da pilha
35Instruções da arquitetura x86
- 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 registradormemória, 1CL
- 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
36Instruções da arquitetura x86
- SBB subtração com empréstimo (carry)
- Sintaxe SBB registradormemória,
registradormemóriaimediato - 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 (IF1)
- Sintaxe STI
- Função ativa o flag de interrupção, ativando
assim as interrupções - SUB subtração
- Sintaxe SUB registradormemória,
registradormemóriaimediato - 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
37Instruções da arquitetura x86
- TEST comparação lógica
- Sintaxe TEST registradormemória,registradormemó
riaimediato - 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 registradormemória,registradormemór
iaimediato - 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
38API do MS-DOS e BIOS IBM PC
- 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
39API do MS-DOS e BIOS IBM PC
- 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 00000417H)
40API do MS-DOS e BIOS IBM PC
- 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
41API do MS-DOS e BIOS IBM PC
- 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
(CTRLC) - Chamada AH 08H
- Retorna AL código ASCII do caractere
42API do MS-DOS e BIOS IBM PC
- INT 21H API do MS-DOS
- Função 09H exibe string
- Chamada AH 09H, DSDX segmentooffset da
string - Retorna nada
- Função 0AH entrada bufferizada do teclado
- Chamada AH 0AH, DSDX segmentooffset 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.)
43Exemplos de código-fonte
- 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
44Referências
- 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 Developers
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.
45Perguntas e Discussão
- Dúvidas mailtogaerity_at_gmail.com