03 Memory Addressing Modes


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 Hierarchies
03 Virtual Memory?ches
863 03
ALL L130310?lass101
Mode 03 Chaos Mode
2009 03 Our 100Th Issue
jezyk ukrainski lekcja 03
DB Movie 03 Mysterious Adventures
Szkol Okres pracodawców 03 ochrona ppoż
Fakty nieznane , bo niebyłe Nasz Dziennik, 2011 03 16
2009 03 BP KGP Niebieska karta sprawozdanie za 2008rid&657
Gigabit Ethernet 03
Kuchnia francuska po prostu (odc 03) Kolorowe budynie

więcej podobnych podstron