调用“ret”与调用 sys_exit 编号程序集 gcc 有什么区别

Rio*_*lku 1 assembly

在 gcc 汇编中,main 函数可以返回或退出,两者都起作用。这里我有两个程序,其中一个通过 syscall 退出int $0x80,另一个只是调用 ret。有什么不同?

.data
hello: .string "Hello, World!"
.globl main
main:
  push %rbx
  movq $hello, %rdi
  call puts
  pop %rbx

  ret
Run Code Online (Sandbox Code Playgroud)

.data
hello: .string "Hello, World!"
.globl main
main:
  push %rbx
  movq $hello, %rdi
  call puts
  pop %rbx

  movq $1, %rax
  movq $0, %rbx
  int $0x80
Run Code Online (Sandbox Code Playgroud)

我知道 ret 将指令指针从堆栈中弹出,但是在这种情况下它到底有什么作用呢?

fuz*_*fuz 5

调用的代码main如下所示:

int status = main(argc, argv, envp);
exit(status);
Run Code Online (Sandbox Code Playgroud)

如果main返回exit(status)则执行。 exit是一个 C 库函数,它刷新所有 stdio 流,调用atexit()处理程序并最终调用_exit(status),它是系统调用的 C 包装器SYS_exit。如果您使用 C 运行时(例如,通过让程序启动main或使用任何 libc 函数),我强烈建议您永远不要SYS_exit直接调用,以便 C 运行时有机会正确地取消初始化程序。最好的办法通常是打电话exit()或返回,main除非您确切知道自己在做什么。

  • @Riolku,C 直接映射到任何平台上的 asm。C 是描述 asm 功能的常用方式,作为一种简写。您可以使用 GDB 的“stepi”命令单步执行调用“main”的实际 asm,以跳过“main”末尾的“ret”。在 x86-64 的 glibc 中,asm 看起来像 `call rax` / `mov edi, eax` / `call exit`、IIRC,并且存在于 libc 本身中。CRT 启动代码向其传递一个指向“main”的函数指针。 (3认同)