main 与 _start 中的返回值

car*_*ass 0 c assembly program-entry-point x86-64

请注意,这个问题在这里已经有类似的答案,我想指出:

然而,这个问题更多地询问它们的返回格式以及它们如何相互关联(我认为上面的问题没有完全涵盖)。


_start和之间有什么区别main?在我看来,像ld用途_start,但gcc用途main为切入点。我注意到的另一个区别是main似乎返回值 in %rax,而_start返回值 in%rbx

以下是我看到的两种方式的示例:

.globl _start
_start:
    mov $1, %rax
    mov $2, %rbx
    int $0x80
Run Code Online (Sandbox Code Playgroud)

并运行它:

$ as script.s -o script.o; ld script.o -o script; ./script; echo $?
# 2
Run Code Online (Sandbox Code Playgroud)

另一种方式:

.globl main
main:
    mov $3, %rax
    ret
Run Code Online (Sandbox Code Playgroud)

并运行它:

$ gcc script.s -o script; ./script; echo $?
3
Run Code Online (Sandbox Code Playgroud)

这两种方法有什么区别?是否main自动调用_start某处,或者它们如何相互关联?为什么一个返回它们的值,rbx而另一个返回它的值rax

Pet*_*des 8

TL:DR:函数返回值和系统调用参数使用单独的寄存器,因为它们完全不相关。


当您使用 编译时gcc,它会链接 CRT 启动代码,该代码定义了一个_start. _start(间接)调用main,并将main的返回值(主要留在 EAX 中)传递给exit()库函数。(在执行任何必要的 libc 清理(如刷新 stdio 缓冲区)之后,最终会进行退出系统调用。)

另请参阅从 C 中的 main 函数返回与退出- 这与您正在执行的操作完全相似,除了您使用的_exit()是绕过 libc 清理的exit(). exit() 的系统调用实现

根据int $0x8032 位系统调用 ABI(您不应在 64 位代码中使用),系统调用在 EBX 中采用其参数。 它不是函数的返回值,而是进程退出状态。看到带有 Linux 系统调用的汇编语言中的 Hello, world 吗?有关系统调用的更多信息。

请注意,这_start不是一个函数;它不能从这个意义上返回,因为堆栈上没有返回地址。 您正在采用诸如“返回操作系统”之类的随意描述并将其与函数的“返回值”混为一谈。可以打电话exitmain,如果你想要的,但你不能ret_start

EAX 是int函数调用约定中大小值的返回值寄存器。(RAX的高32位被忽略,因为main回报率int。但同时,$?退出状态只能得到低传给值的8位exit())。

有关的:


归档时间:

查看次数:

278 次

最近记录:

5 年,3 月 前