Welcome to the Perspective unit of week six, which is also the last week in the Nand2Tetris course. And there's several questions that come to mind about what we did during this week, which was mostly writing and assembler. And the first question that I'd like to discuss is the following one. Can you possibly improve the symbolic Hack language without changing the binary code or the machine language which is underlying the symbolic level? So indeed, we have two layers of of expression here. We have the symbolic level and we have the binary code that lies below it if you will. And the assembler bridges this difference. And, indeed, we can take this level, the symbolic level, and make it more user-friendly or more programmer-friendly. And there are various ways to do it. And in order to explain them, I will go to the board and and show you some examples. So how can we make the Hack symbolic language more programmer-friendly? Well what we can do is introduce the notions of macro assemblers and macro commands. So let me say a few words about this added layer of abstraction. Let's take a typical operation like loading the D register with a value of some memory register. It is quite natural to think about a command that looks like this. D equals M, let's say at 100, okay, which means go to register number 100, take its contents and put it in the D register. This will be a natural thing to write, and yet the standard, the Hack language does not feature such a, such a command. So what I can do is I can take a command like this and translate it into two valid commands in the Hack language, which will be at 100 and D equals M, okay? So this is an example of what is sometimes called a macro command. And I can decide that whenever I write this command, I actually mean that I want these two commands to get executed. Likewise, think about jump instructions. For example it would be very natural to say something like jump to this particular label. But once again in the Hack language such an instruction is not permitted. So instead, I can expect this instruction to be translated into two instructions, which would be @LOOP and followed by a standard jump command. So these are macro instructions. These are actual instructions. And in order to close this gap, I have to do something to my assembler. I have to extend the assembler. And and write it in such a way that whenever it encounter a command like this, it translates it into two machine language commands rather than a single one, which is what we normally did in, in the standard assembler. One question that often comes up when students work on assemblers is that will I ever have to use an assembler outside school? Well, Norm, what do you think? >> Well, the answer is exactly the same answer we gave to the question, will we ever need to use machine language that we gave in week four? Very, very rarely. Most of the time, people write in high-level languages and do not worry about the machine language. When they do worry about the machine language of course they will do it in assembly language, and thus they will need to use an assembler. But this is very rare, only in the special cases where performance is of utmost criticality. Now in these cases, sometimes they will only want to focus on a very small part of the program and do it in assembly language. And they do rest in a high-level language. Eh, for example, C compilers allow you to do this kind of combination. To write most of the C lang, most of your program in the C language, and in it embed a few commands in assembly. So the assembler is sort of part of the C language compiler. And allows you to deal with very specific point of the program that you want to extremely optimize, and write them in assembly language. Beyond that, you will probably not worry that much, or at all, about assemblers or assembly language programming. >> Now this course is about building computers. And we had the tremendous luxury of using other computers in order to build the Hack computer. And in particular, when we wrote the assembler we wrote it using a high-level language like Java, or Python, or whatever language students have chose have chosen to to use when they wrote the assembler. Those of you who actually programmed the assembler once again used high-level language to do it. So the question is historically what happened when the first computers were designed? When you didn't have this this tremendous luxury, how was the first assembler actually written? So, Norm, do you want to take this question? >> So, this, this is a very mind bending question. Before I an, before I answer it I would like to re-emphasize again that conceptually, it only holds for the first time you write an assembler. In reality, most of the time there are already computers. And usually you use a computer that you already have with the high-level language that you already have to write code and assembler than basic fu, function and basically a functionality for the new computer. Now given that we are still talking about the first computer conceptually in history, how was that done? Well, in this course, you also saw that. Remember that the students that are not programmers in this course simply had to compile something by hand. They got an assembly language program and needed to comp, to translate it one, one command at a time into two machine language. That you can always do. So conceptually, what you can really do is you start to write the high-level assembler. You write an assembler in a high-level language and translate it by hand for the first time only into a machine language of your computer. Once you'll finish this translation, which is extremely time-consuming, extremely annoying to do, but only needs to be done once conceptually, then now you already have a machine language that runs your compiler or your assembler or any high-level help that you want. And then you can keep on using it for the rest of time. >> So, folks, [SOUND] that's it. We're done building the computer. We started with the Nand gates, six weeks ago. And we worked our way through several different types of chips. We built a an ALU, a CPU, a memory system. We've put everything together, and we've got a fully-functioning computer. We added to it an assembler, so we can actually program this computer in a, a relatively friendly language. And, that's it, we have a computer that can run any program that comes to your mind, including, of course, Tetris. So I'm very happy with this computer. Norm, are you happy with it also? >> Well Simon part of the motivation for this course was demystifying computers. Leaving the student with a clear understanding what goes on beyond this amazing beast called a computer, I think we've only partially done that. We basically understand, I think the students now understand how the hardware works. What is still quite mystifying I think to almost anyone that looks at computers is all the different software layers that eh, exist above it. When you actually use the computer, you talk with an operating system. You write in a high-level eh, programming language. It's very far from writing programs in this little assembler that we've already shown. It would be nice, wouldn't it, if we actually had in the second part of the course that actually does talk about all these software layers that are above the hardwa, the hardware level. That explain again in the same manner that, that we've, I think, explained so far, how you can actually construct the different software layers, the compiler and what we, what is required for it. The operating system, and getting to a level where the software hierarchy is demystified like we've demystified the hardware hierarchy so far. >> So thank you, Norm, for this criticism and and luckily I'm just reminded that we actually solved this problem also because we have a complete second part of this course, in which we do precisely what Norm just described. And and so in the second part of the course, we start with the hardware that you wrote or developed in this course. And we add the software hierarchy that needs to operate on top of it. And then we end up with the language which is very similar to object-oriented modern programming languages. And then you can really write programs like Tetris and anything that you want on this computer. And see it get execute on the hardware that you actually built in the first part of the course. Now, how should you go about doing this? Well there are two ways to do it. First of all, you can get a copy of this book, which gives you everything that you need in order to develop the software hierarchy of the computer. Just like we did in this course, the software hierarchy will be divided into six or seven different projects that you work on each week of the course. So that's one way of doing it, do it yourself. And the second way of doing it is just waiting until the second part of Nand2Tetris will be available on Coursera. And and then you can just take the course, just like he took this one and complete this second piece, which is still missing. So, with this folks the course is practically over. We hope that you enjoyed the ride. We want to thank you for the time and effort that you invested into taking this course. And we hope very much to see you in the second part of Nand2Tetris. So with that, bye.