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

我写了一个简单的C程序,并试图使用GDB来debugging程序。 我明白在主要function中使用以下内容:

在进入

push %ebp mov %esp,%ebp 

退出时

 leave ret 

然后我尝试gdb的_start,我得到了以下

 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的代码?

以下是您发布代码的评论汇编源代码。

总结起来,它做了以下几件事情:

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

对于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