Olá Mundo em Assembly no Ubuntu Linux, com Yasm Assembler

Olá Mundo em Assembly x86_64 no Ubuntu Linux, com Yasm Assembler

Fala pessoal! Neste tutorial vamos trabalhar um pouco com a linguagem Assembly, criando um programa bem simples para explorar suas instruções.

O programa será escrito em Assembly para a arquitetura Linux x86_64, usando o assembler Yasm (The Yasm Modular Assembler Project). O programa imprime a string “Olá Bóson” (ou qualquer outra que você queira) no terminal e depois encerra o programa.

Para escrever o código, abra um editor de texto de sua preferência (eu usei o editor Geany), digite o código a seguir e salve o arquivo com o nome de olaMundo.s em um diretório de sua preferência (a extensão .s é importante!)

Código

;olaMundo.s
section .data
    msg db 'Ola Bóson'
    nl db 0x0a
    tamMsg equ $-msg

section .text
global _start

_start:
    mov rax, 1
    mov rdi, 1
    mov rsi, msg
    mov rdx, tamMsg
    syscall
    mov rax, 60
    mov rdi, 0
    syscall

A seguir mostro uma explicação detalhada do código, instrução por instrução.

Explicação do código

O código é organizado em duas seções principais: .data e .text, as quais são definidas a seguir:

Seção .data:

A seção .data é usada para declarar e alocar espaço para dados, como variáveis, constantes e buffers.
Dados declarados nesta seção são geralmente usados para armazenar valores que o programa irá usar durante sua execução, como por exemplo números inteiros, strings, arrays e outros tipos de dados.

Em nosso exemplo temos:

  • msg db ‘Olá Bóson’: Define uma variável chamada msg que armazena a string “Olá Bóson”.
  • nl db 0x0a: Define uma variável nl com o valor hexadecimal 0x0a, que representa uma nova linha na tabela ASCII.
  • tamMsg equ $-msg: Calcula o tamanho da string msg subtraindo o endereço inicial de msg do endereço atual ($). Isso é usado para determinar o comprimento da string durante a execução.

Seção .text

Já a seção .text contém as instruções de código Assembly, ou seja, o programa real que é executado.
Esta seção contém a lógica do programa, incluindo operações aritméticas, controle de fluxo (condicionais, laços de repetição) e chamadas de funções, entre outras.

Em nosso código de exemplo:

  • global _start: Ponto de entrada do programa é definido como _start.
  • _start: Rótulo que define o ponto de entrada do programa. Indica onde a execução do programa começa.
  • mov rax, 1: Grava o valor 1 em rax, que é o número do sistema para a syscall sys_write (escrever na saída padrão).
  • mov rdi, 1: Grava o valor 1 no registrador rdi, indicando que a saída será no stdout (file descriptor 1), ou saída padrão.
  • mov rsi, msg: Grava o endereço da string msg no registrador rsi, apontando para a mensagem a ser impressa.
  • mov rdx, tamMsg: Ajusta o tamanho da mensagem em rdx, indicando quantos bytes devem ser escritos.
  • syscall: Chamada de sistema para escrever a mensagem no terminal.

Após escrever a mensagem, o programa usa novamente syscall para chamar sys_exit (número do sistema 60) e encerrar o programa. O código de status de saída é 0, indicando que o programa terminou sem erros.

A primeira linha do código, ;olaMundo.s, é um comentário, e por conta disso é ignorada pelo compilador. Os comentários se iniciam com o caractere ; (ponto-e-vírgula), e se estendem até o final da linha.

Como executar esse programa? Veremos na próxima seção.

Como rodar o programa em Assembly

Para executar e testar o programa escrito, abra um terminal (alternativamente, execute direto a partir do editor de textos / IDE, se estiver configurado para tal), entre no diretório que contém o código-fonte criado anteriormente, e execute os comandos a seguir:

1 – Gerar um arquivo binário a partir do código-fonte:

$ yasm -f elf64 olaMundo.s

Esse comando lê o arquivo “olaMundo.s” contendo o código assembly digitado e gera um arquivo objeto binário ELF de 64 bits a partir dele, usando o assembler yasm. Será gerado o arquivo olaMundo.o.

A opção -f elf64 especifica o formato de saída desejado. Aqui, indica que o formato de saída deve ser ELF (Executable and Linkable Format) de 64 bits. Trata-se de um formato de arquivo comum usado em sistemas Unix e Linux para executáveis e bibliotecas compartilhadas.

2 – Vincular o arquivo objeto e gerar programa executável:

$ ld -o olaMundo olaMundo.o

O comando diz ao linker ld para usar o arquivo objeto olaMundo.o como entrada e gerar um arquivo executável de nome olaMundo como saída. O arquivo executável é a versão final do programa que pode ser executada no sistema operacional.

ld é o nome do vinculador (linker), que é uma ferramenta que combina um ou mais arquivos objeto em um único arquivo executável (mais sobre esse assunto nos próximos tutoriais).

3 – Vamos verificar o arquivo executável criado no diretório:

$ ls -l

Deve ter sido gerado um arquivo executável de nome olaMundo no diretório atual.

4 – Finalmente, rodamos o programa:

$ ./olaMundo

Resultado:

Olá Bóson

Excelente! Nosso primeiro programa em Assembly criado, compilado e executado com sucesso. Nos próximos artigos vamos explorar mais a linguagem de forma sistemática, para entender como funcionam suas diversas declarações, mnemônicos e estruturas lógicas, e assim criar programas mais complexos.

Até!

Sobre Fábio dos Reis (1223 Artigos)
Fábio dos Reis trabalha com tecnologias variadas há mais de 30 anos, tendo atuado nos campos de Eletrônica, Telecomunicações, Programação de Computadores e Redes de Dados. É um entusiasta de Ciência e Tecnologia em geral, adora Viagens e Música, e estuda idiomas, além de ministrar cursos e palestras sobre diversas tecnologias em São Paulo e outras cidades do Brasil.

Escreva um comentário

Seu e-mail não será divulgado


*