【问题标题】:What is the difference between calling "ret" vs calling the sys_exit number assembly gcc调用“ret”与调用 sys_exit 编号程序集 gcc 有什么区别
【发布时间】:2018-07-15 23:36:49
【问题描述】:

在 gcc 汇编中,主函数可以返回或退出,两者都可以工作。这里我有两个程序,一个以系统调用int $0x80 退出,另一个简单地调用 ret。有什么不同?

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

  ret

.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

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

【问题讨论】:

  • 如果您与 C 运行时链接,它将执行call main。当您执行 ret 时,它会返回到最终终止进程的 C 运行时。 sys_exit 系统调用避免返回调用 main 并请求操作系统停止进程的 C 运行时。
  • @MichaelPetch 如果我不与 c 运行时链接怎么办(当然,假设我更改了 puts 函数)
  • @MichaelPetch 另外,这两个选项有什么区别
  • 如果你不链接运行时,而且你在linux上,你根本不能使用ret,因为没有地方可以返回。
  • @Jester Cool,谢谢

标签: assembly


【解决方案1】:

调用main的代码如下:

int status = main(argc, argv, envp);
exit(status);

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

【讨论】:

  • 这个回复看起来像是针对 c 问题的......我的问题是关于汇编的。无论哪种方式,cmets 比这个答案更好地回答了我的问题,对不起。
  • @Riolku C 直接映射到任何平台上的 asm。 C 是描述 asm 功能的常用方法,是一种简写形式。您可以通过使用 GDB 的 stepi 命令跳过 main 末尾的 ret,单步进入调用您的 main 的实际 asm。在 x86-64 的 glibc 中,asm 看起来像 call rax / mov edi, eax / call exit,IIRC,并且存在于 libc 本身中。 CRT 启动代码将函数指针传递给main
猜你喜欢
  • 2013-09-30
  • 1970-01-01
  • 1970-01-01
  • 2017-07-27
  • 2016-10-28
  • 2013-09-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
相关资源
最近更新 更多