Hello, this is Dr. Miller and this
is Episode ten point one of
Assembly.
Today, we're going to talk about
pointers and erase
pointers.
So pointers, what are they?
Well, 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 have that
or copy the address, or you can
use LYA, which will do a
calculation, but it won't actually
load any memory.
So here are a couple of examples.
So we can have the
array text and we can
move that into yak's and
that will load the address
or similarly we can say
get the data at that address.
So they had data at text
and that will be loaded into yak's
and this will move a D word.
So here we can add another example.
We can copy that address into Yak's.
We can add two to it, which is going
to be called our offset, and then we
can get the data at that location.
So those are a couple examples.
And then if we want to use Leha or
load effective address, we
can basically say load me the
address of the
variable text so that
does the equivalent of that move.
And then here we can just copy the
data and if we want or we could even
use X inside the brackets.
And then here we can use Lia
to do this calculation, so it'll
take the address of text and then
it'll add the offset, be
Ebix into that and then
store that address in SBX.
And so that's one of the benefits of
LIA is that we can do that.
ARray's,
so what are race, an array
is a region of contiguous memory
in the sense that it is all
allocated at once
and it it is contiguous
and that there are no breaks in
between different elements of that.
And this ignores 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 is.
So when you define an array,
you're going to have to tell it how
big it is and 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 array, 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 I.D.
the data section where we actually
give them values.
So here's an array of D words,
an array of words, an array of
bytes, or we can
use the best.
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 bytes.
And then inside of C, we
have a couple of different ways of
actually allocating a raise,
and this is just a little extra info
so you can either allocate them on
the stack or you can use Malac.
And those are the two typical ways
that we define arrays inside of
C, and then C
uses a bracket style notation
to do the offset
of the index.
But we don't have this available to
us in assembly, so we have to
actually do it manually.
So what is the offset, the offset
represents how much from the
beginning of the ride 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 bitts words
and words.
And so for a character array
or a string,
each index is going to be one.
But if you have a bunch of words
than our index is going to be two
or sorry, if you have a bunch of
words, that's going to be two.
And if we have a bunch of words,
that's going to be for.
So here's an example, so we have
several arrays that we defined
earlier and then we say
we're going to read an integer
and then we're going to moving into
the value add array plus
our offset.
And so Array one
is a bunch of D words.
And we're going to take the beginning
array and we're going to add those D
words and then we're just going to
print off what the integer is.
So hopefully we'd get one, two,
three, four or five.
But we see when we run that code
that when we type zero or we get
one, which is what we expected, but
when we type one, we
get thirty five, five, five,
four, four, three, two or
two, we get 13 one, two,
seven, two.
So why is this?
Well, if we look back at the
beginning here, we said
this is an array of D words, but
we are only adding one each
time through. But a D word is four
bytes. So let's look at how this is
so in-memory. This is how D words
are laid out. These are each bytes
I've written them in hex.
And so we have the number one and
that is at the base I address.
And then the beginning, four
bytes of this or next three
bytes actually are going
to be filled with zeros.
And the number two and these are
filled with zeros and the number
three and these are filled with
zeros.
So our base address is right here,
but we're adding one which
is still part of the same,
our first array and element.
And so
if we look at reading, we're
adding a D word, right.
That's going to be four bytes
starting at 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 bytes
where we can see if we have the
number zero zero
two zero zero zero zero zero
zero in hex and
we convert that to base 10.
We get the three three five five
four four, three, two.
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 numbers zero
zero zero two zero zero
zero zero 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 are 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 integer, then we multiply
our offset by four or the size
of each word and then
get the data at Arae 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 enter offset one, we get
to two. We get three.
Three, we get four and four.
We get five.
Which as we look here, those are the
values that are in our array.
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
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
two and figuring out how
to go through that
array.
So string's.
So a string is an array of
characters.
Where characters are defined by the
Askey standard, and that's what
those values are, and then each
element is a bite and they
actually ask uses seven
bits, but we fill it out to eight.
So that way it matches the size
that our computers are allowed to
read in store.
And then at the end of an array, we
have a zero or no byte
hex zero zero.
And this tells us that we are done
with the string
and that is the standard that is
used by nearly all programing
languages in order to store the fact
that we are at the end of a
string of characters.
And so here we've 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 of
functions. So this is this
function is going to figure out how
long this string is and then going
to go ahead and print it without
using print string.
So a couple of functions that we're
going to use. We're going to use
Sterling and put car
sterling. We'll figure out the
length of a string.
Pushkar 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
and push that onto the stack
and then call Sterling and then ESX
will have the length of our string.
And then we can add forward to
correct the stack and then we're
going to write a little loop here,
and so to initialize the loop,
we're going to use X because we're
going to loop, right?
We're going to loop up to print.
So we copy that length ticks so
we can do our loop loop properly.
It is going to be our index
or our index that we're going to get
within the array or our offset.
And then SBX is
going to have the address of the
string.
And so here, when we copy the data
in, we're going to copy into X
SBX plus, so
Ebix is our base, Ed is
our offset.
And then all this code right here
is to save all the registers.
We save these three registers
because Pushka will clobber
them.
We then push on the argument that we
want. So we want to print off the
character X, so we
push that onto the stack called
Pushkar. Now that single character
gets printed on the screen
and then we have to correct the
stack. So this is just
we pushed it so we might as well pop
it. And then here we are restoring
our registers.
And then each time through the loop,
we're going to increment IDEX,
so I will step through the array
so it'll go from index zero
one to three four
at the same time, X is being
decrements by our loop.
So 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
and a raise and a very specific type
of array called a string.
And in the future, we're going to
have some examples of a raise and
we're going to actually look at some
more in depth string operations that
we can have.
So here's our quiz, what
is appointer?
It points to a location in memory.
And then what info do you need to
access an array?
Well, you need the base address
pointer, you need the offset,
and then you need to know how big
each one of the elements are.
So if you have questions, you can
email me, Miller, MJ at you and
Kadiatu and you can find me on
Twitter at Milhouse 30.