帮助破译简单的汇编代码

时间:2010-11-15 20:48:13

标签: c assembly

我正在使用GDB& amp;日食
这是一个简单的C代码。

int absdiff(int x, int y)
{  
if(x < y)  
  return y-x;
else  
  return x-y;
}

int main(void) {  
int x = 10;  
int y = 15;  
absdiff(x,y);
return EXIT_SUCCESS;  
}

这是main()

的相应汇编指令
          main:
080483bb:   push %ebp  #push old frame pointer onto the stack
080483bc:   mov %esp,%ebp #move the frame pointer down, to the position of stack pointer
080483be:   sub $0x18,%esp  # ???
25         int x = 10;    
080483c1:   movl $0xa,-0x4(%ebp) #move the "x(10)" to 4 address below frame pointer (why not push?)
26         int y = 15;
080483c8:   movl $0xf,-0x8(%ebp) #move the "y(15)" to 8 address below frame pointer (why not push?)
28         absdiff(x,y);
080483cf:   mov -0x8(%ebp),%eax # -0x8(%ebp) == 15 = y, and move it into %eax
080483d2:   mov %eax,0x4(%esp) # from this point on, I am confused
080483d6:   mov -0x4(%ebp),%eax 
080483d9:   mov %eax,(%esp)
080483dc:   call 0x8048394 <absdiff>
31         return EXIT_SUCCESS;
080483e1:   mov $0x0,%eax
32        }

基本上,我要求帮助我理解这个汇编代码,以及为什么它按照这个特定的顺序做事。我被卡住的地方显示在汇编注释中。谢谢!

4 个答案:

答案 0 :(得分:3)

0x080483cf0x080483d9正在从堆栈上的当前帧复制xy,并将它们作为{{1}的参数推回到堆栈(这是典型的;参见例如http://en.wikipedia.org/wiki/X86_calling_conventions#cdecl)。如果你看一下absdiff()的反汇编程序(从absdiff()开始),我打赌你会看到它从堆栈中挑选这些值并使用它们。

在这种情况下,这似乎是浪费周期,但这可能是因为你编译时没有进行优化,因此编译器确实按照你的要求进行编译。如果您使用例如0x8048394,你可能会看到大部分代码都消失了。

答案 1 :(得分:2)

答案 2 :(得分:1)

请记住,如果您在调试器或调试模式下运行,编译器保留插入其喜欢的任何调试代码并进行其他无意义代码更改的权利。

例如,这是Visual Studio的debug main():

int main(void) {  
001F13D0  push        ebp  
001F13D1  mov         ebp,esp  
001F13D3  sub         esp,0D8h  
001F13D9  push        ebx  
001F13DA  push        esi  
001F13DB  push        edi  
001F13DC  lea         edi,[ebp-0D8h]  
001F13E2  mov         ecx,36h  
001F13E7  mov         eax,0CCCCCCCCh  
001F13EC  rep stos    dword ptr es:[edi]  
    int x = 10;  
001F13EE  mov         dword ptr [x],0Ah  
    int y = 15;  
001F13F5  mov         dword ptr [y],0Fh  
    absdiff(x,y);
001F13FC  mov         eax,dword ptr [y]  
001F13FF  push        eax  
001F1400  mov         ecx,dword ptr [x]  
001F1403  push        ecx  
001F1404  call        absdiff (1F10A0h)  
001F1409  add         esp,8  
    *(int*)nullptr = 5;
001F140C  mov         dword ptr ds:[0],5  
    return 0;  
001F1416  xor         eax,eax  
}
001F1418  pop         edi  
001F1419  pop         esi  
001F141A  pop         ebx  
001F141B  add         esp,0D8h  
001F1421  cmp         ebp,esp  
001F1423  call        @ILT+300(__RTC_CheckEsp) (1F1131h)  
001F1428  mov         esp,ebp  
001F142A  pop         ebp  
001F142B  ret  

它有助于在相应的程序集旁边发布C ++源代码。在这种情况下,您可以清楚地看到x和y显式存储在堆栈中,并且推送显式副本,然后调用absdiff。我明确地取消引用了nullptr以使调试器中断。您可能希望更改编译器。

答案 3 :(得分:1)

使用-fverbose-asm -g -save-temps与GCC进行比较。