2 pontos por GN⁺ 2026-02-08 | 1 comentários | Compartilhar no WhatsApp
  • SectorC, escrito em assembly x86-16, é um compilador C ultracompacto que cabe no setor de boot (512 bytes) de uma máquina x86 e oferece suporte a um subconjunto da linguagem C suficiente para escrever programas realmente executáveis
  • Inclui variáveis globais, funções, instruções if/while, operadores, desreferenciação de ponteiros, comentários e assembly inline, permitindo executar programas completos mesmo com uma estrutura mínima
  • Para simplificar o tokenizador, foi projetada a linguagem Barely C, com tokenização baseada em espaços e uso de hash com atoi(), preservando a sintaxe existente de C ao mesmo tempo em que alcança uma redução extrema de tamanho
  • No processo de otimização do código, foram aplicadas várias técnicas de compressão em nível de assembly, como eliminação de saltos, fusão de chamadas, uso de offsets de 8 bits e uso de stosw/lodsw, reduzindo o tamanho de 468 bytes para 303 bytes
  • Como resultado, foi implementado dentro de 512 bytes um compilador C completo contendo tokenizador, parser, gerador de código e runtime, mostrando um caso extremo de minimização de software

Visão geral do SectorC

  • SectorC é um compilador C escrito em assembly x86-16 que cabe inteiramente em um setor de boot de 512 bytes
    • O repositório no GitHub é xorvoid/sectorc
    • A linguagem suportada é um subconjunto de C em nível suficiente para escrever programas reais
  • Os recursos suportados incluem variáveis globais, funções, estruturas de controle (if/while), vários operadores, desreferenciação de ponteiros, assembly inline e comentários
  • Como programa de exemplo, é apresentado um código que desenha uma animação de onda senoidal em modo VGA

