 In this video, we're going to walk through a couple of examples of data structures, how we can define them, how we can allocate them, how we can access them. So I'm going to start with something really simple, which is a linked list. A linked list contains two things, some piece of data and a pointer to another linked list. This means that we can chain up a whole bunch of these linked list data structures and build what's kind of like an array. It's easier to add things into the middle or take things out of the middle of this type of array than with a regular one, but it's otherwise doing the same sort of thing. So in this case, my data structure consists of two things. An integer for some data, which would be four bytes, and a pointer to another linked list. In our case, all of our pointers are going to be four bytes. They contain some address and all of our addresses are just four byte integers. So overall, my linked list contains eight bytes of data. So I'm going to lay out eight bytes worth of memory here. I'm going to have some base address and I like sticking my base addresses in S0. This will tell me where my data structure starts. So my data structure starts all the way over here and is just going to continue off to the right. The first thing that I'm going to put into my data structure will be my data. This just seems like a natural place to put it to me. It wouldn't really matter if I put the data second and the linked list pointer first, but I do have the data listed before the next pointer as well. So might as well put the data in the first element and the linked list pointer in the second element. So now I know the data is at S0 plus 0 and the linked list pointer is at S0 plus 4. If I want to allocate some memory for this data structure, I've got two options. I can use a syscall, which case I'd use system call number nine. So I put nine in V0 and then I put the size of my data structure into A0. My data structure is eight bytes, so I'll put an eight into A0. And then I make the syscall. When this returns, the operating system has put a pointer to eight bytes of memory into register V0. I want that to be in register S0 because I like S0, so I'm going to copy that pointer from V0 to S0. Now I have everything set up and I can use this, but I could have worked with the global pointer instead. In this case, the global pointer actually points to unallocated memory. In contrast to the stack where the stack pointer pointed to the first byte of allocated memory, the global pointer points to the first byte of unallocated memory. So in this case, I would copy the global pointer into S0, and then I would move the global pointer up by eight bytes. Moving the global pointer up by eight bytes would allocate that eight bytes that I need. And I would have already copied the address into S0. Either of these methods will work for us, but we'd like to be able to access the data in our data structure now. So this being a linked list, there are three things I'm really going to be interested in doing here. I'm going to be interested in accessing my data, either reading something from it or storing something into it. And I'm going to be interested in finding what is the next element in my linked list. So I can access the data using a load word or a store word, depending on whether I want to read data or write data. And I'm just going to tell it that my data is at S0 plus 0. S0 tells me where my data structure starts, and since the data is my first element in my data structure, I don't need to go anywhere to get to the data. So I just put in S0 plus 0 for the memory location. If I'm interested in copying that data into a register, then I'd put the destination register and say T0, and I'm using a load word for that. To copy something into the data structure, then I would use the store word. And again, just using S0 plus 0, because that tells me where the data is. And then I'd give it the whatever piece of data I want to copy in there. If I want to go find the next element in my data structure, then I'm going to be interested in this next pointer. So in that case, I go to S0 plus 4, because my data structure starts at S0, my first element consumes four bytes of space, and then my next pointer can start. So at S0 plus 4 is where the next is. So that's all I put in here is S0 plus 4. Then I'm going to copy that into S0 so that I can use it exactly the same way I used the current S0. This is just going to be another address telling me where another data structure is in memory. So I'm copying that address into S0 so I can use S0 as a pointer. It will work exactly the same as it did in each of those cases. And I'll be able to access the next element in my linked list. For another example, I could have a record. In this case, we're keeping track of some information about employees. So each employee has a name, some ID number. He gets paid something and has a title. So we want to put all of these into one data structure. In this case, I've got a couple of pointers to characters. This is an old-fashioned way of designating a string. This is just going to be some array of characters, but it's not actually in the data structure itself. The data structure just contains a pointer to that array. So pointers are only four bytes. So the name and the job title both end up being just four bytes of space. Integers are four bytes, so the ID takes up four bytes of space. Basic floats are also just four bytes, so the salary also takes up four bytes of space. So I've got four elements, each of which take four bytes of space. So total, we have 16 bytes of space being used. So if I lay this out just in order, then I'm starting with my name, then I have an ID, salary, and then the job title. If I'm allocating this using a system call, then I'm using system call number nine. In this case, my data structure needs 16 bytes of space. So I put 16 into A0, and then I make the system call. And because I like putting my base address in S0, I'm going to copy the address that the operating system gives me from register V0 to S0. Then I could stick something into, say, the ID field by accessing S0 plus 4, or I could stick something into the character title by accessing S0 plus 12. I could do the same thing using the global pointer, in which case I would copy the global pointer into S0, and then I would just increment the global pointer by 12. I then have access to all those same fields that I did before. I've just allocated the memory directly for myself. In both of these examples, we needed to know what was in our data structure. Was it just two elements? Was it four elements? How large are each of those? That will allow us to figure out how we're going to lay out all of those elements, and how much space do we need for those? Then we can allocate that much space, and we can really just use it however we want. Our memory is not going to be necessarily divided up into specific blocks. We can really choose to put things wherever we need them. If I want my name to be first, I can stick it first. If I want it to be last, I can stick it last. We just have to be consistent about where we're putting things in our data structure. If we're going to put our name first, then we should always put the name first. We should never decide to put it third. We should always expect that name to be in that first position. Then we can expect the ID to be in the second position. As long as we're consistent about that, the order doesn't actually matter too much.