 In this video, we're going to begin looking at assembly language programming. Assembly language is like another programming language, but it's really just one step removed from the actual language that the machine understands. This means we're not going to have any of the fancy features that we're used to working with in high level languages. We won't have abstractions or classes, data structures. We won't have functions, loops, if statements, or even variables. If we want to have any of that, we're going to have to build it ourselves. And that's what we're going to spend a whole lot of time to. Looking at how we build all of these fancy features that we're used to by just starting with this handful of very simple operations. We're going to be working with the MIPS R2000 assembly language. And this is a really, really simple language. It's an old language, but it still contains everything that we need to build any of those fancy features that we've seen in high level languages. You can still write any program that you're used to. You're just going to have to write it in much smaller pieces. Our architecture here is going to provide four things for us. We'll have registers, operations, memory, and system calls. Operations are probably the most straightforward. These are all of our instructions. Each of the things that we can ask our machine to do for us. And we'll introduce new instructions a bit at a time as they're relevant for the type of functionality that we're interested in building right now. We will get to memory about halfway through when we start looking at complex functions and data structures. System calls we'll use very early on because those will allow us to do even simple things like input and output. But we're going to start with looking at registers. So our registers are going to fill the role of our variables in a high level language. But unlike actual variables, we don't have an unlimited number of them. We don't get to name them whatever we want. They can't even have a type assigned to them. So you can kind of think of these like generic global variables. And in our MIPS assembly language, we have 32 of these. Each of these registers has a number assigned to it, 0 through 31, but we can also refer to them by their various mnemonics. So for example, register $t0 could also be referred to as $8. But most of the time it's going to make more sense to use the mnemonics. So the most straightforward register that we've got is actually $0. It's also got the number 0, as you can see. But this one is not really a variable. It's actually been hardwired to the value 0. So you can't really overwrite this value. But it turns out having 0 available to us is actually really useful for a lot of operations. Registers t0 through t9 will be the ones we use for the majority of our computation. This is where we'll store all of our temporary information, while we're in the middle of a computation. When we start looking at functions, we'll see some more registers. We'll have s0 through s7, which are considered saved registers. And these are also for general purpose computation. But they differ from the temporary registers in how they're handled across the function call. We'll see that temporary registers are not likely to be preserved across the function call. So if we want to keep the data that's in them, we'll need to store it someplace safe. On the other hand, we'll expect the saved registers to be saved across the function call, so that their data will still be available when we return from that function call. To ensure that that data is still available, if we want to keep the data in a temporary register, the calling function has to save it. But if the callE function wants to use one of the saved registers, it will have to preserve that data and restore it when it's done using that register. $a0 through a3 are for function arguments. So all of your parameters you can expect will come in $a0 through $a3. And in return, a function will provide its results in v0 and v1. We'll use the return address as a way to say where our function should return to when it's done running. So all of those together will give us the stuff that we need to build actual functions. We want to start accessing memory. We're going to need to have things like our stack pointer, our frame pointer, and our global pointer. Our stack pointer will be used for holding things like local variables, any of those saved registers that we overwrote, and a few other related things. Our frame pointer will be similar to our stack pointer. Our frame pointer will essentially tell us where our block of memory on the stack starts, and our stack pointer would tell us where it ends. The global pointer will be used for managing the heap. Things like objects that you're used to allocating with the new keyword would be put on the heap, and we'll be able to manage that using the global pointer. Finally, we have three other registers that we really won't have to worry about. We have the assembler temporary, which the assembler will use when it needs to expand a pseudo instruction into actual machine language instructions. And we also have two registers reserved for the operating system kernel. While we don't have any fancy variable names like we're used to, following the conventions for putting temporary information in temporary registers, more permanent information perhaps in the saved registers, using our argument registers and our turn value registers appropriately will help us to get some of that same organization that we're used to, even without having the variable names that we'd like.