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 programming, 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 base 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 go to operation. Now, this language, as you clearly see in the 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 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. As 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 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 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 mnemonic, 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 are 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 10 in register D. Well, it turns out that there is 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 = A. Simple. Moving along, what about incrementing the value of D? Well, it turns 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 will see that you can tell the ALU to compute the value of D+1 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 preempt this operation with an @17. And now, having selected the register of interest, we set it, or 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, 10, somehow using these two instructions, and then I set RAM[17] to the value of D which by now is 10. What about setting the 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 take two values which are stored in RAM[0] and RAM[1], add them up and save the result in RAM[2]. Now, why these particular three words RAM [0], [1] and [2]? Well, this is an arbitrary choice we just decided that we'll use the first two words in the memory for input so to speak and the third memory word for the output of this program. 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 are 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. You know, 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 are ready to run it, if you want, you can take a look at the binary code. But it's very difficult to decode what 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 is 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 use some indentation for purposes that will become clear in subsequent units. So I do @0 D=M, @1 D=D+M. And now we can put the result in 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's 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 reliance 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 symbolic code. Okay, so, I was told then I have to put some values in zero and one. So I go ahead and put the value 5 here and 7 there. And then I begin to run the program. So let's see. We execute the first command and we see that nothing happens yet. But the A became 0 and then we do the equals M and we see that the D register now contains 5 which is very nice indeed. Then we do @1 and we see that A contains 1. Let's do D=D + M, we see the D Became 12, then we set A to 2. 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. Before we end this demonstration, I would like to present the fast forward control and also use this opportunity to show you something bizarre that may happen if you don't take proper action. So I have loaded the same program into this emulator and now I'm using different test values, 350 and minus 40. And then I will use the fast forward control to run the program Unattended so to speak. And we see that the program runs properly and in fact it comes out with a right result. 350 plus minus 14 is indeed 310. But we see that the computer is continuing to execute the so called program. Where in fact the program has ended already. Right, as far as we are concerned the program ended but as far as the computer is concerned the program actually continues and it seems that things are getting out of control. So having seen the demo that we just went through and having seen the problem that we encountered at the end of this demo let's us see what can we do in order to terminate a program properly. Now to remind you the problem that we have is the flow of control became a kind of uncontrollable. And basically you know, we told the computer to execute every instruction and 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 hackers, if I were a bad hacker and I would have seen this pattern of execution I would say, well 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 random files on the user's computer. So, what can we do In order to avoid this potential program. By the way this particular attack is called the NOP slide and NOP stands for Null instructions or Null Opcodes and what we have here in instructions six onward are Null instructions and a bed hacker can use this 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 program 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 hacked 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 end two commands like @six and then in seven jumped to six so we have once again @six and then in seven jumped to six, jump six, jump six and so on. And we have this infinite loop and everything is under control because this is something that we intended our program to do. So, as the best practice advice, we recommend that you end everyone of your program with the infinite loop. All right, before the end of the tonic, 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 sixteen so called virtual registers. Or to say it more accurately, we have a set of sixteen labels that we use as if they represented Virtual registers. And these labels range from R0 to R15. And the construct is such that when the assembler or the translator sees a label like R3, it will replace it with a number 3. That's all. So, you might ask yourself, why do we need this fancy labels? Well, here's an example where this labels can come to play. This is a very simple piece of code in which we set RAM 5 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 fifteen into A, and move it into D. In the second pair of instructions, we do something remarkably different. We use to @five command. To address the memory, to select memory register number five and then we do M equals D. So there's something 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 single [INAUDIBLE] instruction, you have no idea what the program I 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 sixteen registers in the memory, use the label convention and then anyone who reads your programme will know exactly what you want to do including yourself because 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 translated the R5 will change to five and then we are back to where we are before. So, this is the motivation why we recommend to you the 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 the 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 programs. 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. We also have a set of six additional symbols that we don't really use in this course. Let me wrap up the built-in or pre-defined symbols in the Hack language. We have sixteen virtual registers, we have two symbols that stands for base addresses of input, output maps. And we have 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 won't use these 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're going to talk about branching variables and iteration.