Skip to content

EdenCompiler/cl-lc3

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

LC-3 em Common Lisp

Material didático para aprender como funciona um computador por dentro, construindo do zero, em Common Lisp:

  1. uma máquina virtual (VM) que executa código de máquina;
  2. um montador (assembler) que traduz assembly para código de máquina.

O alvo é o LC-3 (Little Computer 3), um computador didático de 16 bits muito usado em cursos de arquitetura de computadores: pequeno o bastante para caber na cabeça, completo o bastante para rodar jogos de verdade — um rogue e até o 2048.


Por que LC-3?

Característica Valor
Palavra 16 bits
Registradores 8 de uso geral (R0–R7) + PC + COND
Memória 65.536 posições (2¹⁶)
Instruções 16 opcodes

Com tão pouco já dá para entender o ciclo fundamental de todo processador:

BUSCAR  →  DECODIFICAR  →  EXECUTAR  →  (repete)
 fetch        decode         execute

Arquivos

Arquivo O que é
lc3.lisp A máquina virtual. Lê um .obj e o executa. Comentado como tutorial (13 partes).
lc3as.lisp O montador. Lê um .asm e gera um .obj. Comentado como tutorial (6 partes).
rogue.asm Jogo rogue em assembly LC-3 (Justin Meiners, 2017). Programa de teste.
2048.asm Jogo 2048 em assembly LC-3 (Ryan Pendleton, 2014). Programa de teste maior (~1000 linhas).

Tudo em Common Lisp puro (SBCL). Sem dependências externas.


Como rodar

Requer SBCL (Linux).

# 1) Montar: assembly  ->  código de máquina
sbcl --script lc3as.lisp rogue.asm rogue.obj

# 2) Executar o código de máquina na VM
sbcl --script lc3.lisp rogue.obj

O jogo

  • W A S D — mover
  • Alcance a porta D para vencer
  • Ctrl-C — sair

Legenda do mapa:

Símbolo Significado
@ jogador
D porta (saída)
# parede
(espaço) túnel

2048

sbcl --script lc3as.lisp 2048.asm 2048.obj
sbcl --script lc3.lisp 2048.obj
  • Responda y à pergunta "Are you on an ANSI terminal?"
  • W A S D — juntar as peças
  • Combine os números até chegar a 2048

Prova de que o montador aguenta um programa grande: o 2048.asm tem ~1000 linhas e vira 1138 palavras de código de máquina.


Como funciona

A máquina virtual (lc3.lisp)

O coração é o laço buscar–decodificar–executar:

(loop while *running*
      do (let ((instr (mem-read (reg +r-pc+))))   ; 1) BUSCAR a instrução do PC
           (setf (reg +r-pc+) (u16 (1+ (reg +r-pc+))))  ; avança o PC
           (execute instr)))                      ; 2-3) DECODIFICAR + EXECUTAR

Pontos que o tutorial explica em detalhe:

  • Aritmética de 16 bits — Lisp tem inteiros infinitos, então toda conta é "cortada" de volta para 16 bits com a máscara #xFFFF (macro u16).
  • Decodificação por máscara de bits — os 4 bits altos são o opcode; cada campo (registrador, imediato, deslocamento) é extraído com deslocamentos e logand.
  • I/O mapeado em memória — ler o endereço mágico do teclado (0xFE00) consulta o teclado real.
  • Traps — chamadas de "sistema" para entrada/saída (GETC, OUT, PUTS, HALT…).
  • Terminal em modo cru — via FFI (sb-alien), mexendo na struct termios para ler tecla a tecla sem Enter e sem eco.

O montador (lc3as.lisp)

Problema central: referências para frente (saltar para um rótulo que ainda não apareceu). Solução clássica — duas passagens:

  1. Passagem 1 — percorre o texto só para mapear cada rótulo ao seu endereço (a tabela de símbolos).
  2. Passagem 2 — agora que todos os endereços são conhecidos, gera os 16 bits de cada instrução.

A saída é um .obj em big-endian: a primeira palavra é o endereço de carga (.ORIG), seguida do programa.


Fluxo completo

rogue.asm  ──(lc3as.lisp)──►  rogue.obj  ──(lc3.lisp)──►  jogo rodando
 assembly      montador        código        VM            no terminal
              2 passagens     de máquina   fetch/decode/exec

Sintaxe de assembly suportada

Diretivas: .ORIG .FILL .BLKW .STRINGZ .END

Instruções: ADD AND NOT LD LDI LDR LEA ST STI STR BR(+n/z/p) JMP JSR JSRR RET RTI TRAP

Traps por nome: GETC OUT PUTS IN PUTSP HALT

Números: x1F (hex), #-1 (decimal), rótulos.

Exemplo mínimo (hi.asm):

.ORIG x3000
        LEA R0, MSG
        PUTS
        HALT
MSG     .STRINGZ "Oi!\n"
.END
sbcl --script lc3as.lisp hi.asm hi.obj
sbcl --script lc3.lisp hi.obj

Créditos

  • VM e montador portados para Common Lisp a partir do tutorial Write your own Virtual Machine de Justin Meiners e Ryan Pendleton.
  • rogue.asm por Justin Meiners (2017).
  • 2048.asm por Ryan Pendleton (2014), projeto rpendleton/lc3-2048, licença MIT.

About

Material didático para aprender como funciona um computador por dentro, construindo do zero, em Common Lisp.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors