我编写了一个简单的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
的代码吗?
答案 0 :(得分:2)
以下是您发布的代码的评论assembly source。
总结,它做了以下事情:
esi
,以便我们将其传递给__libc_start_main
__libc_csu_fini
,__libc_csu_init
的地址,参数向量,参数数量和main
的地址作为参数推送到__libc_start_main
__libc_start_main
被调用。此函数(源代码here)设置一些glibc内部变量,最终调用main
。它永远不会回来。__libc_start_main
应该返回,则会在之后发出hlt
条指令。用户代码中不允许使用此指令,并且应该导致程序崩溃(希望如此)。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。