Reputation: 641
I have to read through some randomly generated assembly and enter some proper input to get to the end without calling the explode_bomb function. The problem is there are two lines which seem to directly contradict each other, and I'm worried that my assignment may in fact be impossible due to random generation.
Here is the full code:
08048d1b <phase_2>:
8048d1b: 55 push %ebp
8048d1c: 89 e5 mov %esp,%ebp
8048d1e: 56 push %esi
8048d1f: 53 push %ebx
8048d20: 83 ec 30 sub $0x30,%esp
8048d23: 8d 45 e0 lea 0xffffffe0(%ebp),%eax
8048d26: 89 44 24 04 mov %eax,0x4(%esp)
8048d2a: 8b 45 08 mov 0x8(%ebp),%eax
8048d2d: 89 04 24 mov %eax,(%esp)
8048d30: e8 42 04 00 00 call 8049177 <read_six_numbers>
8048d35: 83 7d e0 00 cmpl $0x0,0xffffffe0(%ebp)
8048d39: 79 05 jns 8048d40 <phase_2+0x25>
8048d3b: e8 f5 03 00 00 call 8049135 <explode_bomb>
8048d40: bb 01 00 00 00 mov $0x1,%ebx
8048d45: 8d 75 e0 lea 0xffffffe0(%ebp),%esi
8048d48: 89 d8 mov %ebx,%eax
8048d4a: 03 44 9e fc add 0xfffffffc(%esi,%ebx,4),%eax
8048d4e: 39 04 9e cmp %eax,(%esi,%ebx,4)
8048d51: 74 05 je 8048d58 <phase_2+0x3d>
8048d53: e8 dd 03 00 00 call 8049135 <explode_bomb>
8048d58: 83 c3 01 add $0x1,%ebx
8048d5b: 83 fb 06 cmp $0x6,%ebx
8048d5e: 75 e8 jne 8048d48 <phase_2+0x2d>
8048d60: 83 c4 30 add $0x30,%esp
8048d63: 5b pop %ebx
8048d64: 5e pop %esi
8048d65: 5d pop %ebp
8048d66: c3 ret
The lines in question are 8048d4a and 8048d4e. Being that this is in 2's compliment, the first number is a -4, the second number is my first input (does this ever even change to my second and third?), and the third will be whatever iteration of the loop we're on, as will the fourth.
Now comparing these values in direct sequence basically means I'm comparing a number to itself - 4, right? How could I ever feasibly pass that test?
Thank you for your assistance.
Upvotes: 0
Views: 1322
Reputation: 43688
mov $0x1,%ebx ; i = 1
lea 0xffffffe0(%ebp),%esi ; ESI = address of array of 6 numbers
mov %ebx,%eax
add 0xfffffffc(%esi,%ebx,4),%eax ; add to element
cmp %eax,(%esi,%ebx,4)
add 0xfffffffc(%esi,%ebx,4),%eax
The above instruction is accessing an element of an array. This is called SIB addressing in x86, for Scale, Index, Base. There is also an Offset component. The array is based at an address determined by the Base register (EBX
here) plus an offset (-4 here). The element number is at the Index register (ESI
here). The size of each element is determined by the Scale (4 here).
lea 0xffffffe0(%ebp),%esi ; ESI = address of array of 6 numbers
If you look further up, you see how the address of the array is moved into %ESI
. The array is a local variable, located 32 bytes below the frame pointer (when using a frame pointer, local variables, including arrays, are addressed as an offset from the frame pointer)
add 0xfffffffc(%esi,%ebx,4),%eax
So this instruction accesses a "virtual" array that starts 4 bytes before the real array. This is because the loop index starts at 1, but the element accessed is 0, so using the "virtual array" everything falls into place.
mov $0x1,%ebx ; i = 1
lea 0xffffffe0(%ebp),%esi ; ESI = address of array of 6 numbers
mov %ebx,%eax
add 0xfffffffc(%esi,%ebx,4),%eax ; add to element i-1
cmp %eax,(%esi,%ebx,4) ; compare against element i
Upvotes: 0
Reputation: 26171
my AT&T syntax isn't the best, but it seems its doing:
ADD EAX,[ESI + EBX * 4 - 4]
CMP EAX,[ESI + EBX * 4]
aka, its comparing the sum of the previous and some counter to the current entry. see this for reference, specifically:
Example:
Intel Syntax
instr foo,segreg:[base+index*scale+disp]
mov eax,[ebx+20h]
add eax,[ebx+ecx*2h
lea eax,[ebx+ecx]
sub eax,[ebx+ecx*4h-20h]
AT&T Syntax
instr %segreg:disp(base,index,scale),foo
movl 0x20(%ebx),%eax
addl (%ebx,%ecx,0x2),%eax
leal (%ebx,%ecx),%eax
subl -0x20(%ebx,%ecx,0x4),%eax
As for why its doing it this way, well it appears to be an optimization to avoid a register spill or the alternative of decrementing the array index then incrementing it.
Upvotes: 2