【问题标题】:why does this give a segmentation fault? it should just exit为什么这会产生分段错误?它应该退出
【发布时间】:2010-09-25 21:43:33
【问题描述】:

我正在尝试学习低级开发。通过将 0 放入 ebx 并将 1 放入 eax(用于 exit() 系统调用)并调用 int 0x80,它应该退出程序。 我有一个运行良好的简单 c 程序,但是当我将其粘贴进去时,我没有按预期退出,而是出现了分段错误。为什么会这样?

谢谢!

 __asm__ ("xor %ebx, %ebx;"
                 "mov %al, 1;"
                "int $80;"
);

编辑:感谢您的建议,不过还是有段错误。 这是我所做的修改:

  __asm__ ("xor %ebx, %ebx;"
           "xor %eax, %eax;"
                "mov $1, %eax;"
                "int $80;"
);

编辑:从http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html修改此示例后

asm("movl $1,%%eax;         /* SYS_exit is 1 */
             xorl %%ebx,%%ebx;      /* Argument is in ebx, it is 0 */
             int  $0x80"            /* Enter kernel mode */
             );

这终于对我有用了:

asm("   movl $1,%eax;
        xorl %ebx,%ebx;
        int  $0x80
"
        );

感谢您的关注和提供建议。

【问题讨论】:

  • 我不知道asm,但是%aleax 是一样的吗?为什么用“C”标记?
  • c 标签在那里,因为它被按原样粘贴到 c 程序中,并用 gcc 编译。
  • 请尝试int $0x80 而不是int $80。我很确定十进制表示法是默认值。

标签: linux assembly


【解决方案1】:

您确定eax 的其余部分已清除吗?尝试将 1 移动到 eax 而不仅仅是 al 或至少先清除它。

__asm__ ("xor %ebx, %ebx;"
         "mov $1, %eax;"
         "int $0x80;"
);

编辑:如果 AndiDog 关于 AT&T 语法是正确的。

编辑:我已经有一段时间没有使用天然气了,但 8016$0x80$80 是 8010。这应该可以解决最后一个问题。

【讨论】:

  • 这对我有用(x86-64/Linux,用 -m32 编译)除了它应该是 "mov $1, %eax" 而不是 "mov 1, %eax" -- 后者尝试读取地址 00000001 处的内存,这当然是段错误。 (从技术上讲,它应该是“xorl”和“movl”,但不管怎样,GAS 似乎都能做到。)
  • @Zack:是的,谢谢。我只是在对 heally 的代码进行调整作为示例而忘记了语法。已经有一段时间了...... :)
  • @Zack:忘了提到 GAS 中的 MOV 是一条综合指令 AFAIK,必要时会在汇编器中转换为适当的移动指令。我知道这适用于 RISC 架构,但不知道这对于 x86 尤其必要。
  • 我花了很多时间阅读 GCC 程序集转储,但几乎没有时间自己编写程序集,所以我不知道。谢谢你的花絮!
【解决方案2】:

这看起来像 AT&T 汇编语法,所以操作的顺序是“操作源,目标”,而不是更常见的英特尔语法中的“操作目标,源”。

知道了这一点,mov %al, 1; 尝试将al 寄存器的内容写入内存位置 1。将其更改为mov 1, %al;,它应该可以在 IMO 中工作。请注意,我从未使用过 AT&T 语法,所以我不确定我是否正确解释了它。

编辑: Jeff M 是对的,系统调用号必须存储在eax 寄存器中,因此请确保将其清除。

【讨论】:

    猜你喜欢
    • 2011-01-27
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2018-03-17
    • 2016-01-09
    相关资源
    最近更新 更多