Arquitetura e organização de computadores Programação em linguagem assembly Aula 17 Prof. Diovani Milhorim Linguagem Assembly Assembly é uma linguagem de baixo nível, chamada freqüentemente de “linguagem de montagem” É uma linguagem considerada difícil, principalmente porque o programador precisa conhecer a estrutura da máquina para usá-la Linguagem Assembly A linguagem Assembly é atrelada à arquitetura de uma certa CPU, ou seja, ela depende completamente do hardware Cada família de processador tem sua própria linguagem assembly (Ex. X86, ARM, SPARC, MIPS) Por essa razão Assembly não é uma linguagem portável, ao contrário da maioria das linguagens de alto nível Linguagem Assembly As primeiras linguagens Assembly surgiram na década de 50, na chamada segunda geração das linguagens de programação A segunda geração visou libertar os programadores de dificuldades como lembrar códigos numéricos e calcular endereços Linguagem Assembly Assembly foi muito usada para várias aplicações até os anos 80, quando foi substituída pelas linguagens de alto nível Isso aconteceu principalmente pela necessidade de aumento da produtividade de software Linguagem Assembly Atualmente Assembly é usada para manipulação direta de hardware e para sistemas que necessitem de performance crítica Device drivers, sistemas embarcados de baixo nível e sistemas de tempo real são exemplos de aplicações que usam Assembly. Linguagem Assembly A linguagem Assembly é de baixo nível, porém ainda precisa ser transformada na linguagem que a máquina entende Quem faz isso é o Assembler. O Assembler é um utilitário que traduz o código Assembly para a máquina Assembler é o compilador Assembly é a linguagem. Linguagem Assembly Exemplo: Antes -> mov al, 061h (x86/IA-32) Depois -> 10110000 01100001 Linguagem Assembly Em Assembly é comum representar os números na forma hexadecimal. Isso acontece porque é interessante visualizar o número na forma de dados A representação hexadecimal facilita o tratamento de números muito grandes. Linguagem Assembly Um algarismo hexadecimal pode ser representado por quatro algarismos binários Logo um byte pode ser representado como dois números hexa, um word como quatro números hexa e um dword como oito números hexa Linguagem Assembly Binário Hexa Decimal Tipo 10000000 80 128 byte 8001 32.769 word 1111111111111 111 FFFF 65.535 word 1111111111111 1111111111111 111111 FFFFFFFF 4.294.967 dword .295 1000000000000 001 Linguagem Assembly Em assembly trabalha-se diretamente com os registradores do processador. Nos processadores Intel, existem apenas 8 registradores de uso geral São eles: EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP Linguagem Assembly Os registradores ESP e EBP só devem ser usados preferencialmente para trabalhar com a pilha EAX -> Chamado de “Acumulador”, geralmente é usado para operações aritméticas e para guardar resultados EBX -> Chamado de “Base”, geralmente é usado para armazenar dados em geral e para endereços de memória ECX -> Chamado de “Contador”, como o nome já diz é usado como contador, principalmente para controlar loops EDX -> Chamado de registrador de dados, é usado geralmente para guardar o endereço de uma variável na memória Linguagem Assembly ESI e EDI -> Respectivamente “Source Index” e “Destination Index”, são menos usados do que os registradores descritos anteriormente. Geralmente usa-se ESI e EDI para movimentação de dados, com ESI guardando o endereço fonte de uma variável e EDI guardando o endereço destino. Não podem ser acessados em nível de Byte. Linguagem Assembly ESP e EBP -> Respectivamente “Stack Pointer” e “Base Pointer”, só devem ser usados para manipulação da pilha. O Registrador ESP guarda a referência para o topo da pilha, enquanto o registrador EBP é usado para “andar” pela pilha Linguagem Assembly Todos os programas fazem uso da pilha em tempo de execução, porém nas linguagens de alto nível não é preciso se preocupar com o funcionamento da pilha Já em Assembly, o programador precisa saber trabalhar com a pilha, pois ela é uma ferramenta importante Linguagem Assembly Registrado de estado (flag) Um registrador de estado é uma coleção de bits que indicam o estado de várias operações matemáticas. Os bits são comumente chamados de flags (bandeiras) e são usados durante testes de condição e ramificação de programas. A número de bits, sua ordem e a interpretação dada a eles depende de cada processador. Linguagem Assembly Formato do registrador Flag Linguagem Assembly Nos processadores Intel as flags mais importantes do principal registrador de estado têm o seguinte significado: Linguagem Assembly Estrutura de um programa assembly. Vamos entender como se estrutura um programa em assembly. Como padrão de editor e compilador utilizares o MASM32 (microsoft assembly) disponibilizado gratuitamente pela microsoft. O programa é dividido em várias áreas, cada uma com suas diretivas próprias. Linguagem Assembly Estrutura de um programa assembly. É necessário inicialmente para que o compilador possa escolher o conjunto de instruções compatíveis indicar o tipo de CPU. Se a CPU é do tipo 80386 em diante (80386, 80486, Pentium, etc). Trabalhar com o conjunto de instruções do 386 costuma ser mais do que suficiente Como é que passamos essa informação para o compilador? Usando uma diretiva apropriada: .386 ---> para processadores do tipo 80386 .486 ---> para processadores do tipo 80486 Linguagem Assembly Estrutura de um programa assembly. Ainda precisamos indicar qual é o modelo de memória que deve ser usado. Um executável é carregado na memória de acordo com o modelo de memória definido durante a compilação. Na época dos computadores de 16 bits, o programa era carregado na memória em segmentos de tamanho predefinido. Com o advento dos 32 bits, os executáveis passaram a ser carregados na memória em endereços contíguos. Imagine um segmento único de memória contendo o executável, uma tripa enorme com a sequência de instruções. Este modelo de memória foi denominado FLAT, ou seja, modelo plano ou contínuo. Usa-se a diretiva: .MODEL FLAT Linguagem Assembly Estrutura de um programa assembly. Passagem de parâmetros para funções: A forma de envia parâmetros precisa ser definida previamente: se houver mais de um parâmetro, podemos enviá-los de frente para trás ou de trás para frente, ou seja, da esquerda para a direita ou da direita para a esquerda. Veja um exemplo: Suponha que uma função espere receber dois parâmetros (param1 e param2). Podemos enviá-los na sequência param1, param2 ou na sequência param2, param1. A primeira convenção de passagem de parâmetros é conhecida como PASCAL e a segunda como convenção C. Linguagem Assembly Estrutura de um programa assembly. Os parâmetros recebidos são guardados temporariamente num registrador da CPU chamado de pilha (stack). Como o conteúdo da pilha é alterado quando uma função é chamada ou quando a própria função alterá-lo, é preciso fazer um ajuste de pilha em cada retorno de função. Na convenção de passagem de parâmetros do tipo Pascal, a função chamada é a responsável pelo ajuste da pilha antes do retorno. Na convenção C, a rotina chamadora é a responsável. Existe uma terceira convenção de passagem de parâmetros denominada STDCALL (abreviação de STanDard CALL - chamada padrão). Usando esta convenção, os parâmetros são enviados da direita para a esquerda (como na convenção C) mas a função chamada é a responsável pelo ajuste da pilha. A STDCALL é um híbrido das convenções Pascal e C. Linguagem Assembly Estrutura de um programa assembly. Os sistemas win32 utilizam exclusivamente a convenção de passagem de parâmetros STDCALL. Podemos e devemos completar a diretiva acima com: .MODEL FLAT, STDCALL Linguagem Assembly Estrutura de um programa assembly. Inicialização de dados e variáveis. Diretiva .DATA. Tudo que o compilador encontrar nas linhas subsequentes, até encontrar outra diretiva, ele vai considerar como variáveis (dados) inicializados. Diretiva .DATA? Declaração de variáveis não inicializadas, ou seja, fazemos com que o assembler ponha determinados nomes de variáveis na lista de variáveis, mas sem valores definidos. Diretiva .CONST. Declaração de dados de valores fixos, as assim chamadas constantes. Os dados declarados são os chamados dados globais (variáveis e constantes).sEnquanto o programa estiver sendo executado, estes dados ficam preservados. Só são destruídos quando o programa termina. Linguagem Assembly Estrutura de um programa assembly. 386 .MODEL FLAT, STDCALL .DATA ... (aqui vão os dados inicializados) .DATA? ...(aqui vão os dados não inicializados) .CONST ... (aqui ficam as constantes) .CODE inicio: ... (aqui está todo o código do programa) end inicio Linguagem Assembly Processo de criação do executável: O processo de criação em um executável assembly passa pela compilação e link de endereços e recursos Linguagem Assembly Processo de criação do executável: Arquivos envolvidos: Os arquivos de recursos (.rc) só são necessários quando se quer utilizar recursos adicionais, como menus e bitmaps. Isto significa que podem ou não estar presentes no seu projeto Linguagem Assembly Arquivos envolvidos: O código fonte dos recursos Como todo código fonte, este também é um arquivo texto produzido com um editor de texto. Deve conter palavras e números que o sistema operacional usa para montar os recursos do programa que será executado os quais, geralmente, são menus, diálogos e tabelas de strings. Também serve de fonte de referência para outros arquivos como ícones, bitmaps e cursores. Maiores detalhes em como criar um arquivo de recursos você encontra nos tutoriais. Linguagem Assembly Arquivos envolvidos: O arquivo objeto dos recursos O arquivo de recursos compilado é como se fosse um "arquivo objeto" dos recursos. Normalmente não se usa este termo, mas a comparação é perfeitamente válida. Este arquivo é produzido por um compilador de recursos, o qual formata as instruções contidas num arquivo .rc (palavras e números), convertendo-o num arquivo .res pronto para ser inserido na seção de recursos de um executável final por um linker. Linguagem Assembly Arquivos envolvidos: O executável O arquivo executável é o arquivo final que pode ser executado pelo sistema operacional. Geralmente está no formato PE, reconhecido pelo Unix, Linux, Windows, etc. O programa é produzido por um linker, o qual usa um ou mais arquivos .obj e .res e os combina num executável final. O formato PE também exige que o executável tenha um cabeçalho com informações a respeito do arquivo .exe. O linker fornece estas informações. Linguagem Assembly Arquivos envolvidos: Arquivos DLL Este tipo de arquivo contém funções e dados que outros executáveis podem utilizar quando estiverem rodando. São úteis quando contêm funções que serão chamadas repetidas vezes por vários executáveis. Ao invés de repetir estas funções em cada um dos executáveis, estes utilizam uma fonte comum: as DLLs. O acrônimo DLL origina-se de Dinamic Link Library - Biblioteca de Vínculo Dinâmico.