Primeiro Programa Assembly no macOS com NASM
Escrever Assembly no macOS em processadores Intel (arquitetura x86-64) é uma experiência única, com suas próprias convenções e ferramentas. Este guia irá conduzi-lo através da configuração do ambiente, da criação de um programa funcional e das particularidades da plataforma.
Montando seu Kit de Ferramentas
Para criar um executável a partir do código Assembly, precisamos de duas ferramentas essenciais: um montador e um linker.
1. O Montador: Instalando o NASM
A maneira mais simples e recomendada de instalar o NASM no macOS é usando o gerenciador de pacotes Homebrew. Se você ainda não o tem, instale-o com este comando no Terminal:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
Com o Homebrew pronto, instalar o NASM é um único comando:
brew install nasm
2. O Linker: Xcode Command Line Tools
O linker padrão no macOS é o ld, que faz parte do conjunto de ferramentas do compilador Clang. A forma mais fácil de obtê-lo é instalando o Xcode Command Line Tools.
Para verificar se as ferramentas já estão instaladas, digite clang -v no Terminal. Se você vir a versão do Clang, está tudo pronto. Se receber um erro, instale as ferramentas explicitamente com:
xcode-select --install
O Primeiro Programa
Vamos começar com um programa que apenas encerra sua execução. Crie um arquivo chamado hello.asm com o seguinte conteúdo:
global _start ; Torna o rótulo _start visível externamente
section .text ; Declaração da seção de código
align 4 ; Alinhamento necessário para o macOS
_start: ; Ponto de entrada do programa
mov rax, 0x02000001 ; Syscall para exit
mov rdi, 22 ; Código de retorno arbitrário: 22
syscall ; Executa a chamada de sistemaAnalisando as Particularidades do macOS:
align 4: O macOS exige que o código executável seja alinhado em um limite de 4 bytes por convenção.- Numeração das Syscalls: Este é um ponto crucial. Pense nas chamadas de sistema do macOS como um número de telefone com código de área e ramal. O "código de área" para syscalls do kernel é
0x2000000. O "ramal" para a funçãoexité1. O valor final que colocamos emraxé a soma:0x2000000 + 1.
Do Código ao Executável: Montagem e Ligação
1. Montagem com o NASM
No Terminal, navegue até a pasta do seu projeto e execute:
nasm -f macho64 hello.asm -o hello.o
A opção -f macho64 é fundamental. Ela gera um arquivo objeto no formato Mach-O, o padrão nativo do macOS.
2. Ligação com o ld
O comando de ligação no macOS parece complexo, mas cada parte tem um propósito claro:
ld -o hello hello.o -l System -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start
Vamos decompor este comando:
-o hello hello.o: Cria um executável chamadohelloa partir do arquivohello.o.-l System: Liga nosso programa à biblioteca de sistema principal do macOS. É como conectar nosso código à "energia" do sistema operacional.-syslibroot: Informa ao linker onde encontrar as bibliotecas do sistema. O comando dentro das crasesxcrun...encontra automaticamente o caminho correto.-e _start: Define_startcomo o ponto de entrada do nosso programa.
Para executar e verificar o código de saída:
programicio@MacBook-Pro nasm % ./hello programicio@MacBook-Pro nasm % echo $? 22
Segundo Programa: Escrevendo no Console
Agora, vamos exibir uma mensagem. Altere seu hello.asm:
global _start
section .text
align 4
_start:
mov rax, 0x02000004 ; Syscall para write (base + 4)
mov rdi, 1 ; Descritor de arquivo: 1 para stdout
lea rsi, [rel message] ; Endereço da mensagem (relativo a RIP)
mov rdx, 19 ; Tamanho da mensagem em bytes
syscall ; Executa a chamada de sistema
mov rax, 0x02000001 ; Syscall para exit (base + 1)
syscall ; Executa a chamada de sistema
section .data
message: db "Hello Programicio!", 10 ; Nossa string e uma quebra de linhaAnalisando a Maior Diferença: Endereçamento Relativo
- A syscall para
writeno macOS é a de número4, entãoraxrecebe0x2000004. A linha
lea rsi, [rel message]é a mudança mais importante. Por segurança, os sistemas operacionais modernos (incluindo o macOS) carregam programas em locais aleatórios na memória. Isso é chamado de Código Independente de Posição (PIE).- O Problema: Não podemos usar um endereço de memória fixo para nossa
message. - A Solução: Usamos o endereçamento relativo.
lea rsi, [rel message]significa: "Carregue emrsio endereço damessage, calculado a partir da minha posição atual (o registradorrip)". É como dar direções ("três casas à frente") em vez de um endereço absoluto ("Rua Principal, 123").
- O Problema: Não podemos usar um endereço de memória fixo para nossa
O tamanho da mensagem é de 19 bytes (18 para "Hello Programicio!" + 1 para a quebra de linha).
O processo de montagem e ligação é exatamente o mesmo. O resultado será:
programicio@MacBook-Pro nasm % ./hello Hello Programicio!
Resumo
- Instalação: Use Homebrew para instalar o NASM e o Xcode Command Line Tools para obter o linker (
ld). - Formato de Arquivo: O formato de saída para o macOS é
macho64. - Chamadas de Sistema: As syscalls do kernel têm uma base de
0x2000000, à qual o número da função é somado (exit= 1,write= 4). - Ligação: A ligação com
ldno macOS requer parâmetros específicos para vincular à biblioteca do sistema (-l System) e definir o ponto de entrada (-e _start). - Endereçamento Relativo: O código no macOS é independente de posição, o que torna obrigatório o uso de endereçamento relativo ao
rip(lea [rel ...]) para acessar dados.