In the previous two units we talked about machine language in general. And from this unit onward we're going to talk about the Hack machine language, which is the native code that we're going to use in order to operate the Hack computer. Now I don't want to talk too much about the Hack computer itself, because we're going to spend a whole week, or more than one week, talking about the computer. But I do want to give you an overview of the hardware platform on which the machine language is going to operate. As Noam described before, these two things, how to design and machine language design go hand in hand. And there's certain duality between them, and you have to know in order to understand the other. So here's an overview of the computer that you are going to build from next week onward. In fact, you've been building this computer all along, but next week we're going to actually assemble all these pieces together, and we're going to have a computer which consists of three main elements. First of all, we're going to have a 16-bit computer, and a 16-bit computer is a machine in which everything consists of chunks of 16 bits. So if you want to store something, you have to store 16 bits together, if you want to retrieve a piece of data, you have to retrieve 16 bits. If you want to move data from one place to another, you move them in chunks of 16 bits, so this is the atomic unit of information in this computer. Now, the computer is going to consist of a data memory, which is a sequence of 16-bit values, and each of these values is going to be stored in a memory register. And these registers are numbered, for convenience, we can think about them as register zero, register one, all the way to as many registers as we have in the data memory. The instruction memory is a separate memory base that is also a sequence of 16-bit values. And the CPU is a device which is capable of manipulating 16-bit values using mostly the ALU, which resides inside the CPU. And finally, we're going to have all sorts of buses that enable us to move data from once place to another. So we have a data bus that connects the CPU and the data memory, we have an instruction bus that moves the instructions from the instruction memory to the CPU. And we're going to also have some address buses which I didn't put in the picture to avoid clutter, and also we don't need this level of detail for this particular unit. You can think about the buses as a highways of 16 lanes moving chunks of 16 bits from one place to another. All right so, how do we control this computer? Well, we have software, and the software in this level of the machine, the software consists of machine language or the program that we write using machine language. And when we designed this computer and when we designed this machine language we decided to create two categories of instructions, which we call A-instructions and C-instructions. And each one of this instructions is specified as a 16-bit number, like everything else in this machine. So what is a Hack program? A Hack program is essentially a sequence of instructions, 16-bit numbers, written in the Hack [COUGH], I'm sorry, written machine language. What about control? Well, before we talk about control, I have to introduce yet another element in this platform which is called a reset button. So, we do have a reset button and here is how I cause this computer to do something useful for me. I write the program, the program is a set of 16-bit numbers, I take these 16-bit numbers and somehow put them into the ROM, we'll discuss how we actually do it. Then I press the reset button, and once I do this, the program starts running. That's the basic sort of user instructions of how to cause this computer to do something useful. Now I have no idea what the computer will do, it all depends on the program. But hopefully, the computer will start sounding some music, or showing video clip, or compute the average of the million numbers or something like this, it all depends on what is written in the program. Now, before we go on to talk about the machine language, I'd like to say a few words about some more hardware artifacts that we have to be aware of. The Hack computer recognizes three registers. First of all, there's the D register which holds a 16-bit value which represents a piece of data. Then there's the A register which holds also a 16-bit value which represents either a data value or an address, we'll talk about this later on. And finally, there is something called the selected memory register, which is denoted by the letter M. So it doesn't matter if I have 2 billion memory registers, at any given point of time, only one of them is selected. And I can basically ignore all other registers, they're irrelevant for what I currently do. I want to focus only on the currently selected register, and I call this register M. This is just a convention that we use in the specification of the Hack machine language. Alright, so now we have all the basic background that we need in order to understand the syntax of the language. So here's the syntax of the A-instruction. Ampersand value, or @value, where value is either A non-negative decimal constant or a symbol referring to such a constant, and we'll discuss these symbols later on. Now instead of spending too much time about the form of semantics let's see an example. What does @21 mean? Well if I tell the computer @21, two things happen. First of all, the A register is set to 21 and second of all RAM of 21 becomes the selected RAM register. So we see that the A register has a very important side effect. Once you set The A register to a particular value like 21. It automatically selects a particular register from the data memory and this register becomes the currently selected register, what I called M in the previous slide, all right? So this is the operation, that's the semantics of the A-instruction. Here is an example of how we actually use this instruction, let's say that we want to set RAM[100] to -1, how do I do it? Well, the first thing that you have to do is select the register on which we want to operate, and we do it by saying @100. Once we do this, we get the side effect working and then we can say M=-1, because M now denotes register number 100 in the memory unit. So that's how we use the A-instruction, we always need it before we operate on the memory, before we do something to the memory, we have to select A register so we always have to address the memory using an A-instruction. And that's by the way why it's called A, A for addressing. The C-instruction is the work course of the language that's where much of the action takes place. And the syntax of this instruction consists of three different fields which we call destination, computation, and a jump directive. Now here's how it works. First of all, we compute something, and then we can do one of two things. We can either store the result of the computation in some destination or we can use this computation to decide if we want to jump to some other instruction in the program. Now this is the basic overall semantics of the C-instruction. Now let's get more into the details of everywhere of this fields. The computation can be anyone of the computations that we see here. So we see here a set of what is sometimes called mnemonics or symbols that represents some operation. So we can compute the values, 0, 1, -1, we can compute the current value of the D register, we can compute D-1, D+A, D&A, and & here is a 16-bit A, D 16-bit or A, and so on and so forth. And, wherever you see the mnemonic A, we can replace it also with a mnemonic M. So we can do many different things, using the computation field. What about destination? Well we have eight possible destinations, beginning with null, which means we don't want to store the results of the computations at all. And we can store the results of the computation either in the currently selected RAM register, or in the D register, or interestingly enough, we can store it simultaneously both in M and in D. This is something which is actually quite powerful about the Hack machine language, we can simultaneously store the result of computations in more than one container. We have 8 different possibilities and the programmer is free to use that any one of them according to work there he or she wants to do. Now what about the jump directive, the jump directive takes a little while to get used to and here's how it works. We have eight possible conditions and these conditions always apply, they always compare the result of the computation to 0, okay? And once again, instead of belaboring about it, I'm going to give some examples in just a few minutes, so this will become much clearer once we see the examples. So let's say that I want to set the D register to -1, okay set the D register to -1. I look at the language specification and I see that I have -1 is one of the values that I can compute and D is one of the legible destinations. So I can simply say, D=-1. The jump directive is optional, so I don't have to specify it. So case closed. Let's move on to the next example. Let's say that I want to set RAM[300], register number 300, to the value of the D register minus 1. Once again I look at the language specification and, but before I do so actually, I have to select the register on which I want to operate. Whenever I want to access the memory, I must use an A-instruction to select the register of interest, so I say @300. And then I look at the specification and I see that I have D-1 as one of the values that the CPU can compute for me and I have M as one of the legible destinations, so all I have to do is say M = D -1. And that is how I set register number 300 to D-1 and as you see I need two instructions to carry out this particular operation. Whenever I do something to the memory I first have to use an A-instruction to help to select the register on which I want to operate. Okay, the last example deals with a jump. How do I tell the computer to jump to execute a particular instruction? Let's say that the condition that I want to use is that if D-1 == 0, jump to execute the instruction which is located in the ROM 56, this is similar to for example a condition that terminates a loop. I do something in a loop and each time I check the value of D-1 and when it reaches 0 I want to jump to some other instruction. So how do I do it? Well, once again, whenever I deal with a memory, they first thing that I have to do is use A-instruction to specify which register I want to operate on. So I say @56 to select the address 56. And then I look at the language specification I see that I have D-1 as one of the possible computations. And I also have a JEQ, which means jump if the value of the computation equals 0, and that's exactly what I want to do, right? I want to jump if the value of D-1 == 0. So I compute D-1, and I say JEQ, so if the value of D-1 == 0, jump. Instead of equals, I could have used the greater than, less than, not equal, and so on. And notice by the way that I also have an unconditional jump. If I simply want to jump to 56 without checking any condition, all I have to say is jump. And in fact, if I want to be more accurate, the syntax that we have in this language requires that they say 0 semicolon jump. Now, this is just a convention, so if I want to do an unconditional jump, I do 0 semicolon JMP, and this will cause an unconditional jump. By the way, everything that I say here is described fully in the book, and in the website, so you don't really have to remember any one of the details because you can refer to them later on. So this has been an overall description of the Hack computer language. And in the next unit we are going to be more specific about this language because we are going to describe two different flavors of this language. What we've seen so far was the symbolic flavor of the language, but we can also write all these instructions using binary codes. And it's quite interesting to see how these two flavors relate to each other. We'll do this in the next unit.