19. Hardware Simulator#
ls
example seawulf
github-in-class-brownsarahm-1 test
kwl testobj.md
nand2tetris tiny-book
cd nand2tetris/
ls
projects tools
cd tools
ls
Assembler.bat JackCompiler.bat VMEmulator.sh
Assembler.sh JackCompiler.sh bin
CPUEmulator.bat OS builtInChips
CPUEmulator.sh TextComparer.bat builtInVMCode
HardwareSimulator.bat TextComparer.sh
HardwareSimulator.sh VMEmulator.bat
and then
bash CPUEmulator.sh
Important
On windows you need to use the .bat file
On Windows: Double click on the CPUEmulator.bat file
We’re going to use the test cases from the book’s project 5:
Load Program
Navigate to nand2tetris/projects/05
We’re not going to do project 5, which is to build a CPU, but instead to use the test.
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.
19.1. 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 what 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)
Explore Badge Idea
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)?
19.2. Machine Representation#
python
19.3. 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:
Python 3.8.3 (default, Jul 2 2020, 11:26:31)
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 2+3
and it will print the result
5
We can create variables
>>> name = 'sarah'
but assignment does not return anything, so nothing is printed.
We can see the value of a variable, by typing its name
>>> name
'sarah'
19.4. Characters to Integers#
Python provides a builtin function ord
to find the Unicode key for that character.
>>> ord('s')
115
>>> [ord(char) for char in name]
[115, 97, 114, 97, 104]
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.
>>> name ='denno'
>>> [ord(char) for char in name]
[100, 101, 110, 110, 111]
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.
19.5. Why is the object file not human readable?#
The object file displays 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.
Python also allows us to change content into a byte array:
>>> bytearray(34)
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 also apply this to a whole string worth of integers
>>> name_ints = [ord(char) for char in name]
>>> name_ints
[115, 97, 114, 97, 104]
We can then write this to a file, by getting the actual byes 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.
>>> with open('name.txt','wb') as f:
... f.write(bytes(bytearray(name_ints))
...
...
...
...
...
KeyboardInterrupt
I forgot the final closing )
but did not see my own error, so I used crt+c to quit and get a fresh start.
>>> 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
>>> name_ints = [ord(char) for char in 'asldfkaslfjs']
>>> with open('name.txt','wb') as f:
... f.write(bytes(bytearray(name_ints)))
...
with more characters, more bytes
12
>>> name_ints = [ord(char) for char in name]
>>> with open('name.txt','wb') as f:
... f.write(bytes(bytearray(name_ints)))
...
5
>>> exit()
If we exit python we can look at the file and see how it is interpreted.
Remember we wrote, as binary, the numbers, 115, 97, 114, 97, 104
to the file
cat name.txt
but it is interpretted as the string by the terminal.
sarah
Back in python
python
Back in Python, we can read the file as binary or as regular, first reading it as a string, we et the char characters
```Python
Python 3.8.3 (default, Jul 2 2020, 11:26:31)
[Clang 10.0.0 ] :: Anaconda, Inc. on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> with open('name.txt','r') as f:
... print(f.read())
...
sarah
>>> with open('name.txt','r') as f:
... name_in = f.read()
...
>>> type(name_in)
<class 'str'>
by checking the type we can confirm by defualt it reads the bytes in and finds a string.
We can use rb
as the mode to read it as binary
>>> with open('name.txt','rb') as f:
... name_in_bin = f.read()
...
>>> type(name_in_bin)
<class 'bytes'>
This is binary, but the python interpreter also prints it as a string, the b
indicates the object is actually binary type.
19.6. Bit level Operations#
We can operate on integers bit by bit.
If we shift 3 one to the right we transform from 11
to 1
, we can use the >>
operator to do this.
>>> 3 >> 1
1
We can shift it the other way too: 11
to 110
so we get from 3 to 6
>>> 3<< 1
6
We can also use logical operators
>>> 1 & 0
0
>>> 7 & 15
7
But these do not work for non integer values. We will look at how these work next class and see why.
>>> 3.4 & 4.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for &: 'float' and 'float'
This is exclusive or, or xor, where it is only a 1 if exactly one bit of the inputs is a one. For the same number it will always be a zero
>>> 3^3
0
inplace swap
you can use xor to inplace swap two values, instead of using a temp variable
The |
does or
>>> 3 | 1
3
>>> 3|6
7
The ~
does negate.
>>> ~4
-5
>>> exit()
19.7. Review today’s class#
Add
bitwise.md
to your kwl and write the bitwise operations required for the following transformations:4 -> 128 12493 - > -12494 127 -> 15 7 -> 56 4 -> -5
shifts
For the following figure out the bitwise operator:
45 (_) 37 = 37 45 (_) 37 = 45 3 (_) 5 = 7 6 (_) 8 = 0 10 (_) 5 = 15
ands/ors
Create
readingbytes.md
and answer the following:1. if a file had the following binary contents, what would it display in the terminal? Describe how you can figure this out manually and check it using C or Python. '01110011011110010111001101110100011001010110110101110011' 1. What is the contents of the `sample.bn` if `cat sample.bn` is: ` ¢¶"*`
Read about integer overflow and in
overflow.md
describe what it is, use an example assuming an 8 bit system.
19.8. Prepare for Next Class#
In fractionalbinary.md use 8 bits to represent the following numbers by using 4 bits as usual (8,2,4,1) and the other 4 bits are 1/2, 1/4, 1/8, 1/16th:
3.75
7.5
11.625
5.1875
Add to your file some notes about the limitations of representing non integer values this way. How much would using more bits help with, what limitations are not resolved by adding more bits.
19.9. More Practice#
Add bitwise.md to your kwl and write the bitwise operations required for the following transformations:
4 -> 128 12493 - > -12494 127 -> 15 7 -> 56 4 -> -5
For the following figure out the bitwise operator:
45 (_) 37 = 37 45 (_) 37 = 45 3 (_) 5 = 7 6 (_) 8 = 0 10 (_) 5 = 15
Create readingbytes.md and answer the following:
- if a file had the following binary contents, what would it display in the terminal? Describe how you can figure this out manually and check it using C or Python. '01110011011110010111001101110100011001010110110101110011' - What is the contents of the `sample.bn` if ther reesult of`cat sample.bn` is: ` ¢¶"*`
Read about integer overflow and describe what it is, use an example assuming an 8 bit system, and how integer overflow is handled in Python, C, Javascript, and one other language of your choice in overflow_languages.md
Contribute a new, not previously posted, use of bitwise operators to the discussion
19.10. Experience Report Evidence#
none today.