Assembly na arquitetura IA-32 com NASM no Linux



Documentos relacionados
Assembly x86. Hugo Bessa - hrba Paulo Serra Filho ptvsf

A linguagem ASSEMBLY

How to write Shellcodes por Luiz Fernando Camargo

Introdução à Arquitetura e Linguagem Assembly de Processadores IA-32

CAPÍTULO 7 NÍVEL DE LINGUAGEM DE MONTAGEM

PROJETO LÓGICO DE COMPUTADORES Prof. Ricardo Rodrigues Barcelar

MC404 - Organização de Computadores. e Linguagem de Montagem Instituto de Computação. Universidade Estadual de Campinas

Arquitetura de Computadores. Prof. João Bosco Jr.

UNIVERSIDADE FEDERAL DO RIO GRANDE DO SUL INSTITUTO DE INFORMÁTICA INFORMÁTICA APLICADA

Projeto 1 - Bootloader

Sistemas Operacionais II

5 Apresentando a linguagem C

Programação de Computadores III

ALP Algoritmos e Programação. . Linguagens para Computadores

Usando o simulador MIPS

Linguagem de Montagem

ARQUITETURA DE COMPUTADORES. Rogério Spindula Rosa

TE11008 Arquitetura e Organização de Computadores Nível da Linguagem de Montagem p. 1

Gerenciador de Boot Simples

Arquiteturas RISC. (Reduced Instructions Set Computers)

Linguagem de Montagem 2. Operações e Operandos

ARQUITETURA DE COMPUTADORES INTRODUÇÃO

LP II Estrutura de Dados. Introdução e Linguagem C. Prof. José Honorato F. Nunes honorato.nunes@ifbaiano.bonfim.edu.br

Computadores de Programação (MAB353)

Introdução à Arquitetura de Computadores

Programação online em Java

Sistemas de Computação

Entradas/Saídas. Programação por interrupções Conceitos gerais Programação da porta série Transmissão

Software Básico (INF1018)

Programação Estruturada. Programação Estruturada. Idéias Básicas da Programação Estruturada

15 a Aula Subprogramação /Subalgoritmos Função e Procedimento

Sistemas de Computação para Controle e Automação CIC132. Assembly. Assembly. Notas. Décima quarta aula: Introdução a programação Assembly

Software Básico. nível de linguagem de montagem (assembly) Tanembaum, capítulo 7

1. SINTAXE DA LINGUAGEM ASSEMBLY