Contexto do projeto e abordagem

  • Como um tokenizador C tradicional seria grande demais para caber em 512 bytes, foi necessário simplificar a própria estrutura da linguagem
  • Grande insight #1: foi adotada uma estrutura de tokens separados por espaços, como em Forth, para projetar uma linguagem derivada chamada “Barely C”
    • Exemplo: uma construção como int(main)(){while(!done){ é tratada como um único “mega token”
    • Ainda assim, ela continua sendo reconhecida como código C válido por compiladores C existentes
  • Grande insight #2: a função atoi() é usada como se fosse uma função hash para converter tokens em números
    • Literais inteiros, palavras-chave e identificadores são todos tratados com base no resultado de atoi()
    • Os identificadores são acessados como índices em um array de 64K

Implementação do Barely C

  • A primeira implementação tinha 468 bytes e usava uma estrutura de parser recursivo descendente com tokens baseados em atoi
    • Sem tabela de símbolos, acessando diretamente um segmento de 64K por valor de hash
    • A geração de código segue o estilo do OTCC, usando o registrador ax como armazenamento do resultado
  • Depois, foi testada uma abordagem de byte-threaded code para experimentar uma estrutura no estilo Forth, mas ela acabou sendo mais ineficiente dentro do limite de 512 bytes e foi descartada

Técnicas de minimização de código

  • Retornando a uma estrutura linear, o tamanho foi reduzido de 468 bytes → 303 bytes
    • Foram usadas técnicas como eliminação de saltos (fall-through), tail-call, fusão de chamadas (call fusion), uso de stosw/lodsw e manutenção de offsets de salto de 8 bits
  • Isso garantiu 207 bytes livres para implementar recursos adicionais

Expansão para recursos completos de C

  • Com mais 200 bytes, foi alcançado o suporte a uma sintaxe C completa
    • Blocos if/while aninhados, vários operadores binários (+, -, *, &, |, ^, <<, >>, ==, !=, <, >, <=, >=)
    • Suporte a definição de funções e chamadas recursivas, assembly inline (asm) e comentários de uma linha e múltiplas linhas
    • Por meio da tabela de operadores (binary_oper_tbl), cada operador é definido em 4 bytes, permitindo tratar 14 operadores em 56 bytes

Estrutura da gramática

  • A gramática completa é composta por program, var_decl, func_decl, statement, expr e outros elementos
  • Há suporte tanto para comentários // quanto /* */
  • O próprio texto de definição da gramática tem 704 bytes, maior que a implementação real

Assembly inline e runtime

  • Com a instrução asm, é possível inserir diretamente código de máquina x86-16
    • Trata-se de um recurso essencial para lidar com I/O
  • O runtime (rt/) é composto por dois arquivos escritos em C
    • rt/lib.c: rotinas de biblioteca baseadas em assembly inline
    • rt/_start.c: ponto de entrada do programa _start()

Programas de exemplo

  • examples/hello.c: imprime texto diretamente na memória 0xB8000
  • examples/sinwave.c: exibe uma animação de onda senoidal no modo VGA 0x13
  • examples/twinkle.c: toca “Twinkle Twinkle Little Star” no alto-falante do PC (com aviso de som)

Conclusão

  • SectorC é um compilador C ultracompacto que realizou um objetivo que parecia impossível,
    mostrando um caso extremo de minimização de software e design criativo de linguagem
  • O texto termina com opções humorísticas de “o que aprendemos”,
    enfatizando de forma satírica a postura de desafiar o impossível e o valor de simplificar software

1 comentários

 
GN⁺ 2026-02-08
Comentários no Hacker News
  • Se uma implementação assim existisse nos anos 1980, parece que o padrão C teria acabado com uma regra dizendo que, se tokens diferentes causassem uma colisão de hash no mesmo valor de 16 bits, isso provocaria comportamento indefinido (UB)
    Os compiladores otimizadores dos anos 2000 talvez simplesmente otimizassem esses tokens para no-op 😉
    • “Você não ativou a opção -wTokenHashCollision! O UB aconteceu por causa da sua ignorância. A especificação é perfeitamente clara!” foi uma resposta em tom de piada
    • É engraçado demais por ser realista. LMAO
  • Parece parecido com o compilador C de boot sector X86-16 que eu fiz recentemente
    Criar jogos de boot sector é uma experiência realmente mágica e nostálgica. Faz lembrar a época em que programar era de fato divertido
    É uma pena que, na era atual de IA, projetos assim sejam tão subestimados
    Link do meu projeto
    • Hum, o que o texto aborda não é C completo, e sim um compilador de linguagem parecida com C que cabe em 512 bytes
      Seu projeto parece ter uma opção para gerar código para boot sector.
      Ambos são interessantes, mas em comum eles têm só “boot sector”, “C” e “compiler”
    • Concordo com a parte de “a época em que programar era realmente divertido”, mas agora muito mais gente consegue fazer a mesma coisa
      Então dá a sensação de que eu já não sou mais especial
  • Projetos assim lembram o quanto o desenvolvimento moderno se afastou do hardware
    Continuamos empilhando abstrações, a ponto de até para rodar um “Hello World” precisarmos de 200MB de node_modules
    Enquanto isso, alguém coloca um compilador C em 512 bytes
    Não que todo mundo devesse escrever código de boot sector, mas ler projetos assim é uma experiência realmente humilhante. Também tem muito valor educacional
  • Talvez eu seja justamente o autor deste projeto. Foi muito divertido fazer isso!
    • Ficou incrível. Eu também estou fazendo um compilador C minimalista, mas em vez de caber em um boot sector, ele mira sistemas de 8 bits
      Este projeto mostra muito bem como a estrutura central de C é simples.
      É interessante que C tenha evoluído da linguagem B, e B de uma versão reduzida de Fortran
    • Fico me perguntando o quanto isso poderia ficar ainda menor se if, while e for fossem convertidos em rotinas simples de goto
      Porque em assembly, no fim das contas, só existe jmp.
      E também deveria ser “chose your own adventure”, não “choose your own adventure” :)
      Eu amo minimalismo
    • Este compilador, ou a ideia de “barely-C”, também talvez pudesse ser usada em uma cadeia de bootstrapping
      Algo como começar de um binário minúsculo e específico de plataforma e ir construindo ferramentas e compiladores cada vez mais complexos
      Como exemplo, dá para ver os projetos mishmashvm e tcc_bootstrap_alt
  • Projeto lindo. Só acho que seria melhor adicionar 2023 ao título logo
    A discussão da época aconteceu aqui
    • Obrigado! Na versão com expansão da macro, daria para organizar assim:
      SectorC: A C Compiler in 512 bytes - link - maio de 2023 (80 comentários)
  • É interessante comparar isso com o compilador C de 100 mil linhas que o Claude fez em 2 semanas por 20 mil dólares e que apareceu ontem no HN
    • Comparação divertida, mas aquele consegue compilar o kernel Linux e gerar código para várias arquiteturas
      Já este projeto só consegue lidar com parte de C
      Ou seja, isto é mais um compilador para um subconjunto de C do que um compilador C completo.
      O código que este compilador consegue compilar também pode ser compilado por um compilador C de verdade, mas o contrário não
  • A forma de fazer uma pseudo tabela de símbolos usando hash de tokens é realmente elegante
    • Eu também já gerenciei identificadores apenas por valores de hash de símbolos ao criar um parser para uma ferramenta de testes
      Espero não ter usado símbolos suficientes para provocar colisões em 32 bits
    • Também pensei a mesma coisa. O truque de hash de tokens é realmente muito legal
      Aliás, ainda sobram 21 bytes de espaço livre entre 0x01e0 e 0x01fd. Talvez dê para colocar mais alguma coisa ;)
  • A parte sobre “atoi() agir como uma função de hash ruim para texto comum” é interessante
    Mas, pelo que eu lembro, atoi() era definido para retornar 0 em entradas inválidas
  • bastante interesse em compiladores para boot sector
    Ao rodar no Linux, basta trocar a chamada do qemu de coreaudio para alsa
    Enviei um pull request no GitHub para isso. Se o autor achar meu estilo verboso de script shell aceitável, talvez faça merge
  • Foi um texto muito legal! Me lembrou do SO de boot sector que eu fiz no passado
    Acho que chegou a hora de adicionar um compilador C nele
    Link do meu projeto de SO