了解C程序中的汇编语言_start标签

时间:2016-02-20 05:14:48

标签: linux gcc assembly x86 glibc

我编写了一个简单的c程序,并尝试使用GDB来调试程序。我理解在main函数中使用以下内容:

入境时

push   %ebp
mov    %esp,%ebp

退出

leave
ret

然后我在_start上尝试了gdb,我得到了以下内容

xor    %ebp,%ebp
pop    %esi
mov    %esp,%ecx
and    $0xfffffff0,%esp
push   %eax
push   %esp
push   %edx
push   $0x80484d0
push   $0x8048470
push   %ecx
push   %esi
push   $0x8048414
call   0x8048328 <__libc_start_main@plt>
hlt
nop
nop
nop
nop

我无法理解这些界限及其背后的逻辑。

有人可以提供任何指导来帮助解释_start的代码吗?

2 个答案:

答案 0 :(得分:2)

以下是您发布的代码的评论assembly source

总结,它做了以下事情:

  1. 使用ebp = 0建立一个标记堆栈框架,因此遍历堆栈的代码可以轻松找到它的结尾
  2. 将命令行参数的数量弹出到esi,以便我们将其传递给__libc_start_main
  3. 将堆栈指针与16位的倍数对齐,以符合ABI。在某些版本的Linux中不能保证这种情况,因此必须手动完成以防万一。
  4. __libc_csu_fini__libc_csu_init的地址,参数向量,参数数量和main的地址作为参数推送到__libc_start_main
  5. __libc_start_main被调用。此函数(源代码here)设置一些glibc内部变量,最终调用main。它永远不会回来。
  6. 如果由于任何原因__libc_start_main应该返回,则会在之后发出hlt条指令。用户代码中不允许使用此指令,并且应该导致程序崩溃(希望如此)。
  7. 最后一系列nop指令是汇编程序插入的填充,因此下一个函数以16字节的倍数开始,以获得更好的性能。在正常执行中永远不会达到它。

答案 1 :(得分:-2)

对于gnu工具,_start标签是程序的入口点。要使C语言工作,你需要有一个堆栈,你需要将一些内存/变量归零,一些设置为你选择的值:

int x = 5;
int y;

int fun ( void )
{
   static int z;
}

这三个变量x,y,z基本上都是全局的,一个是局部全局变量。因为我们以这种方式编写它,我们假设当我们的程序开始时x包含值5并且假设y为零。为了使这些事情发生,需要一些引导代码,这就是_start和main()之间发生的事情(以及更多)。

其他工具链可以选择使用不同的标签来定义入口/起点,但gnu工具使用_start。在main()被称为C ++之前,您的工具可能还需要其他东西,例如,需要的不仅仅是C。