Install nand2tetris
and make sure you can run the CPU Emulator
On Mac/Linux:
bash CPUEmulator.sh
On Windows: Double click on the CPUEmulator.bat file
18. What happens when we run code?#
How are you today?
Are the explore options on the IDE practice badge helpful?
pick the most appropriate first, but you can also free-response to expand
[ ] Yes, already submitted a proposal
[ ] Yes, about to submit a proposal
[ ] No, I’m still confused
[ ] Kinda, those are not interesting to me, but useful examples
[ ] You gave examples?
[ ] N/A I do not plan explore badges
cd Documents/systems
ls
example seawulf
github-in-class-brownaymanm-1 test
kwl testobj.md
nand2tetris tiny-book
18.1. on Mac/Linux#
cd nand2tetris/tools
and then
bash CPUEmulator.sh
or in file explorer, Double click on the CPUEmulator.bat
file
18.2. On Windows:#
Double click on the CPUEmulator.bat file
you can submit an issue to the coursewebsite if you figure out a CLI way to start it on windows
18.3. To work on the online supported version#
Follow this link for CPU emulator https://nand2tetris.github.io/web-ide/cpu
18.4. Starting the CPU Emulator#
In your terminal:
cd nand2tetris/tools
and then
bash CPUEmulator.sh
Double click on the CPUEmulator.bat file
you can submit an issue to the coursewebsite if you figure out a CLI way to start it on windows for a community badge
18.5. Loading a program#
We’re not going to do project 5, which is to build a CPU, but instead to use the test programs designed to check if a student’s CPU works with the CPU Emulator they provide to understand a simple canonical CPU.
For more on how the emulator works see the CPU Emulator Tutorial.
For much more detail about how this all works chapter 4 of the related text book has description of the machine code and assembly language.
We’re going to use the test cases from the book’s project 5:
Load Program
Navigate to
nand2tetris/projects/05
18.6. How does the computer actually add constants?#
We’ll use add.hack
first.
This program adds constants, 2+3.
It is a program, assembly code that we are loading to the simulator’s ROM, which is memory that gets read only by the CPU.
Run the simulator and watch what each line of the program does.
Notice the following:
to compute with a constant, that number only exists in ROM in the instructions
to write a value to memory the address register first has to be pointed to where in the memory the value will go, then the value can be sent there
The simulator has a few key parts:
address register
program counter
If you prefer to read, see section 5.2.1- 5.2.6 of nan2tetris book
This program the first instruction puts 2 in the address register from the instructions in ROM.
Then it moves the 2 through the ALU to the data register (D)
then it puts 3 on the address register
then it adds the numbers at D and A
then it puts 0 on the address register
then it write the output from the ALU (D) to memory (at the location indicated by the A register)
18.7. The max between two numbers#
To compute the maximum value max.hack
:
subtracts the two numbers
compares the difference to 0
jumps to different lines based on if it is >0 or not
assigns the address regiter a value accordingly
copies one of the two values to the new location
18.8. Explore ideas#
Create some experiments in the simulator and write new programs. Here are some ideas, but you can try anything you are curious about.
What line do you change to change where it outputs the data?
How could you add a third number?
How could you add two pairs, saving the intermediate numbers?
How could you do (4+4)*(3+2)?
18.9. Why is the object file not human readable?#
The object file displayed as random weird characters because it is written to disk in a different format than our terminal reads it in. It is the specific instructions (from the assembly) and memory addresses written to a file in binary. Our terminal reads it one byte (8bits) at a time and interprets those as characters.
Today, we will see how characters are represented as integers, then binary, and read and write files in binary of strings we know to see how it what happens and mimic something like how that object file happened by writing as binary and then reading it as characters.
18.10. Prelude: REPL#
One way we can use many interpreted languages, including Python is to treat the interpreter like an application and then interact with it in the terminal.
This is called the Read, Execute, Print Loop or REPL.
We can execute simple expressions like mathemeatical expressions:
4+5
and it will print the result
9
We can create variables
name = 'ayman'
but assignment does not return anything, so nothing is printed.
We can see the value of a variable, by typing its name
name
and then it prints the value
'ayman'
18.10.1. Characters to Integers#
Python provides a builtin function ord
to find the Unicode key for a character.
This structure, the []
is called a list comprehension. It
executes a for
loop in order to build a list
. In the REPL,
it will then print out the list.
[ord(char) for char in name]
We get the integer representation for each one.
Note that it’s important to try multiple things if you aren’t sure the format you are getting back or to check the official documents, as Denno found by testing this with his name in lowercase.
[ord(char) for char in 'denno']
Coincidentally, the letters in his name all fall into the hundreds and only require 0 and 1 in decimal, so it looks like they could be 3 bit binary numbers.
[100, 101, 110, 110, 111]
Python also allows us to change content into a byte array:
bytearray(34)
It does not display in the 0 and 1 like a string that we might expect, but it does change the type.
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
We can then write this to a file, by getting the actual bytes of each item. First, we will save our list in a variable.
We will use the Python with
keyword to open the file so that we do not to need to separately open and close the file.
in the open
function, the first parameter is the file name and the second is the mode. In this case, we want to write (‘w’) in binary (‘b’). f
is the filestream.
name_ints = [ord(char) for char in name]
with open("name.txt",'wb') as f:
f.write(bytes(bytearray(name_ints)))
it returns 5 in this case, because it wrote out 5 bytes, one per character.
5
If we exit python we can look at the file and see how it is interpreted.
exit()
Remember we wrote, as binary, the numbers, 97, 121, 109, 97, 110
to the file
cat name.txt
but it is interpretted as the string by the terminal.
ayman
python
Back in Python, we can read the file as binary
with open("name.txt",'rb') as f:
print(f.read())
This is binary, but the python interpreter also prints it as a string, the b
indicates the object is actually binary type.
b'ayman'
If we read it not as binary, it returns as the string
with open("name.txt",'r') as f:
print(f.read())
ayman
We can also confirm the type
with open("name.txt",'rb') as f:
content = f.read()
type(content)
<class 'bytes'>
The with keyword is alternative to:
f = open("name.txt",'rb')
f.read()
f.close()
Practice exercise
msg = [65, 121, 109, 97, 110, 32, 83, 97, 110, 100, 111, 117, 107, 10]
bytes(bytearray(msg))
b'Ayman Sandouk\n'
18.11. Experience Report Evidence#
Add in your experience report the modifcations to the code as above.
18.12. Prepare for Next Class#
2025-04-08.md1. Review your idethoughts.md
from a few weeks ago and add some summary notes.
Think about what features or extensions in your favorite IDE you like the most and that you think others may not know about be preppared to share.
18.13. Badges#
Run and examine how rect.hack and max.hack in the
nand2tetris/projects/05/
folder work. Make notes and answer the questions below in assemblyexplore.md.1. Write an excerpt of code in a high level compiled language that would compile into this `max.hack``. 2. What does rect.hack do? 3. What did you learn trying to figure out how it works?
Run and examine how rect.hack and max.hack in the
nand2tetris/projects/05/
folder work. Make notes and answer the questions below in assemblyexplore.md.1. What does rect.hack do? 2. What did you learn trying to figure out how it works? 3. Write an excerpt of code in a high level compiled language that would compile into this `max.hack``. Try writing multiple different versions.