Problem
I've discovered that the hack assembler provided by Nand2Tetris has a minor bug. It incorrectly interprets any value larger than 2^15-1 (32767) as a variable symbol definition. The MIT press 2008 release of the book states on page 72 that "A user-defined symbol can be any sequence of letters, digits" ... "that does not begin with a digit". Yet, as can be seen in the screenshot and included code, the A-instruction "@32768" does NOT write 0 into the A register (since 32768 is 1 followed by 15 zeros in binary and when truncated to 15 bits will be equal to 0) but instead allocates the next available block of memory in the RAM.
The software suite I am using is the latest, version 2.6.
I have also included a patch file for the HackAssembler.java file which correctly throws an error when it recognizes a number that is larger than 2^15-1, since the computer only has 2^15 bits of memory.
All relevant files are linked at the end of this post.
Example
Here is a small program I made to illustrate the issue.
// Testing to see if @32768 is recognized as a value or symbol definition. The
// assembler should either give 15 zeros as the value or give an error that the
// value is out of range. Instead what it does is, it creates a symbol named
// "32768" and stores it in the next available block of RAM (after 16).
// Write 99 into block of RAM at address 32767
@99
D=A
@32767
M=D
// The code above is valid and should assemble and work as intended
// Now write 69 into block of RAM at address 32768 (which doesn't exist)
@69
D=A
@32768
M=D
// When assembling this, the assembler should either give an error saying that
// we're trying to access memory out of bounds and halt, or it should
// convert 32768 to binary and truncate it, giving us 0. But it instead
// recognizes 32768 as a variable symbol definition, which gets stored at the next
// available dynamic RAM block (in this case, 16). This is incorrect behavior,
// because according to the definition of "Constants and Symbols" on page 72 of the
// book, "A user-defined symbol can be any sequence of letters, digits" ... "that does not
// begin with a digit".
// So, now we can do something like:
@66
D=A
@32768
M=D
// Which, according to the manual should store 66 at address 32768, but instead
// stores 66 at 16.
// The same applies to any number larger than 2^15:
@42
D=A
@32769
M=D
// A variable label with name "32769" is created at address 17
Here's the Assembler GUI assembling the code above incorrectly without any errors or warnings:
Attachments
Example hack code: label_test.asm
Example hack code compiled with included assembler: label_test.hack
Example hack code compile with my assembler (which truncates large values): label_test_correct.hack
Fix patch file: HackAssembler.patch
Oh also, thank you for the amazing book and course. Just trying my best to give back for everything this course has taught me.