【问题标题】:Segfault when doing syscall using GNU assember使用 GNU 汇编器进行系统调用时出现段错误
【发布时间】:2017-11-07 23:51:04
【问题描述】:

我试图理解为什么as 在汇编级别进行系统调用时的行为与nasm 不同。因为我喜欢惩罚,所以我使用的是 Intel 语法。这是我的程序:

    .intel_syntax noprefix
    .section    .rodata
.LC0:
    .string "Hello world!\n"
    .text
    .globl  _start
    .type   _start, @function
_start:
    mov edx, 13
    mov ecx, OFFSET FLAT:.LC0
    mov eax, 4
    int 0x80
    ret

我与as -o prog.o prog.s 组装并与ld -s -o prog prog.o 链接。

但是当我运行它时,我得到:

$ ./prog 
Hello world!
Segmentation fault (core dumped)

GDB 在这里并不是特别有用。当我在retstepi 时,它会显示Cannot access memory at address 0x1。令人费解的是,ESP 的值是:

(gdb) info registers esp
info registers esp
esp            0xbffff660       0xbffff660

为什么这个程序会出现段错误?

【问题讨论】:

  • 你不能只在你的程序中使用ret,你需要一个exit系统调用。 1 是恰好位于堆栈顶部的参数 (argc) 的数量,因此 ret 尝试将其用作具有明显后果的地址。

标签: linux assembly x86 system-calls gnu


【解决方案1】:

因为它永远不会正确退出。 _start 没有父栈帧,所以从它返回会导致崩溃。

您可以从main 返回,让标准库的_start 实现为您调用exit,但如果您正在编写自己的_start,您需要自己调用exit,因为没有要返回的父堆栈帧。

【讨论】:

  • @DanBarowy 大部分抄袭?我冒险主要可能是问题所在。如果ret 正在工作,那么_start 将不是入口点,main 将是。由于您需要 C 运行时,因此链接它的方式会有所不同。您主要从书中的哪个页面/示例中复制?
  • 我的最后一条评论似乎是一条现已删除的评论 ;-)
  • @DanBarowy 我会更进一步:那本书简直就是垃圾,应该被丢弃。它读起来像是为 DOS 程序员编写的,然后在最后一刻匆忙适应了 Linux。 (而且许多 Linux 细节已经严重过时,因为这本书是 2000 年出版的……)
  • 另外,一个搞笑的细节:edlinas,“No.1 Linux x86 动手汇编开发模拟器”(至少从封面上看)实际上是一个 QBasic 程序,并且只能在DOS下运行。
  • 是的@MichaelPetch 和@duskwuff,我意识到在我发表评论后我已经用_start 替换了main,这导致了我意识到我 i> 是这里的白痴。所以我删除了评论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-08
  • 2016-11-08
  • 2022-01-04
  • 2016-01-16
  • 2020-03-10
  • 2015-04-30
  • 1970-01-01
相关资源
最近更新 更多