Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 为什么帧指针保存在主函数的开头_C_Assembly_X86 64_Stack Frame - Fatal编程技术网

C 为什么帧指针保存在主函数的开头

C 为什么帧指针保存在主函数的开头,c,assembly,x86-64,stack-frame,C,Assembly,X86 64,Stack Frame,假设此C代码: int main(){ return 0; } 在装配中的外观如下所示: main: pushq %rbp movq %rsp, %rbp movl $0, %eax popq %rbp ret 我知道帧指针fp需要通过pushq%rbp保存在函数的开头,因为它需要在返回调用函数时恢复 我的问题是为什么要在main中这样做?main的父调用方是什么?fp不是指向一个虚拟地址吗,这意味着当main终止地址时,对

假设此C代码:

int main(){
   return 0;
}
在装配中的外观如下所示:

main:
    pushq   %rbp
    movq    %rsp, %rbp
    movl    $0, %eax
    popq    %rbp
    ret
我知道帧指针
fp
需要通过
pushq%rbp
保存在函数的开头,因为它需要在返回调用函数时恢复

我的问题是为什么要在
main
中这样做?
main
的父调用方是什么?
fp
不是指向一个虚拟地址吗,这意味着当
main
终止地址时,对下一个程序不再意味着什么,对吗

fp
(甚至是sp)值是否在不同程序及其地址空间之间保持不变

main的父调用方是什么


在linux中,
main
是由
\uu libc\u start\u main
调用的,在windows中,我不太确定,但也有一个
\u start

事实上,一个巧妙的技巧是在不使用
main
的情况下启动C程序:

#include <stdio.h> 
#include <stdlib.h>

void _start() 
{  
    printf("No main function!\n");
    exit(0); 
} 
适用于Windows(10,gcc 8.1.0)和Ubuntu(18.04,gcc 9.2.0)

适用于MacOS(10.14.6,Xcode 11.3)


这里有一篇文章谈到另一个函数调用了

main
,因此它需要返回到另一个函数。那么在加载新程序时,如何设置sp/fp值?它的旧值是重复使用还是加载程序重置了它们?@Nic这是实现定义的行为,取决于您使用的操作系统和二进制格式。例如,在现代Linux系统上,
rbp
开始时为零,而
rsp
指向堆栈上的第一个空闲地址,在该地址上可以找到一些有用的数据(参数、环境、ELF aux向量)。每次启动程序时,该地址都是随机的。@fuz:在x86-64 System V ABI中,进程启动状态的RSP指向堆栈上的
argc
,而不是它下面的可用空间。但是是的,所有这些都记录在ABI中,并且argv[]和envp[]都在上面。如果使用“-O2”进行编译,您将有一个
main
主体,其中包含如下内容:
xorl%eax,%eax;ret
,这样就消除了堆栈帧。事实上,现代调试器甚至不需要帧指针寄存器,如果启用,通常可以使用调试信息执行调试。请注意,提供自己的
\u start
可能会导致libc无法正确初始化。除非您确切知道自己在做什么,否则不要这样做。@fuz,是的,您是正确的,这只是一个小示例,说明
main()
不是程序启动的开始。这篇文章说明了你的观点。这并没有回答这个问题。@BrettHale,有几个问题,其中一个是“main的父调用程序是什么?”因此它确实回答了这个问题,至少部分回答了这个问题,这一点已被接受。@anastaciu:“为什么框架指针保存在main函数的开头?”-你不回答这个。此外,当问题或标记中没有提到Linux时,您会提到Linux特定的运行时。OP可以自由地接受它,我也可以自由地批评它。
gcc main.c -nostartfiles
clang -Wl,-e,-Wl,__start main.c