Now that you are familiar with the Hack programming language, it's time to see what we can actually do with this language. And so, in the next three units we are going to talk about the general subject of low level Programing, and in particular programming in the Hack machine language. Now before we get started I'd like to give you an overview of the two instructions that we have in the Hack language. So we have the A-instruction, which is used to set the value of the A register to a particular value. And we have the C-instruction which is used to do three different things. We can compute a certain expression, we can store the value of this computation in some destination, and optionally we can, based on the value of this computation, we can decide to jump and execute something which exists in a different region of the program, we can perform a goto operation. Now, this language, as you clearly see in this slide, is symbolic. It consists of mnemonics. And computers don't understand the symbols other than zero and one. And therefore before we can execute anything which is written in symbolic Hack machine language, we have to first translate it into binary code. And this is something which is typically done by a program called assembler. And what we see here is this program in action. It takes a file which is written in a symbolic language and it translates it into another file written also in symbols but these symbols are only zeros and ones. Having produced the target code in binary code we can actually take this file, load it into the Hack computer, and finally execute the intended program. So this is the Hack assembler and in week six of this course we will actually build such an assembler, but for now I just want you to remember that it is available to you if you want to use it. The other option of translating symbolic programs into binary code is to use the supplied CPU Emulator. You can take any program that you write in a symbolic Hack language, load it directly as is into the CPU Emulator, and the CPU Emulator is just a Java program and it has an icon that allows you to load files into the instruction memory. If you load these files into the instruction memory the CPU Emulator gives you this very nice service of translating the programs on the fly into machine language. So, once this happens, you can actually execute the program in the CPU emulator. And the result is that the CPU emulator is a very friendly tool for debugging and executing Hack programs in simulation. And therefore, we recommend that if you want to play with the code snippets that you will see in the subsequent units, we recommend that you do it using the supplied CPU emulator. All right. So, moving along. What do we mean when we talk about low level programming? Well, surprisingly enough, we mean a whole bunch of issues that you find in any programming language. Things like working with memory and variables and branching, iteration, pointers, inputs and outputs. These idioms are widely used in any programming language, and the Hack machine language is no exception. So, in this unit, we'll begin to talk about registers and memory. And in subsequent units, we'll talk about the other subjects which are slightly more advanced. All right, so registers and memory is the bread and butter of low level programs and that's what you do all the time you manipulate registers which are either the two standard registers that we have D and A which reside inside the CPU. If you recall the data register can hold a single 16 bit value. The A register can hold either a data value or an address depending in the context in which the programmer wants to use this register. And finally, we use the letter M, or the pneumonic M, to refer to the currently selected memory register. If you recall, the A register has this nice side effect that when you load it with a particular value it ends up selecting one register from the RAM. This register, in our language, is called M. So you can then say something like, M equals minus one or M equals zero, and so on and so forth. All right, so these are the registers of interest that we're going to manipulate. And here are some examples of what actually can be done with these registers. Let us assume that you want to store the number ten in register D. Well it turns out that there's no direct way to do it. If you look up the language documentation there's no C instruction that lets you do something like that. So we have to do it indirectly. And what we do is we set the A register to 10, and then we say D equals A. Simple. Moving along, what about incrementing the value of D? Well it comes out that this actually can be done directly in one instruction only. Because once again if you look up the documentation of the C instruction you would see that you can tell the ALU to compute the value of D plus one and then you can take the result and store it in D. So effectively, we perform a D++ operation. What about setting D to the value of RAM(17)? Well, whenever you want to access a particular memory register, you first have to address the memory, you have to select this register. So we pre-empt this operation with an x17 and now having selected the register of interest we set D to the value of this register. Likewise we can do the reverse operation, we can do RAM(17)=D and we do exactly the same but in reverse. Moving along, what about setting RAM(17) to 10? Well I can do this using a combination of what I did before. First of all I acquire the constant ten somehow., you know, using these two instructions. And then I set the value of RAM(17) to the value of D, which by now is 10. What about setting RAM(3) to RAM(5)? Well, once again, we can do it using similar operations, and if you want you can stop the video, take another look at all these five code examples, and convince yourself that they do what they intend to do. All right. So let us take these memory manipulation operations, and registers manipulations, and put them in the context of an actual program. So here's a program which is designed to add up two numbers, and store the results. As somewhere in memory. So we assume that before the user runs this program the user has placed two values, like let's say, five and seven in RAM 0 and RAM 1, and once you run this program, the program will end up adding up these two numbers, five and seven in this example, and storing the result in RAM 1, so, RAM 1 will contain 12 if everything works well. Why RAM 0, RAM 1 and so on? Well, that’s just an arbitrary decision, we decided to use RAM 0 and RAM 1 as the input of this program and RAM 2 as the program's output. So how do we do it? Well, you may have guessed, we use very similar operations to what we did before, and if we run this program, hopefully it will compute the sum of RAM 0 and RAM 1. Now before we go on, I'd like to remind you that instructions in the Hack language have implicit line numbers, you don't see them when you write the program, but these numbers kind of lurk in the background, and when you translate this program and load it into memory, there's some interesting observations that we have to make. First of all, white space is ignored, and the only instructions that get into play, so to speak, are the real instructions, the instructions that have line numbers in this example here. And in addition, it's important to remember that what we see here in the instruction memory is a symbolic view of this program. This program as such cannot execute on the computer because the computer cannot handle symbols other than zero and one, but if you played with our CPU Emulator, you know that you can tell the emulator to show you the contents of the instruction memory in binary and if you do it, you will see the program in this manifestation, and in this state, the program can actually execute on the computer. But typically, once again, it's much easier to think about the program, talk about it, and debug it when the program is written in symbolic form, and therefore we recommend that when you try to understand what a program is doing, do it symbolically and only when you're ready to run it, if you want you can take a look at the binary code, but it's very difficult to decode whether the binary code is doing anything, so we are fortunate to have all these symbols to make our programs more readable. All right, so with that in mind, I'd like to invoke the CPU Emulator and give you a demo of how this program is actually executing. So the purpose of this demo is to illustrate how to write a little program in the Hack symbolic language and then run it on the CPU Emulator. So I have two windows opened up here, one is the CPU Emulator in the foreground, and in the background, I have a simple text editor that I can use to write my program, so let's write it. We'll begin with some comments, which describe what this program is doing, so let's say. Adds up two numbers, and let's give some usage advice to the person who's going to use this program, put the values that you wish to add. In RAM 0 and RAM 1. And let's add here some more information, RAM 2 becomes RAM 0 plus RAM 1, all right, very nice, so, let us begin to write the program. I used some indentation for purposes that will become clear in subsequent units. So I do @A, I'm sorry, @0, D=M, @1, D=D+M, and now we can put the result, @2, M=D, and that's the end of the program. Let's save the program using something that you cannot see now because it's far away on the screen. So, we want to save the program, we'll give it the most imaginative name, demo.asm. We save it, and now we can go back to the CPU Emulator and load the program. So I click the load button, and let's see, I should have a directory called program examples, and here it is, and demo is right here, so I pick demo, I load it, and here is the program that I wrote. Now, notice that the program contains only the real instructions, if you go back to the source, we see that we have comments, white space, and so on. So when you load a program into the Emulator, you get to see, or actually the only instruction, the only lines that get loaded, so to speak, are the real instructions. And as these instructions are being loaded into this GUI here, they're also being translated into machine language, and I can see that if I change the representation here to binary and I see the program as it really is, inside the ROM in binary code. But once again, it's much more convenient to see this program in, I'm sorry, in symbolic code. Okay, so, I was told that I have to put some values in 0 and 1, so, I go ahead and put the value 5 here and 7 there, and then, I begin to run the program. So, lets see, we execute the first command and we see that nothing happens yet, but A became zero. And then we do the equals M and we see that the D register now contains five, which is very nice indeed. Then we do @1 and we see that A contains one. Let's do D=D+M, we see that D became 12. Then we set A to two, we do M=D and we see that lo and behold RAM 2 contains 12, which is exactly what we wanted to get, so the program seems to be working. Looking. So having seen the demo that we just went through. And having seen also the problem that we encountered at the end of this demo. Let us see, what can we do in order to terminate a program properly? Now, to remind you, the problem that we had is that the flow of control became kind of uncontrollable. And basically, we told the computer to execute every instruction, everything was just fine, but then other so called instructions came into play, and the computer basically went out of control. Now, if I were a hacker. If I were a bad hacker. And I would have seen this pattern of execution. I would say, well, you know? Maybe I can write some malicious program, and put it somewhere downstream in this memory. And then I would let the user run his or her program naively, the user will happily run his program the program will actually do what it's supposed to do. But then unknowingly the computer will continue executing and then boom my program will go to work and will start to do some bad things like deleting some random files on the user's computer. So what can we do in order to avoid this potential problem? By the way, this particular attack is called NOP slide and NOP stands for null instructions or null hop codes. And what we have here in instructions six onward are null instructions and Beth Hecker can use these instructions to slide the flow of control to an area of the memory. That he controls and then something bad can happen. What can we do to avert this problem? And in general, what can we do to terminate the problem properly? Well one thing that you have to understand is that computers never stand still. They always do something. Even when you don't touch the keyboard, there are many processes running in the background. So in the head computer, because we don't want the computer to do something crazy, we might as well cause the computer to do something that we control. So what we can do is we can end the program with an infinite loop. We can add two commands like @6 and then in seven JMP to six so we have once again @6 and then in seven JMP to six, JMP, six, JMP, six and so on and we have this infinite loop and everything is under control because this is something we intended our program to do. So as a best practice advice, we recommend that you end every one of your programs with an infinite loop. All right, before the end of this unit, I'd like to say a few things about another feature of the language that we haven't yet discussed. And by saying this, I’m basically going to complete the specification of the hack machine language. The language features several built in symbols and here they are. First of all, we have a set of 16 so-called virtual registers, or to say it more accurately, we have a set of 16 labels that we use as if they represented virtual registers. And these labels range from R0 to R15. And the contract is such that whenever the assembler or the translator sees a label like R3, it will replace it with a number three, that's all. So you may ask yourself, why do we need these fancy labels. Well, here's an example where these labels can come to play. This is a very simple piece of code in which we set RAM5 to 15. Now let's read carefully what is going on here. In the first pair of instructions we use the a register as a data register. We put the number 15 into a and then we move it into d. In the second pair of instructions we do something remarkably different. We use the F5 command to address the memory. To select memory register number five and then we do m equals d. So there's something, you know, troubling about this code. First of all, we do two very different things, but we use exactly the same syntax, at number that's one thing which is a little bit I think disconcerting. And the other thing which is somewhat troubling is that when you read a singular instruction, you have no idea what the program you wanted to do until you see the next instruction. So how can we make this thing more readable? Well our advice is that whenever you want to address one of the first 16 registers in the memory, use the label convention and then anyone who reads your program will know exactly what you want to do, including yourself. Because you know machine language programs are difficult to read and comprehend and therefore we have to make every effort to make them more readable so that next time you see a program a week from now or two weeks from now you will know what the program is doing. So in the second example that you see on the right it's a very small difference compared to the left one but it's much more readable. And also effectively, the program will do exactly the same thing. Because once it will get translated, the R5 will change to five and then we are back to where we were before. So this is the motivation why we recommend to use these so called virtual registers. There's one thing that you have to worry about, and this is the fact that like many other programming languages, hack is case-sensitive. An uppercase R5 is not that same as lowercase r5. And we recommend that you remember this observation here because If you forget it, it can cause all sorts of very exotic bugs and in the future if you have a program that has no syntax problems and you have no idea what this program is doing. There's a good chance that you misspelled one of your symbols. So keep this in the back of your mind when you run your own symbolic program. What other symbols do you have in the language? Well we also have screen and keyboard, which we discussed previously in one of the units. They stand for the base addresses of the screen and the keyboard memory maps. And we also have a set of six additional symbols that we don't really use in this course. So let me wrap up they symbols, the built in or the predefined symbols in the Hack language. We have 16 virtual registers. We have two symbols that stand for base addresses of input/output maps, and we have a set of six symbols which are used by people who want to write virtual machines and compilers for high level languages. That will operate on top of the Hack platform. Now this is something that we actually do in the second part of this course, called Nand to Tetris Part II, but we want use this six registers in the present course. All right, so this has been a brief overview of working with registers and memory. And in the next unit we are going to talk about branching, variables, and iteration.