← Voltar aos artigos

Semihosting e syscalls: como o arm-box traduz chamadas de sistema EABI para o host

O que é semihosting?

Quando você roda código ARM em um emulador (ou em hardware real com debugger), o código não tem acesso direto ao sistema operacional do host. Mas muitas vezes ele precisa:

  • Imprimir na tela (printf)
  • Ler do teclado (scanf)
  • Abrir/criar arquivos
  • Sair do programa

O semihosting é a solução: o código executa uma instrução especial (BKPT ou SVC) com um número de chamada, e o depurador/emulador intercepta, executa a operação no host, e retorna o controle ao código.

O mecanismo: como funciona

Entrada do semihosting

No Thumb-2 (Cortex-M e Cortex-A em mode Thumb):

  • BKPT #0xAB — a instrução clássica de entrada (16 bits)
  • O número da chamada fica em R0 (código da operação)
  • Argumentos adicionais em R1, R2, R3

No ARM mode (ARMv7-A):

  • SVC #0x12 — Supervisor Call (32 bits)
  • O mesmo mecanismo de números de operação em R0

No AArch64 (ARMv8):

  • HVC #0 ou SMC #0 — Hypervisor/Secure Monitor Call

O protocolo EABI

A lista de operações é padronizada pelo AAPCS/EABI:

Código (R0)OperaçãoDescrição
0x20SYS_WRITE0Escreve string terminada em NUL para stdout
0x21SYS_WRITEEscreve buffer para stdout
0x22SYS_READLê de stdin para buffer
0x23SYS_OPENAbre arquivo
0x24SYS_CLOSEFecha arquivo
0x25SYS_WRSCANFormatted write to stdout
0x26SYS_RDSCANFormatted read from stdin
0x30SYS_EXITTermina o programa

Bytes verificados (devkitARM)

    /* Thumb-2 */
    movs r0, #0x20       @ SYS_WRITE0
    ldr  r1, =msg
    movs r2, #0
    bkpt #0xAB           @ semihosting call
    b .
00000000<msg-0xa>:
0:2020movsr0, #32@ 0x20 = SYS_WRITE0
2:4903ldrr1, [pc, #12]
4:2200movsr2, #0
6:beabbkpt0x00ab@ semihosting entry
8:e7feb.n8
InstruçãoBytes (hex)Tamanho
movs r0, #0x2020 2016-bit
ldr r1, =msg49 0316-bit
movs r2, #022 0016-bit
bkpt #0xABBE AB16-bit
b .E7 FE16-bit

Nota sobre bkpt:BKPT #0xAB = 0xBEAB — o campo imm12 codifica 0x0AB. O BKPT é uma instrução de 16 bits em Thumb-2. O depurador reconhece o valor 0xAB como o entry point do semihosting ARM.

Semihosting no arm-box

Quando o arm-box executa com --arch=thumb2, o arm-jitter:

  1. Decodifica o BKPT #0xAB
  2. Lê os registradores (R0 = código da operação, R1/R2/R3 = argumentos)
  3. Traduz a chamada para a API correspondente do host
  4. Executa a operação (ex.: escreve na saída padrão do host)
  5. Retorna o controle ao código ARM

Para SYS_EXIT (código 0x30), o arm-box termina a execução do programa.

Tabela: instruções semihosting

InstruçãoBytes (hex)TamanhoUso
BKPT #0xABBE AB16-bitEntry point semihosting (Thumb)
SVC #0x12—32-bitEntry point semihosting (ARM mode)
movs r0, #0x2020 2016-bitSYS_WRITE0
movs r0, #0x3020 3016-bitSYS_EXIT

Glossário: instruções

InstruçãoO que faz
BKPT #0xABBreakpoint — entry point do semihosting
SVC #immSupervisor Call (ARM mode)
HVC #immHypervisor Call (AArch64)
movs Rd, #immMove immediate + flags
ldr Rd, =labelCarrega endereço de label

Glossário: comandos

ComandoO que faz
arm-none-eabi-as -mcpu=cortex-m3Monta Thumb-2
arm-none-eabi-objdump -dMostra bytes e instruções
--arch=thumb2Seleciona Thumb-2 no arm-box

Bytes verificados com arm-none-eabi-as -mcpu=cortex-m3 + arm-none-eabi-objdump -d.