 This time I'm going to be working with an array of integers. So I've declared an array of 10 integers, which I've got down here. And this is what we're going to be working with. So I've got two different ways I could allocate this array. I can either use a system call, in which case I stick 9 into v0. I stick the size of the array into a0 because my array is composed of integers, each of which are 4 by its large, and I have 10 of those. 4 times 10 gives me 40, so I put in 40. Then I have the system call, and I can copy the pointer into s0 so that I have my base address available. But I could have done this just by manipulating the global pointer. So I could have just copied the global pointer into s0 and then incremented the global pointer by 40. And 40 is the size of my array, so incrementing it by 40 allocates 40 bytes of space for me. If I just want to access a specific element in my array, say x0 or x3 or 8, then that's really easy to do. I could just look down at my data structure as I've written it and say, x0 is at s0 plus 0 or x3 is at s0 plus 12 or x8 is at s0 plus 32. That will work. But I can also realize that I'm getting numbers that are in multiples of 4. So 0 times 4 gives me 0 and 4 times 3 gives me 12. 8 times 4 is 32. So I could just take my index and multiply it by 4 and that would tell me what that constant offset is. Turns out we get that 4 because that's the size of our integers. This is an array of integers. Each of those integers are 4 bytes large, so we go down 4 bytes to get to the next element in our array each time. This will be really useful when we actually just want to walk down this array performing some operation on each element, for example. The way we normally write loops in high-level languages involves using indices. Have this index say 5 or 6 or 7 that tells us which element in the array it is but doesn't really tell us much about where in the array it is. But we can convert those indices into the address offsets and that's what we'll use in this case to loop over all of the elements. So to do this, I'd start by putting my loop index, say i, into perhaps t0 and the total number of elements into t1. Then I can run this loop until t0 actually gets to be the number of elements. So once i has been incremented to 10, then I know that I would be trying to access something off the end of my array and I should just quit my loop. Now to access one of those elements, first thing I need to do is multiply that index i by 4. Again, each of the elements in my array are 4 bytes in size, so I need to scale my index by 4 by the size of that element. In this case, I'm using a shift left logical operation to do that. That will work because I want to multiply by 4. It would also work if I wanted to multiply by 2. I could just shift by 1 instead. If the size of my data was not an exponent of 2, then I'd need to do something more normal. But the shift left logical instruction will work for this case. Then because my load word instruction takes this form, where I've got a base address and a constant offset, I really need to get both that base address and the offset into one register. I can't put the offset in as the constant in this case. So I add the base address from S0 to the offset that I calculated and put in T2, and then I'm just storing that into T2 as a reasonable place to keep it. Then I can go actually access that data. I can load the value from T2 where T2 contains the value of S0 plus my offset. In this case, I'm sticking my result into T3, and I could do something useful with it at that point. But in this case, I'm interested in just showing how the loop works. So I'm just going to increment my index by 1 and then go back through my loop again. So in this way, I would be able to walk down each element of this array and load all the data out. I could then do something more interesting with it, even if it's just printing it out. But this is enough to allow me to walk down and get all of the data out of this array. I could also do this by working with these as addresses. And you'll notice this code is slightly shorter. This is because I'm not going to have to do all of that scaling by my data size. I can just walk down in blocks of 4 instead. So I'm going to start by using my base address as the counter. So I'm putting S0 into T0. And then I'm going to put S0 plus 40 in ST1. Once my counter has reached S0 plus 40, I know it's gotten to the end of the array. I don't want to process anything out here. So that will be my termination condition for the loop. Once T0 equals T1, then we're going to end our loop. Now, since the value in T0 is an address, I can actually just go load that data directly. At the moment, it's telling me where the first element in the array is, so it would pull out X0. In this case, it would stick it in T2, and then I could do something more interesting with it. To get to the next element, I'm just going to increment my address by 4. Before I was pointing out S0, now I'm pointing out S0 plus 4. So the second time through the loop, T0 would still be less than T1 over here. And it would pull out the value of X1. Then it would increment the address again. We'd get X2, X3, and so on. So this code ends up being shorter, but it's not the way that we're used to working with arrays. Transits are you've had a whole lot more practice working with indices than with addresses. So this may feel rather unusual at first, but it's doing the exact same thing. You've just gotten rid of the abstraction of having an index for your array.