Aula 13 – Assembly 2 – Para novatos
Transcrição
Aula 13 – Assembly 2 – Para novatos
Aula 13 – Assembly 2 – Para novatos Anderson L. S. Moreira [email protected] http://dase.ifpe.edu.br/~alsm Anderson Moreira Arquitetura de Computadores 1 O que fazer com essa apresentação Anderson Moreira Arquitetura de Computadores 2 Escrevendo um simples programa Começando com o básico, o aluno se familiariza com a linguagem; Assembly, precisa de dedicação e esforço de lógica; Não compare Assembly com outras linguagens de programação, como C e Java (essa então nem tente associar!!!) Anderson Moreira Arquitetura de Computadores 3 Introdução Um programa contém instruções que serão usadas pelo processador do computador; As instruções são chamadas de código do programa; O processador executa as instruções de código, uma por uma - é por isso que o programa é chamado de executável; Quando o programa for carregado, o SO dá ao processador o endereço a partir do código onde a execução deve começar; Daquele ponto em diante, cabe ao programa para desviar a execução para o local correto em seu código. Anderson Moreira Arquitetura de Computadores 4 Introdução O que o código realmente faz? • Uma coisa que faz é mover números de e para os registradores dentro do processador; • Existem sete destes para uso geral; • Cada registro tem 32 bits de dados; • Chamado um dword (literalmente uma palavra dupla). Cada bit é ligado ou desligado (um ou zero) a qualquer momento; • Este é um número binário. Em 32 bits, se todos os bits estejam acionados, o número é 4294967295D Anderson Moreira Arquitetura de Computadores 5 Introdução Existem também várias instruções aritméticas que podem ser realizadas pelo processador (ULA); Outra coisa que o código faz é passar os números dos registradores da memória e da memória para os registradores, ou colocar números na memória stack (pilha). Anderson Moreira Arquitetura de Computadores 6 Introdução A pilha é como um prato quente. Coloca um dword na pilha usando a instrução PUSH e remove o último dword colocado na pilha usando uma instrução POP; A memória RAM (memória de acesso aleatório) é a de referência na pilha, dentro do computador; A pilha é reservado pelo sistema quando o programa carrega. Dependendo de suas instruções de dados, outra memória é reservada pelo sistema quando o programa carrega. Esta memória é chamada de dados de memória, terá de ser solicitado pelo programa em tempo de execução. Anderson Moreira Arquitetura de Computadores 7 E no sistema Windows? No SO Windows uma das coisas mais importantes que as instruções de código fazem é chamar uma função de janela, ou seja, para desviar a execução para essa função; As funções do Windows são chamadas APIs (Application Programmer's Interface). A maioria das instruções de código seja utilizado para se preparar para essas chamadas e lidar com o resultado das chamadas; São estas as chamadas para APIs que darão aos programas a funcionalidade Janelas, desta forma oferece acesso a uma vasta gama de processos que resultam em interação com o usuário; Anderson Moreira Arquitetura de Computadores 8 O processo de Construção (build) GoAsm - assembler. Este programa tem a sua fonte de script e converte-o em um arquivo objeto. Tradicionalmente, a extensão seria . Asm. A fonte de script contém as linhas de código-fonte que contém o código e as instruções de dados que foram gravados para o programa. O arquivo objeto, pode ser lido pelo linker e que é utilizado para criar o executável final. Gorc - compilador. Este programa tem o seu script de recursos e converte-lo em um arquivo .res. O script de recursos é outro arquivo de texto simples, mas que contém instruções para estabelecer os controles do Windows - menus, diálogos, ícones, bitmaps e stringtables. Tradicionalmente, teria a extensão .rc. O arquivo res está codificado, e é lido pelo linker. GoLink - vinculador. Este programa tem os arquivos de um ou mais objetos e um res e cria o executável final. GoBug - depurador. Com esta ferramenta, o programa executar cada instrução por vez e ver como cada instrução afeta os registradores e as áreas de memória. Anderson Moreira Arquitetura de Computadores 9 O processo de construção pode ser resumido .asm .obj .exe .rc .res Anderson Moreira Arquitetura de Computadores 10 Criando um programa em branco Anderson Moreira Arquitetura de Computadores 11 Qual a funcionalidade disso? A funcionalidade é criar um programa que carrega, executa e termina sem fazer nada; Isto é para demonstrar o processo de construção e para explicar mais algumas coisas. Anderson Moreira Arquitetura de Computadores 12 Passo 1 Chame o RadASM Crie um novo projeto (Arquivo → Projeto Novo) Será executado o assistente de criação; Escolha conforme figura: Assemblador → GoASM Tipo de projeto → Console Nome do projeto → nada Clique no botão PROXIMO Anderson Moreira Arquitetura de Computadores 13 Passo 2 o Escolha na tela seguinte o tipo NONE; o Clique no botão PROXIMO; o Em criação de Arquivos, deixe apenas as opções ASM e BAK habilitadas; o Na próxima tela clique no botão FINAL. Anderson Moreira Arquitetura de Computadores 14 Passo 3 Clique na aba de Projetos, escolha a pasta Assembly e duplo clique no arquivo “nada.asm” Note que o RadASM já ajuda a organizar o seu trabalho, deixando cada um dos arquivos em uma pasta diferente. Anderson Moreira Arquitetura de Computadores 15 Passo 4 Digite o seguinte código Este é o programa. .code diz ao assembler que o que se segue são as instruções de código; start: é uma etiqueta de código (label). Ele também informa o vinculador que este é o lugar onde a execução do programa deve começar; ret é uma instrução do processador mnemônica, que informa ao processador para retornar para o chamador do código (que neste caso vai ser o próprio Windows. Anderson Moreira Arquitetura de Computadores 16 Passo 5 Escolha o menu Montar Assemble Vai aparecer algumas mensagens como a seguir: GoAsm.Exe Version 0.56.7 - Copyright Jeremy Gordon 2001/9 - [email protected] Output file: nada.obj Make finished. Total compile time 16 ms Depois escolha o mesmo menu Montar Link C:\RadAsm\GoAsm\BIN\GoLink.EXE /console "nada.obj"  GoLink.Exe Version 0.26.10 - Copyright Jeremy Gordon 2002/9 - [email protected] Output file: nada.exe Format: win32 size: 1,024 bytes Make finished. Total compile time 10577 ms Observe que a própria console mostra o comando executado, que pode ser feita diretamente pelo CMD do Windows. Anderson Moreira Arquitetura de Computadores 17 Passo 6 Após esse processo vamos executar nosso programa. Pode ser pelo menu Montar e após escolher Run, ou escolher Ferramentas Goto Dos (essa segunda opção é mais apropriada para a situação); Então digite nada, na linha de comando. O que irá acontecer? Anderson Moreira Arquitetura de Computadores 18 Conclusão Note que na verdade não acontece o que o nome diz “nada”; O prompt do DOS irá apenas mover para baixo uma linha; Mas o Windows estava muito feliz com este programa parabéns você fez o seu primeiro programa Assembler Windows! Anderson Moreira Arquitetura de Computadores 19 Criando um programa Ola Mundo Anderson Moreira Arquitetura de Computadores 20 Passo 1 Os passos iniciais são semelhantes ao programa anterior; A diferença é que o nome do projeto será tads; Digite o seguinte código no arquivo tads.asm: Anderson Moreira Arquitetura de Computadores 21 Passo 2 A diferença é que na execução do Link (vinculador), execute a opção Goto Dos e execute: C:\RadAsm\GoAsm\BIN\GoLink.EXE /console tads.obj kernel32.dll Aqui, tem incluído a opção kernel32.dll na linha de comando do GoLink; Isto diz ao vinculador GoLink ,olhar para o arquivo kernel32.dll do sistema Windows quando liga o arquivo para qualquer incógnitas, neste caso, o Windows APIs GetStdHandle e WriteFile e que são necessárias para a execução do programa. Anderson Moreira Arquitetura de Computadores 22 Dissecando o programa Vamos por cada parte do programa: Anderson Moreira Arquitetura de Computadores 23 Parte 1 .data PALAVRA dd 0 “.data" diz ao assembler que uma instrução de dados ou instruções seguem. Também pode digitar DATA SECTION; “PALAVRA" é um rótulo de dados que é um nome que indica um lugar especial nos dados. “dd" cria um dword (4 bytes) de dados (literalmente, "declare dword"). "0" inicializa o dword para um valor, neste caso, zero. Anderson Moreira Arquitetura de Computadores 24 Parte 2 .code start: push -11 CALL GetStdHandle “.code” e “start” que visto antes. Sendo que posso digitar CODE SECTION; “push” coloca um valor na pilha. O valor neste caso é -11 (expresso como um número decimal ordinário). Isso é empurrado para a pilha pronta para enviar para a chamada API como um parâmetro. "CALL" transfere a execução de um processo, neste caso, a API do Windows é GetStdHandle. Esta API tem um parâmetro e retorna um identificador no registrador EAX para se adequarem. Aqui ele trata com o valor -11 que é o identificador de saída padrão para o console. O console é a interface com o usuário, que neste caso será a janela de MS-DOS (também conhecido como "comando" ou prompt. Anderson Moreira Arquitetura de Computadores 25 Parte 3 push push push CALL 0,addr PALAVRA 11,'ola mundo' eax WriteFile Aqui o SO empurra os parâmetros prontos para a chamada à API do Windows WriteFile; Esta API escreve para o identificador passado para ela no último parâmetro (ainda detidas no registrador EAX); Ela escreve a string que é de 11 caracteres. Também passa o endereço de PALAVRA que era o dado DWORD feita anteriormente; Isso é necessário porque WriteFile irá reportar em dword quantos caracteres ele realmente escreve. Anderson Moreira Arquitetura de Computadores 26 Parte 4 mov ret eax,0 Aqui passa o valor 0 no registrador EAX (para indicar um retorno bem-sucedido) e, em seguida, use RET para retornar ao sistema (fechando o programa); Libera memória. Anderson Moreira Arquitetura de Computadores 27 Conhecendo o seu programa O que compõe um programa em assembler Anderson Moreira Arquitetura de Computadores 28 O que é um programa sem recursos? Arquivo .asm Arquivo .exe ou .dll Arquivo .obj Anderson Moreira Arquitetura de Computadores 29 O que é um programa com recursos? Arquivo .asm Arquivo .obj Arquivo .exe ou .dll Arquivo .rc Arquivo .res Anderson Moreira Arquitetura de Computadores 30 Recursos Os recursos (resources) são mantidos separadamente para facilitar a programação; São principalmente o conteúdo de menus e janelas, mas também coisas como bitmaps, cursores e ícones; Normalmente, um programa do tipo console não inclui recursos, uma vez que não faz uso de recursos gráficos do SO; Um programa que usa o Windows GUI (Graphics User Interface) provavelmente irá utilizar os recursos (mas não precisa). Anderson Moreira Arquitetura de Computadores 31 Arquivo .asm Este é um arquivo que pode ser criado e editado usando um editor de texto comum, como vim ou context; Se usar o Notepad ou Wordpad deve certificar de salvar o arquivo em um formato que não acrescenta qualquer controle ou a formatação de caracteres, diferente da habitual; Isso é válido porque as ferramentas de desenvolvimento só olha para o texto. Se não usar uma extensão para o arquivo, o editor pode dar um nome “. Txt”; Anderson Moreira Arquitetura de Computadores 32 Arquivo .asm É tradicional entre os programadores para dar a sua fonte scripts uma extensão que corresponde a língua em que o código-fonte é escrito; Por exemplo, você pode ter um montador arquivo chamado “meuprog.asm". Da mesma forma que normalmente irá encontrar o código-fonte escritos na "linguagem C", com a extensão “. c” ou “. cpp” para C++, “.pas” para pascal e assim por diante. No entanto, não há mágica em essas extensões. O Assembler aceita arquivos de qualquer extensão. O arquivo .asm contém as instruções para o processador de palavras e números. Estes são executados pelo processador quando o programa é executado. Portanto, que o asm, contém o código-fonte ou o “script de fonte”; Quando está pronto para fazer o programa, o GoASM converte arquivos .asm para os arquivos .obj. Anderson Moreira Arquitetura de Computadores 33 Arquivo .obj Este é um arquivo feito pelo Assembler de um arquivo .asm; O Assembler tem as instruções no arquivo ASM. Que estão em palavras e números e os converte em formato de objeto COFF que é um formato que o vinculador espera; O Assembler concatena todo o seu código e as instruções de dados em código-fonte e coloca-os em código e seções de dados no arquivo .obj; A seção de código contém as instruções do processador real (opcodes) que o processador executa quando o programa é executado. Anderson Moreira Arquitetura de Computadores 34 Arquivo .obj A seção de dados contém informações que serão mantidos na memória enquanto o programa é executado; Não pode realmente executar um arquivo .obj como um programa, porque não está no formato do programa final esperado pelo SO (o formato PE); Passa o arquivo .obj para o vinculador, quando está pronto para fazer o programa; Às vezes o arquivo .obj é chamado um arquivo “binário” ou “bin”. Isso ocorre porque o arquivo agora contem apenas números; Mas se olhar para dentro de um arquivo .obj verá as seqüências de caracteres que estavam no script de origem. Anderson Moreira Arquitetura de Computadores 35 Arquivo .rc Este é um outro arquivo de texto que faz usando um editor de texto; Este arquivo fornecer as instruções em palavras e números, que o SO usa para fazer os recursos (principalmente menus, diálogos e stringtables) em seu programa quando ele é executado; Também pode usar o arquivo .rc para nomear os arquivos que devem ser carregados no .res quando o compilador de recursos é executado (como, por exemplo, os ícones bitmaps e cursores); O arquivo .rc pode ser descrito como contendo material de origem; Para criar esse arquivo se utiliza o compilador de recursos GoRC. Anderson Moreira Arquitetura de Computadores 36 Arquivo .res Este é um arquivo feito pelo compilador de recursos a partir de um arquivo .RC; O recurso formado pelo compilador e as instruções do arquivo .rc que estão em palavras e números e os converte em uma forma pronta para a inserção na seção de recursos de um arquivo .exe; Passa o .res do vinculador (linker) quando está pronto para fazer o programa. Anderson Moreira Arquitetura de Computadores 37 Arquivo .exe Este é o arquivo executável final que pode ser executado como um programa Windows; É no formato Portable Executable (PE); O arquivo é feito pelo vinculador (linker), que tem um ou mais arquivos .obj e um .res e combina-os em um arquivo .exe; O formato de arquivo PE exige também um cabeçalho com informações sobre o arquivo; O Linker fornece essa informação. Para tornar os programas Windows, precisará usar um vinculador capaz de fazer os arquivos PE, por exemplo GoLink. Anderson Moreira Arquitetura de Computadores 38 Arquivo .dll Este arquivo contém os dados e outras funções que o .exe pode usar quando estiver em funcionamento; Na maioria das vezes não vai precisar usar um arquivo .dll em tudo. No entanto, é útil se você tem muitas funções que necessitam ser chamadas por mais de um .exe; Em vez de duplicar o código nos dois .exe pode tê-lo apenas uma vez em um arquivo .dll; O Windows usa extensivamente para fornecer acesso às APIs para aplicações do SO. O linux utiliza em geral arquivos .lib; Dê uma olhada na pasta do sistema \Windows no seu computador - isto é onde o Windows Dlls são normalmente mantidas, ou no diretório /lib no Linux. Anderson Moreira Arquitetura de Computadores 39 Sintaxe para utilização de .dll GoLink @comando Em que a parte designada por comando pode ser: /debug coff Myprog.obj Myprog.res Kernel32.dll As linhas informa o linker a procurar no arquivo kernel32.dll pela API para identificar chamadas feitas no programa; Esta é uma parte necessária do processo de vinculação. É bem possível que o programa faz chamadas para APIs que estão em Dlls do sistema. Anderson Moreira Arquitetura de Computadores 40 Por que um código em nível tão básico? Anderson Moreira Arquitetura de Computadores 41 Porque? Existem várias razões, entre elas: Código enxuto: Codificando em baixo nível, reduz o código para o mínimo exigido; Velocidade: Menor tamanho de código significa que os programas carregam mais rápido e executam mais rápido; Controle: Desenvolvedor está no controle do código, não o compilador. Isto significa que sabe exatamente o que o processador está fazendo enquanto se move através de seu código. Isto torna mais fácil para acertar as coisas e para encontrar erros; Satisfação: Você mesmo está escrevendo o programa. Não está sendo escrito em parte pelo compilador. Anderson Moreira Arquitetura de Computadores 42 Os componentes de um código ASM Basicamente os códigos podem ser definidos nas seguintes categorias: Instruções de Registradores; Instruções de Pilha; Instruções de Execução; Instruções de Memória; Instruções de Sinais; Declarações de Memória; Instruções do Sistema Operacional. Anderson Moreira Arquitetura de Computadores 43 Instruções de Registradores Isto é onde o Desenvolvedor diz ao processador para mover dados ou executar cálculos utilizando os seus próprios registros de 32 bits; Existem 6 registros para uso geral, chamado EAX, EBX, ECX, EDX, ESI e EDI (não são novidades!). Exemplos dessas instruções são: MOV ESI,EBX ;move conteúdo do registrador EBX para ESI ADD EAX,EDI ;adiciona o conteúdo do registrador EDI para EAX BT ECX,0 ;testa o bit 0 do registrador ECX CMP EDX,450 ;compara conteúdo de EDX com 450 DIV ECX ;divide EDX:EAX (long integer) por ECX MUL ECX ;multiplica EAX por ECX resultado em EDX:EAX (long ;integer) SHL EDX,4 ;shift EDX bits para esquerda em 4 bits (multiplica por ;16) TEST EAX,8 Anderson Moreira ;testa o bit 3 do registrador EAX Arquitetura de Computadores 44 Instruções de Pilha A pilha é uma área de memória fornecido pelo SO para cada programa em execução usar como uma área de armazenamento temporário. Exemplos dessas instruções: PUSH EAX ;coloca o conteúdo do registrador EAX para pilha POP EDX ;tira a última coisa colcoada na pilha para EDX PUSH 1000h ;coloca o valor 1000 em hexa na pilha MOV EBP,ESP ;mantem o valor no ponteiro da pilha no registrador ;EBP SUB ESP,30h ;movo o ponteiro da pilha para fazer uma área para ;dados locais MOV D[EBP-20h],500h Anderson Moreira ;insere o valor 500 em hexa em uma área de dados local Arquitetura de Computadores 45 Instruções de Execução Desvia o processador para executar código de um ponto a outro de acordo com a próxima linha dentro do código-fonte. Exemplos: CALL MAKEWINDOW ;executa o procedimento e depois retorna CALL EAX ;executa o endereço de código de EAX e depois ;retorna RET ;termina um procedimento retornanco para o chamador JZ 4 ;continua a execução do label 4: se o resultado for ;zero JC >.fin ;continua a execução de .fin se a flag carry estiver ;habiltada (set) JMP MAKEWINDOW ;continua a execução do procedimento identificado LOOP 2 ;decrementa ECX e pula para label 2: a menos que ECX=0 Anderson Moreira Arquitetura de Computadores 46 Instruções de Memória Lêem ou escrevem em áreas da memória que não seja a pilha. Normalmente, essa memória pode estar na seção de dados executável (.data) ou ele próprio poderia ser memória alocada pelo SO em tempo de execução. Exemplos: ADD EAX,[ESI] ;adiciona em EAX conteúdo de memória apontado por ;ESI MOV EAX,[MYDATA] ;move para EAX conteúdo de memória do label MYDATA SUB D[MYDATA+64],10h ;subtrai 10h da dword de MYDATA mais 64 bytes CMP B[MYDATA+EDX*4],2 ;compara um byte com 2 em parte do array MYDATA LODSB ;carrega byte da memória apontada por ESI em AL STOSD ;carrega o conteúdo de EAX dentro da memória ;apontada por EDI Anderson Moreira Arquitetura de Computadores 47 Instruções de Sinais (flag) As principais flags que iremos usar são Z (zero flag), C (carry flag), S (flag de sinal) e D (flag de direção). A maioria das instruções altera as flags automaticamente para dar o resultado da instrução. Existem instruções específicas que podemos usar para mudar as flags do processador manualmente: STC ;inicializa a carry flag CLC ;limpa o conteúdo carry flag STD ;inicializa a flag de direção CLD ;limpa a flag de direção Anderson Moreira Arquitetura de Computadores 48 Declarações de Memória O SO reserva uma memória para o executável quando ele é executado. As declarações são feitas para reservar memória na seção de dados (.data) ou seção constante (.cons), se os dados devem ser inicializados, isto é, definida como um valor. Se os dados não precisa ser inicializado a área de dados pode ser reservado na seção de dados não inicializados. Isso não ocupa nenhum espaço do arquivo EXE. Ao invés de espaço em memória é alocado para este tipo de dados quando inicia o primeiro executável. Exemplos de como a memória é declarada: Anderson Moreira Arquitetura de Computadores 49 Declarações de Memória DB 4 MYDATA DB 4 MYSTRUCT DD 16 DUP 0 BUFFER DB 1024 DUP ? Anderson Moreira ;declara um byte e seta com o ;valor inicial de 4 ;a byte com valor inicial de ;4 com label MYDATA ;16 dwords todos setados com ;zero chamado MYSTRUCT ;1024 bytes chamado BUFFER em ;área de dados não definida Arquitetura de Computadores 50 Instruções do SO Possibilita ao programadores assembler acesso a um vasta gama de APIs (Applications Programming Interface). Este é o código dentro do sistema operacional. Exemplos: PUSH 12h ;coloca o valor 12 hexa na pilha para chamar ;API CALL GetKeyState ;fala ao Windows para buscar o estado da tecla ;do teclado em EAX TEST EAX,80000000h ;testa se a tecla <ALT> é pressionada (bit 31 ;set) JZ >L22 Anderson Moreira ;caso não, pula para frente de L22 Arquitetura de Computadores 51 Outras informações Instruções para dizer ao Assembler em qual seção colocar o código fonte. O Assembler marca a seção de código como seções de leitura, executável e dados, definidos e indefinidos como leitura / gravação: CODE SECTION ;todo código nessa seção será marcada como ;read-only e executavél (.code) DATA SECTION ; todo código nessa seção será marcada como ;atributo de read/write mas não atributos ;de código (.code) CONST SECTION ; todo código nessa seção será marcada como ;read Anderson Moreira Arquitetura de Computadores 52 Dúvidas Anderson Moreira Arquitetura de Computadores 53