有人可以解释汇编代码吗?

时间:2011-04-20 12:43:18

标签: assembly x86

装配新手。我有以下功能

int foo(char *argv[])
{
   char buf[256];
   bar(argv[1], buf);
}

汇编中的哪一个 -

0x08048473 <foo+0>:push   %ebp
0x08048474 <foo+1>:mov    %esp,%ebp
0x08048476 <foo+3>:sub    $0x118,%esp
0x0804847c <foo+9>:mov    0x8(%ebp),%eax
0x0804847f <foo+12>:add    $0x4,%eax
0x08048482 <foo+15>:mov    (%eax),%edx
0x08048484 <foo+17>:lea    -0x100(%ebp),%eax
0x0804848a <foo+23>:mov    %eax,0x4(%esp)
0x0804848e <foo+27>:mov    %edx,(%esp)
0x08048491 <foo+30>:call   0x8048454 <bar>
0x08048496 <foo+35>:leave  
0x08048497 <foo+36>:ret    

有人可以向我解释一下吗?为什么那里有280个?确保堆栈上分配256个字节。我无法解释其余的事情。

1 个答案:

答案 0 :(得分:4)

堆栈用于局部变量,但也用于函数所需的中间值。在这里,您的foo()函数通过给它两个指针调用bar(),一个指向字符串(argv[1]),另一个指向buf变量;那些指针值被压入堆栈,即mov %eax,0x4(%esp)mov %edx,(%esp)操作码。因此,foo()需要多于256字节的堆栈空间。

更多细节:

0x08048473 <foo+0>:push   %ebp
0x08048474 <foo+1>:mov    %esp,%ebp

这是标准函数序言:函数将在调用之前使用%ebp指向堆栈元素(即其参数)。

0x08048476 <foo+3>:sub    $0x118,%esp

堆栈上保留了一些空间,主要(但不仅限于)buf[]

0x0804847c <foo+9>:mov    0x8(%ebp),%eax
0x0804847f <foo+12>:add    $0x4,%eax
0x08048482 <foo+15>:mov    (%eax),%edx

0x8(%ebp)argv函数参数;这些操作码从argv[1]获取指针并将结果存储在%edx中。这将成为bar()的第一个参数。

0x08048484 <foo+17>:lea    -0x100(%ebp),%eax

这将%eax的地址存储在buf[]中 - 编译器确定buf[]位于它为{{1}保留的堆栈空间的高256字节中}。

sub

0x0804848a <foo+23>:mov %eax,0x4(%esp) 0x0804848e <foo+27>:mov %edx,(%esp) 的两个参数被推到堆栈上(实际上,写在两个顶部堆栈位置,bar()已经调整过了。)

%esp

0x08048491 <foo+30>:call 0x8048454 <bar> 被调用。

bar()

0x08048496 <foo+35>:leave 0x08048497 <foo+36>:ret 取消序幕(相当于leave)。 mov %ebp, %esp; pop %ebp退出该功能。

众所周知,GCC会在堆栈上进行一些分配;在这里,它可能保留了264个字节而不是280个。这似乎是其内部寄存器分配优化器的一个人工制品(额外的堆栈插槽 用于存储中间值,但优化器终于找到了方法仅在寄存器中保留相应的值。)