file.j. a Baseado no Jasmin User Guide. (

Introdução ao FORTRAN (Parte I)

PROJETO LÓGICO DE COMPUTADORES Prof. Ricardo Rodrigues Barcelar

Programação de Computadores. Professor Ilaim Costa Junior

Projeto de Banco de Dados

2 SYSCALLs: O que são

Geração de código. Ivan Ricarte INTRODUÇÃO À COMPILAÇÃO

Arquitetura do SET de instruções Instruction SET. CISC vs RISC. What s assembly as to do with it?

8. Instruções de multiplicação e divisão

Unidade 10: A Unidade Lógica Aritmética e as Instruções em Linguagem de Máquina Prof. Daniel Caetano

Programação de Computadores IV. Introdução a Linguagens de Programação Simone Martins SLIDES CEDIDOS POR BRUNO MARQUES 1

3. O NIVEL DA LINGUAGEM DE MONTAGEM

3 Introdução às chamadas ao sistema

Ambiente de desenvolvimento de Programação Assembly MCU 8051 IDE

IFPE. Disciplina: Sistemas Operacionais. Prof. Anderson Luiz Moreira

Organização de Computadores 1

CAPÍTULO 3 NÍVEL ISA. 3.1 Introdução ao Nível de Arquitetura do Conjunto de Instruções

Componentes do Computador e. aula 3. Profa. Débora Matos

Organização de Computadores Software

Sistema Operacional Ex: Complexo Computador multiusuário com vários terminais Tem que administrar todos os pedidos de usuários e assegurar que eles

Conceitos básicos da linguagem C

RISC - Reduced Instruction Set Computer

Arquitectura de Computadores II. Medição de desempenho

Figura 01 Kernel de um Sistema Operacional

Sistemas Operacionais

Capítulo 7 Nível da Linguagem Assembly

2 echo "PHP e outros.";

Parte II Introdução a Linguagens de Programação

Prof. Marcos Ribeiro Quinet de Andrade Universidade Federal Fluminense - UFF Pólo Universitário de Rio das Ostras - PURO

Introdução aos Computadores

cast poderia ser usado também para transformar um real (float) em inteiro. A sintaxe C (float)i pode ser substituída em C++ por float(i).

PCS-2302 / PCS-2024 Lab. de Fundamentos de Eng. de Computação

Protótipo de Gerador de Código Executável no Ambiente FURBOL

Orientação a Objetos

Organização e Arquitetura de Computadores I

NOTAS DE AULA Prof. Antonio Carlos Schneider Beck Filho (UFSM) Prof. Júlio Carlos Balzano de Mattos (UFPel) Arquitetura de Von Neumann

Componentes da linguagem C++

Tutorial de Matlab Francesco Franco

Estrutura de Dados. Introdução a Ponteiros. Prof. Gerson Borges Estrutura de Dados I 1

Nível da Arquitetura do Conjunto das Instruções

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

Exceções no Fluxo de Execução: Interrupções e Traps

Tais operações podem utilizar um (operações unárias) ou dois (operações binárias) valores.

Arquitetura de Computadores. Tipos de Instruções

LINGUAGENS E PARADIGMAS DE PROGRAMAÇÃO. Ciência da Computação IFSC Lages. Prof. Wilson Castello Branco Neto

Conceitos de Sistemas Operacionais: Chamadas de Sistema. Prof Rafael J. Sandim

Capítulo 12. SUB-ROTINAS

MC-102 Aula 01. Instituto de Computação Unicamp

34 dígitos 28 dígitos 62 dígitos significativos! (base 10!)

Análises Geração RI (representação intermediária) Código Intermediário

Fundamentos de Programação II. Introdução à linguagem de programação C++

Curso: Ciência da Computação Disciplina: Construção de Compiladores Período: Prof. Dr. Raimundo Moura

Armazenamento de Dados. Prof. Antonio Almeida de Barros Junior

Introdução ao Processamento de Imagens com o IRIS Por Rodolfo Barros

4-1. Parte2: A Arquitetura do Conjunto de Instruções

RECUPERAÇÃO DE CONTEÚDO BANCO DE DADOS

O Processo de Programação

Chamadas Remotas de Procedimentos (RPC) O Conceito de Procedimentos. RPC: Programa Distribuído. RPC: Modelo de Execução

Introdução à Programação

Descrição e análise da implementação em Assembly MIPS da função itoa

Transcrição:

Assembly na arquitetura IA-32 com NASM no Linux Prof. Dr. Luciano José Senger 1 Introdução A Figura 1 mostra os registradores principais para a arquitetura IA-32. Essa arquitetura trabalha com palavras de 32 bits e estende os registradores de 16 bits (da arquitetura do 8088) para registradores de 32 bits. Por exemplo, o registrador AX é estendido para o registrador EAX. Figura 1: Registradores IA-32 2 Montagem do programas em Assembly no Linux O quadro a seguir mostra os comando para a montagem e linkedição de programas no Linux, para um programa chamado de program: Montagem e linkediç~ao nasm -f elf -o program.o program.asm ld -o program program.o Note que o comando -f especifica o formato do arquivo executável, que neste caso será o elf, padrão do sistema Linux. Quando são usadas bibliotecas externas (p.e. stdio, stdlib), a linkedição é feita da seguinte forma: Linkediç~ao ld -dynamic-linker /lib/ld-linux.so.2 -lc -o program program.o O quadro a seguir mostra um exemplo de programa em assembly para o Linux. Note que estão sendo usados registradores de 32 bits. Responda: 1. Qual é o registrador utilizado pelo kernel do Linux para selecionar a função de escrita de string em tela? 2. Ao contrário do DOS, que trabalha com o serviço 21h, qual é o número de serviço do Linux? 3. Para que serve a diretiva $, encontrada na seção de dados do programa? 1

Montagem section.data hello: db Hello world!,10 ; Hello world! plus a linefeed character hellolen: equ $-hello ; Length of the Hello world! string ; (I ll explain soon) section.text global _start _start: mov eax,4 mov ebx,1 mov ecx,hello mov edx,hellolen mov eax,1 mov ebx,0 ; The system call for write (sys_write) ; File descriptor 1 - standard output ; Put the offset of hello in ecx ; hellolen is a constant, so we don t need to say ; mov edx,[hellolen] to get it s actual value ; Call the kernel ; The system call for exit (sys_exit) ; Exit with return code of 0 (no error) Esse arquivo, se salvo com o nome helloworld.asm, pode ser montado e linkeditado da seguinte forma: Montagem e linkediç~ao nasm -f elf -o helloworld.o helloworld.asm ld -o helloword helloworld.o Empregando o comando nm, pode-se obter a lista de símbolos do programa: o comando nm nm helloworld.o A saída deste comando é: 080490b1 A bss_start 080490b1 A _edata 080490b4 A _end 08048080 T _start 080490a4 d hello 0000000d a hellolen saída do comando nm Responda : Oque significam as informações obtidas? (dica: use o comando man nm) para consultar a página de manual do comando nm. A seguir, tem se o resultado da execução do comando: comando objdump objdump -d helloworld Pode-se verificar o código em assembly (nesse caso o GAS, padrão em sistemas UNIX) e os códigos em linguagem de máquina para as instruções: saída do comando objdump helloworld: file format elf32-i386 Disassembly of section.text: 08048080 <_start>: 8048080: b8 04 00 00 00 mov $0x4,%eax 8048085: bb 01 00 00 00 mov $0x1,%ebx 804808a: b9 a4 90 04 08 mov $0x80490a4,%ecx 804808f: ba 0d 00 00 00 mov $0xd,%edx 8048094: cd 80 int $0x80 8048096: b8 01 00 00 00 mov $0x1,%eax 804809b: bb 00 00 00 00 mov $0x0,%ebx 80480a0: cd 80 int $0x80 Responda: Quais são as principais diferenças da sintaxe do GAS em relação ao NASM? 2

2.1 Obtendo os argumentos da linha de comando A pilha tem uma função importante em sistemas Linux: a comunicação do sistema operacional com o programa em execução. Através da pilha, os argumentos são passados ao programa para o processamento. Considere a execução do programa abaixo imprimemsg que recebe como parâmetro a string Ola: imprimemsg Ola 5 Nesse caso a, configuração da pilha é a seguinte: 4 ; quantidade de argumentos imprimemsg; nome do programa Ola ; primeiro argumento 5 ; segundo argumento O programa imprimemsg está listado a seguir: section.data linebreak db 10 section.text global _start O programa imprimemsg _start: mov ebp, esp mov eax,4 mov ebx,1 mov ecx, [ebp+8] mov edx, 3 ; Call the kernel mov eax,4 mov ebx,1 mov ecx, linebreak mov edx, 1 mov eax,1 mov ebx,0 ; Exit Exercício: Modifique o programa anterior para que o mesmo imprima em tela todos os parâmetros recebidos pelo programa, e não apenas o primeiro argumento. Salve este programa como imprimemsg2.asm. 2.2 Verificando em tempo de execução as chamadas de sistema O comando strace inicia a execução do programa passado como parâmetro e mostra em tela uma listagem de todas as chamadas de sistema invocadas pelo programa: Assim, o comando: O comando strace strace./imprimemsg Olateste 5 produz como resposta: Listagem obtida com o comando strace execve("./imprimemsg", ["imprimemsg", "Olateste", "5"], [/* 33 vars */]) = 0 write(1, "Olate", 5Olate) = 5 write(1, "\n", 1 ) = 1 _exit(0) =? 2.3 Utilização de macros Note no exemplo anterior a repetição no uso da syscall write. Através do uso de macro, fragmentos de código frequentemente usados podem ser definidos como macros, inclusive com parâmetros. Responda: Quais são as vantagens e desvantagens de macros em relação aos procedimentos? 3

resposta Um exemplo do uso de macros para facilitar o acesso à syscalls é mostrado a seguir. As macros são definidas nas linhas 16 e 27. Um exemplo do uso no programa principal pode ser visto na linha 42. macros 1 section.data 2 prompt_str db Enter your name: 3 STR_SIZE equ $ - prompt_str 4 5 greet_str db Hello 6 7 8 GSTR_SIZE equ $ - greet_str 9 10 11 section.bss 12 13 ; Reserve 32 bytes of memory 14 buff resb 32 15 16 ; A macro with two parameters 17 ; Implements the write system call 18 %macro write 2 19 mov eax, 4 20 mov ebx, 1 21 mov ecx, %1 22 mov edx, %2 23 24 %endmacro 25 26 27 ; Implements the read system call 28 %macro read 2 29 mov eax, 3 30 mov ebx, 0 31 mov ecx, %1 32 mov edx, %2 33 34 %endmacro 35 36 37 section.text 38 39 global _start 40 41 _start: 42 write prompt_str, STR_SIZE 43 read buff, 32 44 45 ; Read returns the length in eax 46 push eax 47 48 ; Print the hello text 49 write greet_str, GSTR_SIZE 50 51 pop edx 52 53 ; edx = length returned by read 4

54 write buff, edx 55 56 _exit: 57 mov eax, 1 58 mov ebx, 0 59 3 Procedimentos Na linguagem Assembly, procedimentos são invocados através da instrução CALL, seguida de um rótulo. Por exemplo, CALL R1 desvia a execução para o rótulo R1. O endereço de retorno no término do procedimento é armazenado na pilha, e através da instrução RET, o retorno é executado. Existem três formas de passar parâmetros para procedimentos: registradores, variáveis globais e através da pilha. Registradores e variáveis globais não são adequados, se for necessário a passagem de um número variável de parâmetros ou quando é necessário que o procedimento seja invocado por ele mesmo, em chamadas recursivas. Assim, geralmente a passagem de parâmetros pela pilha é mais utilizada, tanto em programas escritos em Assembly como linguagens de alto nível, como C, Fortran e Pascal. Como exemplo, suponha que um procedimento chamado Imul2 calcula a multiplicação entre dois inteiros que foram inseridos na pilha e retorna o resultado em EAX: 1 push VarA ; dword 2 push VarB ; dword 3 call Imul2 4 add ESP, 8 Assume-se que o procedimento não afeta a pilha, de forma que ao fim de sua execução, o ponteiro da pilha ESP referencia a mesma posição antes da chamada. Isso explica a operação add ESP,8, que é necessária para restaurar o valor inicial do ESP, pois cada uma das variáveis têm 16 bits de tamanho. Esse método é chamado como restauração da pilha pelo código que invocou a chamada (stack restored by the caller) e utilizado pela maioria dos compiladores C/C++. A convenção adotada na linguagem C/C++ é empilhar os parâmetros na ordem inversa em que aparacem na declaração da função (da direita para a esquerda). O código do procedimento pode ser escrito então: 1 Imul2: 2 push ebp 3 mov ebp, esp 4 mov eax, [ebp+12] 5 Imul eax, [ebp+8] 6 pop ebp 7 ret O primeiro parâmetro está na posição ESP+8. A longo da execução da função/procedimento o valor de ESP pode variar. Por isso, utiliza-se um outro registrador, EBP, para referenciar a base da pilha durante toda a execução da função/procedimento. A porção da pilha referente a cada função/procedimento é chamada de registro de ativação. A Figura 2 mostra o conteúdo da pilha para esse exemplo. Figura 2: Exemplo de registros de ativação Assim, ebp referencia sempre a base do registro de ativação corrente. Na medida que os procedimentos são invocados, a pilha de execução cresce. Além dos endereços de retorno, é comum cada procedimento usar a pilha para armazenar variáveis locais. A figura 3 ilustra os registros de ativação para uma chamada encadeada de procedimentos. Seguindo tais convenções, pode-se unir o código escrito em Assembly com código escrito na linguagem C. Tal ligação é comum no desenvolvimento de software básico, como por exemplo o software de um sistema operacional. 5

4 Utilização de bibliotecas externas Figura 3: Exemplo de registros de ativação O quadro a seguir mostra um exemplo de utilização de rotinas externas: Exemplo de utilizaç~ao de bibliotecas externas 1 section.data 2 3 ; Command table to store at most 4 ; 10 command line arguments 5 cmd_tbl: 6 %rep 10 7 dd 0 8 %endrep 9 10 section.text 11 12 global _start 13 14 _start: 15 ; Set up the stack frame 16 mov ebp, esp 17 ; Top of stack contains the 18 ; number of command line arguments. 19 ; The default value is 1 20 mov ecx, [ebp] 21 22 ; Exit if arguments are more than 10 23 cmp ecx, 10 24 jg _exit 25 26 mov esi, 1 27 mov edi, 0 28 29 ; Store the command line arguments 30 ; in the command table 31 store_loop: 32 mov eax, [ebp + esi * 4] 33 mov [cmd_tbl + edi * 4], eax 34 inc esi 35 inc edi 36 loop store_loop 37 38 mov ecx, edi 39 mov esi, 0 6

40 41 extern puts 42 43 print_loop: 44 ; Make some local space 45 sub esp, 4 46 ; puts function corrupts ecx 47 mov [ebp - 4], ecx 48 mov eax, [cmd_tbl + esi * 4] 49 push eax 50 call puts 51 add esp, 4 52 mov ecx, [ebp - 4] 53 inc esi 54 loop print_loop 55 56 jmp _exit 57 58 _exit: 59 mov eax, 1 60 mov ebx, 0 61 Salve o programa como readargs.asm. Realize a montagem e linkedição, lembrando de especificar na linkedição a biblioteca externa. Verifique você mesmo: 1. use os comandos nm e objdump para verificar as informações detalhas sobre o arquivo objeto; 2. use o comando strace para verificar as chamadas de sistema empregadas. 4.1 Diferenças entre o IA-32 e a arquitetura MIPS em relação aos procedimentos Como a arquitetura IA-32 tem menos registradores de propósito geral, tal arquitetura não pode convencionar alguns registradores específicos para isso conforme existe na arquitetura MIPS. A quantidade menor de registradores da arquitetura IA-32 implica em uma maior utilização da pilha na passagem de parâmetros e no para salvamento de valores de registradores. 7