装配中的两条线没有任何意义

时间:2012-11-04 15:10:13

标签: assembly

我必须阅读一些随机生成的程序集并输入一些正确的输入,以便在不调用explode_bomb函数的情况下到达目的地。问题是有两条线似乎直接相互矛盾,我担心由于随机生成,我的任务实际上可能是不可能的。

以下是完整代码:

 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  

有问题的行是8048d4a和8048d4e。因为这是2的恭维,第一个数字是-4,第二个数字是我的第一个输入(这是否甚至改变到我的第二个和第三个?),第三个将是循环的任何迭代我们是和第四个一样。

现在直接顺序比较这些值基本上意味着我将数字与自身进行比较 - 4,对吗?我怎么能够通过那个测试呢?

感谢您的协助。

2 个答案:

答案 0 :(得分:3)

我的AT&amp; T语法并不是最好的,但它似乎在做:

ADD EAX,[ESI + EBX * 4 - 4]
CMP EAX,[ESI + EBX * 4]

aka,它将前一个和一些计数器的总和与当前条目进行比较。请参阅this以供参考,具体为:

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

至于为什么它这样做,好像它是一个优化,以避免寄存器溢出或减少数组索引然后递增它的替代。

答案 1 :(得分:0)

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

上述指令正在访问数组的元素。对于Scale,Index,Base,这在x86中称为 SIB 寻址。还有一个Offset组件。该阵列基于由基址寄存器(此处为EBX)加上偏移量(此处为-4)确定的地址。元素编号位于索引寄存器(此处为ESI)。每个元素的大小由比例(这里为4)确定。

lea    0xffffffe0(%ebp),%esi            ; ESI = address of array of 6 numbers

如果你进一步了解,你会看到数组的地址如何移动到%ESI。该数组是一个局部变量,位于帧指针下方32个字节处(当使用帧指针时,局部变量,包括数组,被视为与帧指针的偏移量)

add    0xfffffffc(%esi,%ebx,4),%eax

因此该指令访问在真实数组之前开始4个字节的“虚拟”数组。这是因为循环索引从1开始,但访问的元素是0,因此使用“虚拟阵列”一切都会到位。

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