Dump of assembler code for function main:
0x0804833e <+0>: push %ebp
0x0804833f <+1>: mov %esp,%ebp
0x08048341 <+3>: sub $0x8,%esp
0x08048344 <+6>: and $0xfffffff0,%esp
0x08048347 <+9>: mov $0x0,%eax
0x0804834c <+14>: add $0xf,%eax
0x0804834f <+17>: add $0xf,%eax
0x08048352 <+20>: shr $0x4,%eax
0x08048355 <+23>: shl $0x4,%eax
0x08048358 <+26>: sub %eax,%esp
=> 0x0804835a <+28>: movl $0x10,-0x4(%ebp)
0x08048361 <+35>: movl $0x0,-0x8(%ebp)
0x08048368 <+42>: pushl -0x4(%ebp)
0x0804836b <+45>: call 0x8048334 <myfunc1 at test.c:4>
0x08048370 <+50>: add $0x4,%esp
0x08048373 <+53>: pushl -0x8(%ebp)
0x08048376 <+56>: call 0x8048339 <myfunc2 at test.c:8>
0x0804837b <+61>: add $0x4,%esp
0x0804837e <+64>: mov $0x0,%eax
0x08048383 <+69>: leave
0x08048384 <+70>: ret
End of assembler dump.
(gdb) info line
Line 16 of "test.c" starts at address 0x804835a <main+28 at test.c:16> and ends at 0x8048361 <main+35 at test.c:17>.------------------------------------(1)
(gdb) shell cat test.c
#include<stdio.h>
void myfunc1(int recv_arg1)
{
/* does nothing */
}
void myfunc2(int recv_arg1)
{
/* does nothing */
}
int main(int argc,char **argv)
{
int var1;
int var2;
var1 = 16;
var2 = 0;
myfunc1(var1);
myfunc2(var2);
return 0;
}
注意(1)main的asm代码在该范围内!!和此范围之前的asm代码是用于其他什么?什么 ?肯定是神秘的东西!!
答案 0 :(得分:9)
请允许我为您发表评论。
0x0804833e <+0>: push %ebp ; Establish standard
0x0804833f <+1>: mov %esp,%ebp ; stack frame record
0x08048341 <+3>: sub $0x8,%esp ; Make room for locals
0x08048344 <+6>: and $0xfffffff0,%esp ; Align esp to 16-byte memory
0x08048347 <+9>: mov $0x0,%eax ; eax=0
0x0804834c <+14>: add $0xf,%eax ; eax=f
0x0804834f <+17>: add $0xf,%eax ; eax= (eax + 0xf)
0x08048352 <+20>: shr $0x4,%eax ; ( >> 4)
0x08048355 <+23>: shl $0x4,%eax ; ( << 4)
;The above math rounds up eax as set by 0x0804834c to the next 16-byte boundary
;In this case, eax will be 0x10, rounded up from 0x0f. You compiled without
;optimizations? This could be a "probe" checking whether the upcoming call
;will fail?
0x08048358 <+26>: sub %eax,%esp ; Make room for "0x10 more mystery bytes"
0x0804835a <+28>: movl $0x10,-0x4(%ebp) ; var1 = 16
0x08048361 <+35>: movl $0x0,-0x8(%ebp) ; var2 = 0
0x08048368 <+42>: pushl -0x4(%ebp) ; push var1
0x0804836b <+45>: call 0x8048334 <myfunc1 at test.c:4> ;myfunc1( );
0x08048370 <+50>: add $0x4,%esp ; pop (var1)
0x08048373 <+53>: pushl -0x8(%ebp) ; push var2
0x08048376 <+56>: call 0x8048339 <myfunc2 at test.c:8> ;myfunc2( );
0x0804837b <+61>: add $0x4,%esp ; pop (var2)
0x0804837e <+64>: mov $0x0,%eax ; return 0;
0x08048383 <+69>: leave ; undo standard stack frame
0x08048384 <+70>: ret ; actual return
我认为这是一个很好的问题,为什么最终执行0x08048358
分配看似无用的空间。我怀疑这是在执行调用之前检查esp超出范围异常。如果你指定你正在使用的处理器,我想知道它是否会“消失” - 它闻起来可能是特定芯片的勘误表。
答案 1 :(得分:6)
0x0804833e <+0>
至(包括)0x08048358 <+26>
的代码正在设置所谓的stack frame。
前四个陈述非常标准。首先保存旧的基指针(在维基百科文章中称为帧指针)。然后使用堆栈指针的当前值设置新的基指针。
接下来,递减堆栈指针以便为局部变量腾出空间(注意你减去0x8,这对你来说足够两个整数)。最后,它确保堆栈指针与16位地址对齐。
下一组行(从0x08048347 <+9>
到0x08048358 <+26>
)有点奇怪。效果是增加堆栈,但我无法解释为什么它使用5条指令来计算值(因为没有变量,它应该能够在编译时执行此操作)或为什么需要更多地增加堆栈。
答案 2 :(得分:2)
这是猜测......我不太确定我是否正确理解了这个问题。
1 + 3 GT;到&lt; + 26&gt;看起来有点轻浮。也许是为了简化调试,使代码中的变量声明显式化?我敢打赌,如果启用了优化,几乎所有代码都会消失。
编辑:
既然我已经学会了横向滚动,我看到这似乎就是你所指的。该消息是说第16行(第一个分配)从主+ 28开始。
之前的所有代码都是设置堆栈来保存局部变量。
答案 3 :(得分:1)
通常函数需要一个序言和一个结尾(它取决于调用函数的约定,在处理器上也有点,......)。序言设置了传入的局部变量和参数以及最终其他东西所需的一切。结语“清除”了序幕所做的事情。
确切生成的代码取决于编译器及其版本。例如。用你的C代码做gcc -S
,得到不同的输出,当然如果我添加-On
选项,输出也会改变。
0x0804833e <+0>: push %ebp
save current ebp register
0x0804833f <+1>: mov %esp,%ebp
copy esp register to ebp (aka base pointer or frame pointer)
0x08048341 <+3>: sub $0x8,%esp
make rooms on the stack (for 2 32bit integers)
0x08048344 <+6>: and $0xfffffff0,%esp
align stack to multiple of 16
0x08048347 <+9>: mov $0x0,%eax
eax = 0
0x0804834c <+14>: add $0xf,%eax
eax += 15
0x0804834f <+17>: add $0xf,%eax
eax += 15 (eax == 30)
0x08048352 <+20>: shr $0x4,%eax
0x08048355 <+23>: shl $0x4,%eax
total effect: zeros less significant nibble of eax;
30 = b:11110 -> eax = b:10000
0x08048358 <+26>: sub %eax,%esp
more 16 bytes room on the esp
esp -> dword room made by last esp-eax
dword
dword
dword
... maybe stuffs because of alignment
dword first two dword created by esp-8 (var2)
dword (var1)
ebp -> dword original ebp ptr
...
=> 0x0804835a <+28>: movl $0x10,-0x4(%ebp)
put 16 in -4(ebp), so we realize that it is var1
0x08048361 <+35>: movl $0x0,-0x8(%ebp)
put 0 in -8(ebp) so we realize it is var2
0x08048368 <+42>: pushl -0x4(%ebp)
0x0804836b <+45>: call 0x8048334 <myfunc1 at test.c:4>
pass var1 to myfunc1 (args are passed on stack, by convention)
0x08048370 <+50>: add $0x4,%esp
and cleaning the stack is up to the caller
0x08048373 <+53>: pushl -0x8(%ebp)
0x08048376 <+56>: call 0x8048339 <myfunc2 at test.c:8>
0x0804837b <+61>: add $0x4,%esp
pass var2 to myfunc2 and "clears" the stack
0x0804837e <+64>: mov $0x0,%eax
return value (0)
0x08048383 <+69>: leave
is the same as doing esp = ebp; pop ebp, i.e. take the stack
back at the initial point after the first push, and then retrieve
back original ebp value
0x08048384 <+70>: ret
return to the caller (return 0 <- eax)
此代码不是最理想的。它做了不必要的事情,并不是我用gcc v 4.3.2得到的,没有优化。特别是,像两个立即添加的东西可以成为一个添加(即使在默认优化的最基本阶段),并且shr-shl对可以成为单个和。实际上,这段代码对我来说比“普通”编译器输出看起来更奇怪。