我正在使用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 }
基本上,我要求帮助我理解这个汇编代码,以及为什么它按照这个特定的顺序做事。我被卡住的地方显示在汇编注释中。谢谢!
答案 0 :(得分:3)
行0x080483cf
到0x080483d9
正在从堆栈上的当前帧复制x
和y
,并将它们作为{{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进行比较。