Re: Problems understanding Hardware/Software interface
Posted by ivant on
URL: http://nand2tetris-questions-and-answers-forum.52.s1.nabble.com/Problems-understanding-Hardware-Software-interface-tp4032625p4032627.html
First some terminology: ALU - Arithmetic and Logic Unit, PC - Program Counter, RAM - Random Access Memory, ROM - Read Only Memory, CPU - Central Processing Unit (or Processor), Register - a memory which can hold one machine word.
The CPU contains one ALUs, one PC and 2 registers: A and D. It also has two kinds of connections between them: data connections and control connections.
The CPU "receives" an instruction on it's instruction input. It's just a 16-bit value. The CPU sets its internal control and data paths depending on the various bits in the instruction. For example, if the the leftmost bit (bit 15) is 0, this means that CPU should just treat the value as data and store it in register A. For this it has to set the load input of register A to 1, and its input to instruction bits. It also has to increment the value in the PC by 1. With this its work for this instruction is done.
For other instructions it may need to do some more complex things, like using the ALU to add two numbers, or to set the PC to a specific number, etc. But it all depends on the current inputs and the values in its registers.
The CPU communicates with the outside world through its inputs and outputs. It receives data and instructions in its inputs, and it sends data and "commands" through its outputs. These commands are much simpler than the instructions. They just tell the RAM to load or store a value in a specific address, and they also tell the ROM to read the data from specific address (pc).
The computer needs some more parts besides the CPU. Namely, RAM for the data, ROM for the instructions and keyboard and display for input and output (I/O). We wire them in such a way, so the ROM receives its address from the pc output of the CPU and sends its data to the instruction input of the CPU.
We also connect the RAM, Video and Keyboard to the the inM CPU input and addressM, writeM and outM outputs.
Now let's say that the ROM contains some data, like
ROM[0] = 0000 0000 0000 0001
ROM[1] = 1110 1100 0001 0000
When we start the computer, the CPU's registers A, D and PC are all zeros. This means that the ROM will produce the data stored in ROM[0] and it will send it to the instruction input of the CPU.
The CPU will see this data and will act accordingly: it will treat it as value and just store it in register A and it will increment the PC. So:
A = 0000 0000 0000 0001
D = 0000 0000 0000 0000
PC = 0000 0000 0000 0001
Now this new PC value will be seen by the ROM and it will fetch the contents of ROM[1] and send them to the instruction input of the CPU.
The CPU will have to act according to this new instruction that just came. It looks at its various bits and sees that:
1. This is a computation instruction (Instr[15] = 1)
2. We need to send the value of A to the ALU (Instr[12] = 0). The other ALU input is always the contests of D.
3 We send the bits 6:11 to the ALU as its control bits:
ALU: x=0000 0000 0000 0001
ALU: y=0000 0000 0000 0000
ALU: control bits=110000
So the ALU outputs its x input:out = 0000 0000 0000 0001 (we ignore z and n for the moment).
4. The CPU stores the output of the ALU in register D (Instr[4] = 1)
5. It increments the PC because bits [0:2] are all zeros.
The effect of all this is that now the register D also contains the same value as A, and that we are pointing to the next instruction:
A = 0000 0000 0000 0001
D = 0000 0000 0000 0001
PC = 0000 0000 0000 0010
These two instructions are an example of a small program (or software). They made the CPU store specific values in its internal registers. Further instructions may make it do something even more exciting like adding some numbers, reading and writing values in specific addresses in RAM, and jumping to a different instruction instead of always going to the next one. By deciding what values we put in ROM we can make the computer do various stuff, for example draw some image or let you play tetris. This is the essence of how software commands the hardware.
Now, we people aren't very good with numbers like 1110 1100 0001 0000. We prefer to write something a little bit more understandable, so we give the instructions a "name" or mnemonic. For this instruction this is D=A. So we can write the same program like this:
@0
D=A
This is much clearer to us and we can understand what's going on. But now the computer doesn't! It only understands binary sequences. One way to fix this is to manually translate the mnemonics to binary and store that in the ROM. But we are cleverer than that. We can write a small program, which reads these mnemonics and translates them for us. And we call this program Assembler. And we call this language Assembly language. (Note that different CPUs will have different assembly languages).
If this machine that we're developing was the first computer in the world, we'd have to write this Assembler in assembly itself, and we'll have to manually convert it to binary. After that we can use this program to do that for us and we never again have to manually convert assembly to binary.
Luckily we do have other computers, so we can use them to convert our assembly programs to binary. This is called cross-assembly, because the machine that does the job cannot execute the resulting binary. It's meant for the target machine.