为什么我的机器在这段代码中将堆栈指针减少了20?

时间:2012-11-04 21:11:24

标签: c gcc assembly architecture gdb

我有以下用GCC编译的C代码,并在gdb中反汇编为程序集。我正在使用配备64位Intel i5处理器的Macbook pro。在'main()'中'char * name [2]'有2个char指针,它们应该让堆栈指针减少2个字(16个字节)?但是,当我在gdb中反汇编它减少20 ...有人能帮助我理解吗? C代码:

#include <stdio.h>
#include <unistd.h>
int main(void)
{   
    char* name[2];
    name[0] = "/bin/sh";
    name[1]= NULL;
    execve(name[0],name,NULL);
}

gdb反汇编代码:

GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Thu Nov  3 21:59:02 UTC 2011)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin"...Reading symbols for shared libraries .. done

(gdb) disassemble main
Dump of assembler code for function main:
0x0000000100000ee0 <main+0>:    push   %rbp
0x0000000100000ee1 <main+1>:    mov    %rsp,%rbp
0x0000000100000ee4 <main+4>:    sub    $0x20,%rsp
0x0000000100000ee8 <main+8>:    lea    -0x18(%rbp),%rax
0x0000000100000eec <main+12>:   lea    0x61(%rip),%rcx        # 0x100000f54
0x0000000100000ef3 <main+19>:   mov    %rcx,-0x18(%rbp)
0x0000000100000ef7 <main+23>:   movq   $0x0,-0x10(%rbp)
0x0000000100000eff <main+31>:   mov    -0x18(%rbp),%rcx
0x0000000100000f03 <main+35>:   mov    $0x0,%rdx
0x0000000100000f0d <main+45>:   mov    %rcx,%rdi
0x0000000100000f10 <main+48>:   mov    %rax,%rsi
0x0000000100000f13 <main+51>:   callq  0x100000f22 <dyld_stub_execve>
0x0000000100000f18 <main+56>:   mov    -0x4(%rbp),%eax
0x0000000100000f1b <main+59>:   add    $0x20,%rsp
0x0000000100000f1f <main+63>:   pop    %rbp
0x0000000100000f20 <main+64>:   retq   
End of assembler dump.

3 个答案:

答案 0 :(得分:4)

因此,读取程序集时,名称[0]在堆栈上为-0x18,名称[1]为-0x10。另外,如前所述,-0x4用于返回值。

留下12个字节,因为0x20实际上是32.范围是-32到-24,范围是-8到-4。 -8到-4肯定是对齐的,我猜-32到-24也是(16字节对齐)。

编辑:请注意,实际上减去了48个字节。调用main的callq指令减去8个字节,并将%rpb推送到另一个8。

编辑2:验证16字节对齐:http://www.x86-64.org/documentation/abi.pdf第3.2.2节

答案 1 :(得分:1)

我猜这个“奇怪的”堆栈帧格式与“懒惰绑定”调用约定有关,显然在你的调用中使用它。即你实际上是在调用惰性绑定存根dyld_stub_execve,而不是execve本身。调用后从-0x4(%rbp)读取的结果代码可能是绑定失败时返回的错误代码。

如果您静态链接库,我想为该调用准备的堆栈帧看起来会更常规。

<强> P.S。我的答案可能是纯粹的无意义,因为堆栈帧形成代码是在编译期间生成的,而使用静态或共享库的决定仅在链接时进行。

答案 2 :(得分:0)

如果您正在谈论<main+4>行,则不会减去20(在基数10中)。它在基数16中减去20,即16^1 * 2 + 16^0 * 0等于32,或者大小为2个字。