Antes de dar continuidade á leitura desta postagem, seria bom voçê já ter uma noção de programação. Já tem? Pois bem, então, esqueça. Estamos diante de um paradigma totalmente diferente. Assembly é uma linguagem considerada de baixo nível, ou seja, mais próxima da linguagem de máquina (Que só a máquina entende). PHP, JAVA e PYTHON podem ser consideradas linguagem de alto nível (Muito mais próximo do entendimento humano). Ela tem algumas peculiaridades bem interessantes, que deixam qualquer programador acostumado com linguagens de alto nível de cabelo em pé.
Este tutorial serve para voçê ter uma noção de como trabalha e se desenvolve nesta linguagem tão clássica. Voçê terá uma noção teórica importante antes de por a mão na massa, e alguns exemplos para analisar e ir treinando.
Esta linguagem, hoje em dia, é utilizada para escrever softwares que se comunicam diretamente com o hardware, como, por exemplo: controle remoto, microcontrolador, etc.
Pra começar, voçê deve saber que, uma vez que o código-fonte já esteja sido escrito, ele precisa ser compilado, ou seja, precisa ser transformado num programa executável, para poder rodar. Os programas que fazem este papel chamam-se ASSEMBLADORES. Assemblador, em poucas palavras, converte a linguagem assembly em linguagem de máquina, por processo conhecido como montagem. A máquina só entende agrupamentos de bits 0 e 1. O assemblador converte o seu código em bits 0 e 1, compreensíveis ao seu computador.
Para utilizar nossos exemplos, utilizaremos o assemblador NASM, que pode rodar tanto em WINDOWS quanto em LINUX. Está disponível no seguinte endereço: Site oficial da NASM.
Sugiro que baixe e instale este programa antes de dar continuidade á este artigo.
Pois bem, antes de continuar, vamos entender o que é registrador, pois, voçê vai manipulá-los direto. Registrador é a unidade de armazenamento interno do processador. Em poucas palavras, são os espaços para manipular dados. Normalmente, através das instruções em assembly, estes registradores são manipulados. Fique esperto que, alguns registradores tem finalidade específica. Por exemplo: EAX pode ser usada para realização de operações aritméticas, mas também é utilizadas para fazer chamadas ao núcleo do sistema operacional, como por exemplo: Exibir algo na tela, finalizar execução, etc. Segue ao lado uma lista destas interrupções que se deve setar no registrador EAX: Lista de interrupções.
É preciso lembrar que, existem registradores de 32 bits, de 16 bits e de 8 bits. Por exemplo: EAX é um registrador acumulador de 32 bits, AX é o mesmo só que em 16 bits; AL e AH são o mesmo em 8 bits. Neste caso, AX é composto por AX e AL, tendo 8 bits cada. Uma explicação mais detalhada sobre cada registrador voçê vê em: Lista de registradores
Agora sim, vamos por a mão na massa. Lembrando que, cada assemblador possui uma estrutura própria de programa. No nosso caso, a estrutura própria é a seguinte:
section .data ; Dados inicializados section .bss ; Dados não-inicializados section .text ; Conteúdo do programa global _start ; Definindo como global, para ser interceptado por alguma biblioteca em C _start: ; Conteúdo mesmo é aqui
Pois bem, segue abaixo um programa que recebe dois números (Que voçê ira digitar), e irá retornar a soma.
section .data ; Onde ficam dados inicializados. Normalmente o padrão para declarar variável é: ; NOME TIPO (POde ser DB-BYTE,DD-DOUBLE WORD,DW-WORD) VALOR p DB "Digite um número: " len_p equ $-p ; Tamanho da variável p. É necessário para passar ao registrador edx pp DB "Digite o segundo número: " len_pp equ $-pp m DB "Resultado: " len_m equ $-m section .bss ; Reservando espaço de 1 byte para posterior uso. No nosso caso, troca-se apenas o D por RES numero RESB 2 resultado RESB 2 segundo RESB 2 section .text global _start _start: ; Qualquer instrução do trecho de programa _start ficará aqui. Neste caso, _start é um rótulo dado á este trecho específico de programa. _start é o fluxo principal do programa ; Em instruções que se exibe algo na tela. O EAX possui valor 4, que é a interrupção para se exibir algo na tela. EDX armazena a quantidade de caracteres a serem exibidas mov edx, len_p ; Tamanho da string que será exibir mov ecx, p ; Conteúdo da mensagem mov eax, 4 ; Chamada ao núcleo do sistema para exibir algo na tela mov ebx, 1 ; 0 = NADA; 1 = STDOUT (Saída); 2 = STDIN (Entrada) int 0x80 ; CHamada ao núcleo do sistema, que recebe o valor contido em eax para executar ; Trecho abaixo trata de receber o número digitado pelo usuário e o armazena na variável numero mov eax, 3 ; Indica ao núcleo que é pra receber um valor preenchido pelo usuário mov ebx, 2 ; STDIN (Preparar o programa para uma entrada de texto) mov edx, 1 ; Tamanho do campo recebido mov ecx, numero ; Armazena a entrada na variável numero int 0x80 ; Interrupção ; Exibindo na tela a segunda mensagem mov edx, len_pp mov ecx, pp mov eax, 4 mov ebx, 1 int 0x80 ; Recebendo o segundo parâmetro mov eax, 3 mov ebx, 2 mov edx, 2 mov ecx, segundo int 0x80 ; Exibindo terceira mensagem mov edx, len_m mov ecx, m mov eax, 4 mov ebx, 1 int 0x80 ; Efetuando a soma mov bl, [segundo] ; Atribuindo o valor da variável segundo ao registrador BL mov al, [numero] ; Atribuindo o valor da variável numero ao registrador AL sub bl, '0' ; Convertendo valor de ASCII em decimal para fins de operação add al, bl ; Efetuando a soma, sendo que, o resultado fica armazenado no registrador al mov [resultado], al ; Movendo o valor de al na variável resultado ; Trecho abaixo exibe o resultado na tela mov ecx, resultado mov edx, 2 mov eax, 4 mov ebx, 1 int 0x80 mov eax,1 ; SAIDA int 0x80
Para compilar o programa acima, copie e cole o código acima em seu editor de texto, e salve com o nome de soma.asm. Todo código-fonte em assembly deve ter a extensão .asm.
Em seguida, execute os seguintes comandos em linha de comando:
nasm -f elf64 soma.asm // Para compilar ld soma.o -o soma // Para gerar o executável ./soma // Para executar // Lembrando que o comando acima serve para LINUX, não sei como deve ser no WINDOWS
Segue outro programa que calcula a área de um triângulo tendo a base e a altura da mesma.
section .data msg DB "Digite a base do triangulo" ,0xa l_msg equ $ - msg msg2 DB "Digite a altura do triangulo", 0xa l_msg2 equ $ - msg2 msg3 DB "Resultado", 0xa l_msg3 equ $ - msg3 divisor DB '2' section .bss base RESB 1 altura RESB 1 area RESB 2 section .text global _start _start: mov eax, 4 mov ebx, 1 mov edx, l_msg mov ecx, msg int 0x80 mov eax, 3 mov ebx, 2 mov ecx, base mov edx, 2 int 0x80 mov eax, 4 mov ebx, 1 mov edx, l_msg2 mov ecx, msg2 int 0x80 mov eax, 3 mov ebx, 2 mov ecx, altura mov edx, 2 int 0x80 ; Multiplicando base e altura sub [base], byte '0' sub [altura], byte '0' mov al, [base] mov bl, [altura] mul bl ;AL = AL * BL OU AX = AL * BL ; Dividindo o produto por 2 sub [divisor], BYTE '0' ; Conversão de decimal para ASCII mov bl, [divisor] div bl ; Divisão do acumulador(AX) pelo divisor (bl) . No AX, está o resultado da multiplicação add al, '0' mov [area], al mov eax, 4 mov ebx, 1 mov edx, l_msg3 mov ecx, msg3 int 0x80 mov eax, 4 mov ebx, 1 mov edx, 2 mov ecx, area int 0x80 jmp sair sair: mov eax, 1 mov ebx, 0 int 0x80
Caso queira conhecer um pouco mais desta linguagem, sugiro os seguintes links abaixo:
Tutorial de ASSEMBLY Uma breve introdução ao ASSEMBLY
Segue abaixo uma lista de exemplos que fiz para aprender a usar esta ferramenta:
Nenhum comentário:
Postar um comentário