13 hours 15 minutes
Hello. This is Dr Miller, and this is Episode 10.1 of Assembly.
Today, we're gonna talk about pointers and arrays
So, Pointers, what are they? Will they point to a location in memory and this is RAM or the ram that you would install on your computer?
And then you can get the address of them by using one of two operations.
So we can either use the move assembly, pneumonic and every little copy the address, or you can use L E A, which will do a calculation, but it won't actually load any memory.
So here are a couple examples,
so we can have the
array text and we can move that into yea X and that will load the address
or similarly weaken, Say, get the data at that address. So they had data at text and that will be loaded into yea X. And this will move a D word.
So here we can another example. We can copy that address into EA X. We can add to do it, which is gonna be a colder offset. And then we can get the data at that location.
Was there a couple examples
and then if we want to use l E a r load effective address,
we can basically say load me the address of the variable text, right? So that it does the equivalent of that move.
And then here we can just copy the data in if we want, or we could even use E x inside the brackets.
And then here we can use L e A. To do this calculation. So it'll take the address of text and then it'll add the offset B e B X into that and then store that address in E B X. And so that's one of the benefits of L E A. Is that we can do that
So what are raise an array is a region of contiguous memory in the sense that it is all allocated at once. Um, and it
it is contiguous in that there are no breaks in between different elements of that,
um, and the signore sort of memory segmentation and pages.
And then an array is defined by the element size or how big each element is, and then how long it ISS. So when you define an array, you're gonna have to tell it how big it is and how how many elements are going to be in that array.
And then if you're going to actually use the array, you have a base address or the address of the beginning of the ray, the offset that you're looking at. And then you need to know the size of each element inside that array.
So here are some examples of defining arrays. We can either use the data section where we actually give them values.
So here's an array of D words, an array of words and over a of bites,
Um, or we can use the BSS. And so this is a array of D words, but we don't give them initial values. We just say that I'd like five d words
are like five words, or I'd like five bites
and then inside of See, we have a couple of different ways of actually allocating a raise.
Um, and this is just a little extra info, so you can either allocate them on the stack or you can use Malik. And those are the two typical ways that we define a raise inside of C
and then see uses a bracket style notation to do the offset of the index. But we don't have this available to us and assembly, so we have to actually do it manually.
So what is the offset? The opposite represents how much from the beginning of the ray that we're going to add. So how far into the array are we going to get?
And that uses those pointers? And so you take a pointer and then you add the offset in order to
get the data at a particular location.
And then you have to do the calculation of how big each element is in the array. And so the standard sizes, as we've seen, are bites, words and the words.
And so, for a character array or a string right, each index is going to be one. But if you have a bunch of D words than our index is gonna be, too
our sorry if we have a bunch of words that's gonna be too. And if we have a bunch of the words, that's gonna be four.
So here's an examples. We have several raise that we defined earlier,
and then we say we're going to reading an edger and then we're going to moving into yea X. The value at array plus are offset.
array one is a bunch of the words and we're gonna take the beginning array and we're gonna add those d words. And then we're just gonna print off what the energy is. So hopefully we get 12345
But we see when we run that code that when we type zero, we get one, which is what we expected. But when we type one,
we get 35 554432
or two. We get 13 107 to.
So why is this?
Well, if we look back at the beginning here, right, we said this is an array of D words, but we are only adding one each time through. But a D word is four bites. So let's look at how this is
so in memory. This is how d words are laid out. These air each bites. I've written them in hex. And so we have the number one, and that is at the base address. And then the beginning for bites of this or next three bites actually
are going to be filled with zeros on the number two and these air filled with serious and the number three and these air filled with zeros.
So our base addresses right here. But we're adding one, which is still part of this same our first array and element.
if we look at reading a wording a D word right, that's gonna be four bytes starting it offset zero.
And so we read these four bites and this is our number. And then we convert that from hex into decimal.
But if we load offset one, that's the data starting right here and we're loading these set of bites.
Well, we can see if we have the number zero x 0 to 000000 in hex and we convert that to base 10. We get the 33554432
And so the problem is that we're not adding the right offset. Let's look at one more example. So if we do offset to which we also printed, we get the number 00020000 in hex.
And if we take that and we convert that into decimal we get this number here, so we start reading at this location and we go this way, and that is the number that we read.
And so because we're not adding the right offset
because we're not multiplying by the size of each element in the array, we're getting the wrong values.
So to fix that here, when we read an imager, then we multiply, are offset by four or the size of each D word and then get the data at array plus whatever that offset is, and then we can print that.
And when we run that if we enter offset zero, we get one. If we don't enter offset one, we get to two, we'll get 33 we get four and four, we get five,
which, as we look here, those are the values that are in our array, right? So it's reading each one of those properly,
and so you got to know the size of each element and then multiply that so that you can,
um, get the correct data given the size of the array.
And so what you should do is maybe try
taking this code and using array to and figuring out how to
go through that array.
So a string is an array of characters
where characters air defined by the Ask e standard. And that's what those values are. And then each element is a bite, and they actually ask You uses seven bits, but we fill it out to eight. So that way it matches the size that our computers are allowed to breed in store.
And then at the end of an array, we have a zero or null byte hex 00 And this tells us that we're done with the string,
and that is the standard that is used by nearly all programming languages in order to store the fact that we're at the end of a string of characters.
And so here we have defined a an example here. So we have string and it says this is a test, and then it has the 10 which is a new line and then a zero, which terminates our string,
and we're actually using a couple functions. So this is this function is gonna figure out how long this string is and then going to go ahead and print it without using prints string.
So a couple functions that we're gonna use we're going to use Sterling in and put car. Sterling will figure out the length of the string put car will print a single character to the console.
So here, in order to use Sterling, we have to figure out the address of our string. So we load that address in t a X, push that onto the stack and then call Sterling and then e X will have the length of our strain.
And then we can add forward to correct the stack. And then we're going to ride a little loop here. And so to initialize the loop, we're going to use easy X because we're gonna loop, right? We're gonna loop up to print.
So we copy that length and TC X so we can do our Luke Luke properly.
E d x is gonna be our index are index that we're going to get within the array or offset.
And then e b X is going to have the address of the string.
And so here, when we copy the data in, we're gonna copy into ea x
e b x plus e d x so ebx is our base. E d exes are offset.
And then all this code right here is to save all the registers. We save these three registers because put car will clobber them.
We then push on the argument that we want. So you want to print off the character E X? So we pushed that onto the stack called put car. Now that single character gets printed to the screen
and then we have to correct the stack. So this is just we pushed it, so we might as well, poppet.
And then here we are, restoring our registers,
and then each time through the loop, we're gonna increment GDX so et X will step through the array.
So don't go from index 01234 At the same time, E c X is being deck amended by our loop rights. We're going back up to the top each time because we know how many times we need to print. So we're going to go through and print each one of these characters and we don't have to print the zero, and so we just go all the way through the end.
So today we talked about pointers in a raise in a very specific type of array called a string.
And in the future, we're gonna have some examples of a raise, and we're gonna actually look a tsum mawr end up string operations that we can have.
So here's our quiz.
What is a pointer?
It points to a location in memory.
And then what info do you need to access in a rain?
Well, you need the base address, pointer. You need the offset. And they needed to know how big each one of the elements are.
So if you have questions, you can email me, Miller MJ at you and Kate I e to you, and you can find me on Twitter at Milhouse 30.