Reputation: 21
I need help with a homework problem. I am supposed to figure out what the value of edx
will be after this code runs.
0x40106e <main+30>: mov $0x1,%edx
0x401073 <main+35>: mov $0x8,%ecx
0x401078 <main+40>: test %ecx,%ecx
0x40107a <main+42>: jg 0x40107e <main+46>
0x40107c <main+44>: jmp 0x40108a <main+58>
0x40107e <main+46>: lea (%ecx,%ecx,1),%eax
0x401081 <main+49>: lea (%eax,%edx,1),%eax
0x401084 <main+52>: lea 0xffffffff(%eax),%edx
0x401087 <main+55>: dec %ecx
0x401088 <main+56>: jmp 0x401078 <main+40>
0x40108a <main+58>: // endpoint
Since it is homework I don't really want to know the answer as much as how to figure it out. I was having trouble with figuring out the loop, but I think I got it. I think the test %ecx,%ecx
loops until %ecx
is decremented to 0. Is that right? What's really getting me is all the lea
stuff. I cannot figure out what that is doing.
Upvotes: 1
Views: 1130
Reputation: 6403
As icktoofay explained, the lea
instruction is going to set the edx
register to eax - 1
. Let's go through the whole code, step by step.
The first two lines are moving immediate values to registers, so edx
is made equal to 1
and ecx
is set to 8
.
The test
instruction is at the start of the loop here and together with the instruction immediately after it states the condition for the execution of the loop. The test
instruction affects quite a few flags, but as the conditional jump is jg
, we'll only focus on ZF
, OF
and SF
. jg
branches only if ZF=0
while SF=OF
. Now
ZF
will be zero until ECX!=0
OF
will always be zero and the same applies for SF
, as 8
is greater than zero in two's complement (more precisely the most significant bit of 8 is 0). The first lea
instruction sets eax
to 2*ecx
. The second and the last lea
s add eax
to edx
and decrement it. Finally, ecx
is decremented and instruction pointer is set to the start of the loop.
Written out symbolically:
sum(8, n = 1, n*2 -1) + 1
Upvotes: 1
Reputation: 128993
You're right about the test
and jg
; it does indeed loop until ecx
is zero.
lea
I'm not very familiar with AT&T syntax, so I'll use Intel syntax (which I find more intuitive) instead. I hope it's still intelligible. (One of the main differences is that Intel syntax puts the destination first.)
Some instructions let you load a value from an address:
mov eax, [esi] ; load a DWORD from the address in ESI
You can change these to add offsets:
mov eax, [esi + 4] ; load a DWORD from four bytes after the address in ESI
Certain combinations of registers, scales, and offsets are allowed:
mov eax, [esi + ecx * 4 + 16] ; load a DWORD from (ECX * 4 + 16) bytes after the
; address in ESI
This is rather convenient; you don't need to calculate the effective address manually.
lea
stands for “Load Effective Address”. Essentially, it lets you do something like this:
lea eax, [esi + ecx * 4 + 16]
Rather than loading the value in memory at that location, it just computes the address; in other words:
EAX = ESI + ECX * 4 + 16
The lea
instruction above assembles to 4 bytes. In contrast, the most obvious way to me:
mov eax, ecx
shl eax, 2
add eax, esi
add eax, 16
…assembles to 14 bytes.
Upvotes: 1