【问题标题】:What happens if there is no exit system call in an assembly program?如果汇编程序中没有退出系统调用会发生什么?
【发布时间】:2018-09-15 08:59:00
【问题描述】:

在汇编程序中,.text 部分在0x08048000 处加载; .data.bss 部分紧随其后。

如果我.text 部分中放置exit 系统调用会怎样?它会导致.data.bss 部分被解释为导致“不可预测”行为的代码吗?程序什么时候终止——可能是在每个“指令”执行之后?

我可以在没有exit 系统调用的情况下轻松编写程序,但测试.data.bss 是否被执行是我不知道的,因为我想我必须知道生成的真实机器代码了解这一点。

我认为这个问题更多的是关于“操作系统和 CPU 将如何处理这种情况?”比汇编语言,但对于汇编程序员等来说,了解它仍然很有趣。

【问题讨论】:

  • 执行将继续到您的代码之后的任何内容,是的。这可能迟早会遇到无效指令,或者您将遇到未映射的内存。如果你非常幸运,你可能会遇到一个无害的无限循环,在这种情况下你的程序不会终止。
  • @Jester 我会说赢得彩票的机会比陷入无休止的循环要多。
  • @TonyTannous 我确实说过“非常幸运”:D 但是,您可以使用 2 个字节在 x86 中进行无限循环,并假设随机内存内容已经比我知道的任何彩票都好。不幸的是,您可能会遇到一些零字节而不是随机的,那就是 x86 上的 add al, [eax],这可能会出错。
  • 作为记录,00 00 解码为 add [eax], al:内存 destination,而不是内存源,因此 EAX(或 64 位代码中的 RAX)必须指向在可写内存中,但重复执行不会改变地址的低字节。

标签: linux assembly operating-system termination


【解决方案1】:

处理器不知道您的代码在哪里结束。它忠实地执行一条又一条指令,直到执行被重定向到其他地方(例如,通过跳转、调用、中断、系统调用或类似方式)。如果你的代码没有跳转到其他地方就结束了,处理器会继续执行你的代码之后内存中的任何内容。究竟会发生什么是相当不可预测的,但最终,您的代码通常会崩溃,因为它试图执行无效指令或试图访问不允许访问的内存。如果两者都没有发生并且没有发生跳转,最终处理器会尝试将未映射的内存或标记为“不可执行”的内存作为代码执行,从而导致分段违规。在 Linux 上,这会引发 SIGSEGVSIGBUS。如果未处理,它们会终止您的进程并选择性地生成核心转储。

【讨论】:

  • 在 CPU 级别,您所说的异常是页面错误 (#PF),与段无关。 x86 Linux 上的 32 位或 64 位进程以 CS base=0 / limit = unlimited 运行。 SIGSEGV 中的“分段”基本上与 x86 段无关,因为这不是 x86 Linux 用于内存保护的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-16
  • 1970-01-01
相关资源
最近更新 更多