Laboratory assignment · 17 September

Lab 6: Build a Hack Assembler

Develop a Python program that translates Hack assembly-language programs into the 16-bit binary code executed by the Hack hardware platform.

Back to course home

Objective and contract

What your assembler must do

The generated machine code must match the reference assembler exactly.

Contract

Translate Prog.asm into Prog.hack

Every output line must be the correct 16-bit binary encoding of one Hack instruction.

Input
A valid Hack assembly-language file named Prog.asm.
Output
A binary machine-language file named Prog.hack.
Language
Implement the assembler in Python.
Correctness
Your output must be identical to the output generated by the supplied Nand2Tetris assembler.

Building plan

Implement it in two stages

Get instruction translation working before adding symbols.

Stage 1

Symbol-less assembler

Parse and translate A- and C-instructions in programs containing no labels or symbolic variables.

  • Remove whitespace and comments.
  • Recognize the instruction type.
  • Encode comp, dest, and jump fields.
  • Test first with the L versions of the supplied programs.
Stage 2

Add symbol handling

Extend the assembler with a symbol table and the two passes needed to resolve labels and variables.

  • Predefine the standard Hack symbols.
  • Record label declarations with their ROM addresses.
  • Allocate variables beginning at RAM address 16.
  • Translate the complete programs containing symbols.

Test programs

Use the supplied Project 6 programs

Except for Add, each program has a symbol-less ProgL.asm version and a complete Prog.asm version.

Add

Add.asm

Adds the constants 2 and 3 and stores the result in R0.

Max

MaxL.asm and Max.asm

Computes max(R0,R1) and stores the result in R2.

Rect

RectL.asm and Rect.asm

Draws a 16-pixel-wide rectangle whose height is the value stored in R0.

Pong

PongL.asm and Pong.asm

Translates the large Pong application. Its roughly 20,000 machine instructions make it a useful final stress test. Pong runs slowly in the CPU emulator; this is expected and makes its graphical behavior easier to follow.

Evaluation: Use the symbol-less MaxL.asm, RectL.asm, and PongL.asm files while developing Stage 1. The final evaluation uses Add.asm, Max.asm, Rect.asm, and Pong.asm.

Workflow

Translate and compare

Use the supplied assembler as the reference implementation.

Steps

  1. Open the Nand2Tetris Assembler and load the files in projects/06. Locate Add.asm, Max.asm, MaxL.asm, Rect.asm, RectL.asm, Pong.asm, and PongL.asm.
  2. Download the assembly files to your computer.
  3. Run your Python assembler on a selected input file. For example:
    python assembler Add.asm
  4. For comparison during this lab, save your generated output with a 1 suffix—for example, Add1.hack. The normal final contract remains Prog.asm to Prog.hack.
  5. Open the supplied web assembler, load the original Add.asm, and generate the reference Add.hack.
  6. Upload Add1.hack as the compare file and compare the two binary outputs line by line. They must match exactly.
  7. Repeat the process for Max.asm, Rect.asm, and Pong.asm. Use their L versions to debug the symbol-less stage.
Testing principle

One source program, two assemblers

Prog.asm is translated both by the supplied assembler and by your assembler.

If the reference output Prog.hack and your output Prog1.hack differ, your assembler still contains a bug. Matching every line gives evidence that the translation is correct for that test program.