What we've viewed so far in the previous
examples for memory addressing was the
simplest form, which we have an address
for it in our registry.
And we just tell memory to return us the
value of the location stored in, in the
registry.
Now we're going to see in, that so
because in addressing mode.
Now we're going to see the complete
addressing modes supported by x86.
Okay?
So in these are the add, these are how
addresses are used for accessing memory
in a moving structure, them we saw a lot
of them in the previous example.
So that means the most general form of
addressing more than a[INAUDIBLE] six is
of the following form, okay you have D is
a constant displacement that's added to,
to, to the final address, okay, in this
is a constant that has to be one.
Two or four bytes.
That's a constant displacement.
That doesn't mean that it can be only off
by four bytes.
It means that the displacement distance
itself has to be a value of one, two or
four bytes.
Okay.
So now.
The other primary here, our b, is a base
register.
It's called a base register because we
adding, we're adding
to that reference point.
that's the base register where our, our
address starts to be completed from.
Ri, also called the index register, is
used for things like arrays.
That's why we have a multiplication here
by the contents of Ri.
And that's multiplied by a constant
called S, which is the scale.
Kay.
And this value can be one, two, four or
eight.
Why those numbers?
Well those numbers because we want to
officially support.
Arrays are value of these size, of these
sizes, 'kay.
So, but they're many special cases, on
how to use this, complete addressing
mode.
For example, if you just use, in
parenthesis, Rb, Ri, the final memory
address is going to be the contents of Rb
added.
With the contents of Ri.
And that's because in this case, S,
variable S is just set to the, the
constant S is set to one.
The scale is set to one.
Now we can also use D Rb, Ri, and that's
just going to do Rb plus Ri, plus D.
And the, the scale here is just set to
one.
That's the special case.
Okay?
And also, you could have no displacement
at all, we're not adding anything, right?
So it's in this displacing is in fact
will be zero.
Okay?
So it adds rb, with the scale, multiplied
by register Ri.
So let's see some quick examples here.
We have two registers in our example.
EDX and ECX.
EDX is set to F000 hex and ECX is set to
100.
So now we're going to be exercising all
these addressing modes here, let's start
with the first one.
this first one here our.
So our d, the displacement is, 0x8.
and we're adding this to the contents of
edx.
So, are we going to say that well, that's
the value of edx?
That's the constant the final addition is
just an addition of these two.
Okay?
Now, the next one, is using this fall,
this form here.
Right?
Which is just going to be rb plus ri, in
this case just edx plus ecx, that's what
we get here, f100.
Now, the third example here, is using a a
scale factor, okay.
So, and what it's going to do is, it's
going to get Edx, and add it to four
times, because we have four here.
Ecx, which is 100.
So, in the end we get f400.
So, now the final example here is d is
set to 0x80.
We do not have Rb, so Rb is empty.
But we have our RI and we have a scale,
too.
So, what's this going to do?
Well, it's going to do two times the
contents of edx, okay?
That's here.
Added with the displacement, and we get
the final address, 1e080.
there's an instruction in X86 called leal
that get a source.
So it's source operand is an address mode
expression is any of the expressions that
I just showed you.
And so what the this function does is it
evaluates that address mode expression,
and puts the resulting address into the
destination operand, into the destination
register.
For example If I use this, what is it
going to do?
Well, eax is going to get, is going to
give us eax equals edx + 4 times ecx.
Isn't that cool?
So, and you can use that to actually
compute addresses.
Right?
So to go with that, this is without a
memory reference, so if you have this in
your c code,[INAUDIBLE] showed you this
when he talked about pointers, and what
do you want to do here?
You want to get the address, of
the[INAUDIBLE] element of the, of array
x.
Okay?
See, so you just want to get the address,
you're not doing a memory, you're not
doing a memory access, so in this case
you're going to be using this layout
instruction.
But this instruction is it, it can
actually be used to compute any
expression of the form, any arithmetic
expression of the form x plus k times i.
Now I'll tell a bit about some other
arithmetic operations, then we're going
to put everything together into a large
example, okay, a larger example.
So here we're doing, we have a bunch of
instructions, the first one does a
arithmetic addition okay, so it takes two
operands as far from this destination and
you get destination equals destination
plus the source.
Okay, the sub is very similar except that
it does subtraction and imull, same
thing, except that it does
multiplication.
So now we're going to see instructions
that actually does shifts.
So just shifts the shifts bit wise, okay.
So shll is doing a shift arithmetic and
it's called shift arithmetic because it
preserves the sign bit, it does something
special with the sign bit, okay.
So this, L means left, that's why it's
shifting to the left.
So gets the destination value shifts left
by the foruth operan and stores it back
itno the destination register.
Now SARL does the same thing but notice R
because it shifts to the right.
Okay.
And this shrl, is shifting to, shifting
to the right, okay.
Except that this is shift logical
community does not do anything with the
sine bits.
'Kay, so the xorl instruction it just
does an xor of the destination with the
source and stores it back to, to the
destination.
And does, a bitwise and, or does a
bitwise or.
'Kay, so then watch out for the argument
order.
That's actually very important.
Yeah, because the, the, argument order,
affects your results.
Especially for subtraction.
Hm?
So it knows that there's no distinction
here, between signed, and unsigned ints.
Why is that?
Well, it's because remember that if you
use two complements you can do arithmetic
without regards[INAUDIBLE] you simply can
just[INAUDIBLE] or[INAUDIBLE] but most of
these do have to worry about if you're
doing shifts arithmetic or shifts
logically because of the sign difference.
Here's some, some other arithmetic
operations.
This is a unarlal unary instructions
because it takes single operand.
Incl just increments by 1, Decl,
decrements by 1 and then neg-o Just
changes the signment, okay just, just, it
changes the sign.
And, not just a bitwise not, of the
contents of the register.
And now you, you should look at the, the
text book, for more instructions like
mov, and so on.
Divisions.
Okay so now let's put everything together
in a, in an example, that uses leal, and
some other instructions as well.
Okay?
So recall that now we have the setup,
that's just saving the, the stack
pointer.
And then finish is just restoring the
stack pointer and returning.
Okay?
This is, this is, and this is the C code
that we are implementing here.
Let's see how this, this works.
First of all, this is our stack so you,
you know where our parameters are.
We have three parameters.
Kay.
So this is IE 32 that means the
parameters are stored onto the stack.
Well these two instructions here are
doing they're just reading X and Y and
putting it into EAX and EDX.
Okay?
And that's what this one here is doing.
This one is using the leal instruction,
this is the leal instruction.
What it's going to do, it's just going to
add edx with eax and put it in ecx, okay?
Recall that leal just evaluates
expressions of any, any expression looks
like an address.
expression, okay.
And now we use it again here, when we're
multiplying.
So, now we're executing this, this
statement.
And this layout, this instruction gets a,
d, x.
Okay, and it adds it with two times e to
the x and is stored in e to the x.
Okay?
So that's why we get e dx equals y plus
two times y which is the same thing as
three times y.
Now we're shifting arithmetic left here
by 4.
Hm, what does that mean to, to, to shift
by 4.
4 bits is the same as multiplying by 2 to
the 4 which is 16.
That's why now we get 16 times 3.
It equals 48.
That's why we're now effectively storing
48 times y into dx, because before we
had, we had 3y, we multiply that by 16,
now we have 48 multiplied by y, and
storing into dx.
And the next instruction, now is just,
what is it doing.
It's implementing this one here 'Kay?
So, he does t5 equals t3 plus t4.
But what he did was just inline this one.
It's executing this one together as well,
'kay?
It's just putting it here, 'kay?
That's why now what we're doing is four,
that's the square number here, adding
four.
OK, which was a four here.
With T4, there was a, computed by the
previous instruction.
And adding it with X, it just happens to
be stored in EAX.
And then storing back in EAX.
And then finally.
We are in this instruction here.
This instruction is just implementing the
final stack in our arith, arith function,
okay?
So things to note here is that, note that
the instructions are in the different
order than what appeared in the C code.
Okay, so we see like at this, this orange
instruction happens to implement that
relates to these two instructions in c
code, that these two statements in the c
code.
And also, green comes before blue in c,
but blue comes before green in, in there,
in the assembly code.
Okay, and also it's interesting to note
that some expressions require multiple
instructions, and some instructions.
Like this one that I just showed here,
covers multiple expressions, okay?
And you get the same exact code when you
compile this.
Why is that?
Because the compiler is going to have to
create temporary variables.
Anyways.
So, let me show you another example now.
This example is implementing this logical
function that evaluates all of these,
that executes all of these expressions
here.
And again, here what this is like the,
the previous example.
We're just reading a parameter from the
stack.
Now, this function has two parameters, x,
and y.
this instruction is just loading the x
parameter, which is 8 from EVP into EAX.
Okay?
And that's what the first instruction's
doing now.
This first instruction here, this x or is
implementing this.
A statement here.
And look how interesting.
This, this instruction is an interesting
example because it has a register operand
as well as a memory operand, okay?
And this memory operand happens to point
to er, where Y was located.
So that's why this instruction implements
X, X or Y.
Now this instruction here is just
shifting EAX right by 17 bits.
So it's implementing this expression
here, this, this statement here.
And and we're shifting right so it
chooses, it chooses the compiler chose
the shift right instruction.
And finally this instruction here is
implementing these two statements, but
there's something interesting here going
on, right?
What the compiler did is note that this
expression here is a constant expression.
But instead of inserting instructions to
evaluate that, the compiler evaluates
that at compile time, but uses a single
number that represents that instruction
using, that, that represents that
statement and uses it in the instruction.
So you don't have to do this in during
execution time, which is what our compile
time wants, because we know it's not
going to change.
Then that code, that's, that's a, that's
going to be much faster.
Wyszukiwarka
Podobne podstrony:
03 Memory Hierarchies03 Virtual Memory?ches863 03ALL L130310?lass101Mode 03 Chaos Mode2009 03 Our 100Th Issuejezyk ukrainski lekcja 03DB Movie 03 Mysterious AdventuresSzkol Okres pracodawców 03 ochrona ppożFakty nieznane , bo niebyłe Nasz Dziennik, 2011 03 162009 03 BP KGP Niebieska karta sprawozdanie za 2008rid&657Gigabit Ethernet 03Kuchnia francuska po prostu (odc 03) Kolorowe budyniewięcej podobnych podstron