Por que emular ARM (e por que isso ensina arquitetura)
A ideia da trilha
Dá para aprender arquitetura ARM lendo o Architecture Reference Manual de capa a capa. São umas 8000 páginas. A alternativa desta trilha é outra: aprender implementando. Cada conceito — um registrador, uma flag, um modo de exceção — vira código que decide o que acontece quando aquela instrução executa. Não tem como "mais ou menos entender" o carry do ADCS quando o seu emulador precisa produzir o bit certo.
O material de apoio é um conjunto de projetos Java que eu mantenho:
arm-jitter— a biblioteca-núcleo. Executa, depura e compila (JIT) blocos ARM/THUMB. Não temmain: é um core para ser embutido.armbox— um runner Linux user-mode (estiloqemu-arm) sobre oarm-jitter. Carrega um ELF estático, monta a pilha ABI do Linux e traduz syscalls. É onde a maioria dos exemplos da trilha roda.gbaemu/ndsemu/n3dsemu— emuladores de Game Boy Advance, Nintendo DS e 3DS. Cada console fixa uma geração do ARM.virtual-arm-box— máquina ARM completa (CPU + MMU + periféricos) que boota um Linux real até o shell.
A trilha inteira está indexada na página do Curso de Arquitetura ARM.
Por que um emulador ensina o que um livro não ensina
Um livro descreve o comportamento. Um emulador é o comportamento. Três coisas ficam concretas quando você implementa:
- Não existe caso omisso. O manual pode dizer "o resultado é
UNPREDICTABLE". O emulador tem que fazer alguma coisa — e escolher o quê te força a entender por que a arquitetura deixou aquilo em aberto. - Estado é tudo. Registradores bancados por modo,
SPSR, o bit T doCPSR, o bit 0 doPCque seleciona ARM ou Thumb — tudo isso deixa de ser trivia e vira uma variável que você lê e escreve na ordem certa, ou o programa convidado quebra. - O binário é a verdade. Você para de pensar em
mov r0, #1e passa a pensar em0xE3A00001. Decodificar esse número — separarcond, opcode,Rd, operando — é o exercício central dos módulos 2 e 3.
O ecossistema, em uma tabela
| Projeto | Papel | O que executa |
|---|---|---|
arm-jitter | Biblioteca-núcleo (core + decoder + IR + JIT + GDB) | blocos ARM/THUMB, embutido por um hospedeiro |
armbox | Runner Linux user-mode | ELF estático 32-bit + syscalls EABI |
gbaemu | Emulador de GBA | ARM7TDMI (ARMv4T) |
ndsemu | Emulador de NDS | ARM9 + ARM7 (ARMv5TE) |
n3dsemu | Emulador de 3DS | ARM11 MPCore (ARMv6K) |
virtual-arm-box | Máquina ARM completa (softmmu) | kernel Linux ARM até shell busybox |
A linha do tempo do ARM que a trilha percorre
Os emuladores da coleção cobrem, sem querer, quase toda a evolução do ARM de 32 bits. É essa a espinha do módulo 5:
| Arquitetura | Núcleo | Guest típico | O que ela adiciona |
|---|---|---|---|
| ARMv4T | ARM7TDMI | GBA | ARM + Thumb, o conjunto base |
| ARMv5TE | ARM9E | NDS | BLX, CLZ, multiplicações DSP/saturating, LDRD/STRD |
| ARMv6K | ARM11 | 3DS, Raspberry Pi 1 | LDREX/STREX, SIMD paralelo, CPS/SETEND/WFI |
| ARMv6-M / v7-M | Cortex-M | firmware | perfil M: MSP/PSP, xPSR, NVIC, sem modos bancados clássicos |
| ARMv7-A | Cortex-A | Linux/Android 32-bit | MOVW/MOVT, SDIV/UDIV, bitfield, barreiras, VFPv2 |
| AArch64 | ARMv8-A | Linux arm64 | 64 bits, X0–X30, sem banking por modo, exceções por Exception Level |
Começar no ARMv4T não é nostalgia: é o subconjunto menor. Tudo que vem depois é acréscimo sobre essa base, e é mais fácil sentir por que uma extensão existe depois de ter passado sem ela.
Um gostinho do que vem por aí
Este é o menor programa Linux ARM que dá para escrever — sem libc, só syscalls cruas (armbox/testdata/hello.s):
.arch armv5te
.arm
.text
.global _start
_start:
mov r0, #1 @ fd = stdout
adr r1, msg
mov r2, #(msg_end - msg)
mov r7, #4 @ NR_write
svc #0
mov r0, #42 @ código de saída
mov r7, #1 @ NR_exit
svc #0
msg:
.ascii "hello from a real ELF\n"
msg_end:Montado e desmontado com o toolchain arm-none-eabi, ele vira isto:
Reparou que adr r1, msg virou add r1, pc, #20? Esse tipo de tradução — do que você escreve para o que a máquina realmente executa — é o assunto da trilha. No artigo de decodificação a gente pega números como 0xe3a00001 e separa campo por campo.
Glossário
| Termo | O que é |
|---|---|
| ISA | Instruction Set Architecture — o contrato entre o binário e o hardware |
| Emulador | Programa que implementa a semântica de uma ISA em outra máquina |
| Core | A parte do emulador que executa instruções (registradores + decode + execute) |
| Guest / host | O sistema emulado / a máquina que roda o emulador |
| JIT | Just-In-Time — compilar blocos do guest para código nativo do host em tempo de execução |
| Interpretador | Executar instrução por instrução, sem compilar; a referência de semântica |
| Bare-metal | Código sem sistema operacional por baixo |
Próximo passo
O próximo artigo monta a bancada: JDK, Maven, o toolchain arm-none-eabi e os repositórios, para você conseguir compilar e rodar cada exemplo daqui pra frente.
Trilha: Curso de Arquitetura ARM · Módulo 0, lição 1.