【问题标题】:Segmentation Fault: int 80h [duplicate]分段错误:int 80h [重复]
【发布时间】:2018-04-11 20:44:52
【问题描述】:

最近我一直在学习 NASM x86 汇编。在编写代码时,每当我使用 int 21hint 80h 或任何中断时,它都会返回分段错误。整个程序是:

section .data
    msg: dw 'Hello World!', 10
section .text
    global _main

_main:
    mov eax, 4
    mov ebx, 1
    mov ecx, msg
    int 80h

非常感谢任何关于我可以在哪里了解更多关于 NASM 的帮助或提示。

【问题讨论】:

  • 您正在为什么操作系统编程?你在为什么架构编程?请注意,系统调用仅适用于为其设计的操作系统,因此使用 int 21h 将无法在 Linux 上运行,而使用 int 80h 将无法在 DOS 上运行。
  • 还有,你的程序在write系统调用后没有代码,所以即使系统调用成功也会崩溃。
  • 如果你使用的是win10的“linux in windows”(不知道具体是怎么调用的),那么那个内核只有64位,所以int 0x80不起作用,你必须构建 elf64 二进制文件并使用正确的 64b 系统 ABI 来调用服务(使用syscall 指令)...要拥有 32b 兼容内核,您必须将完整的 linux 安装到某些 VM 中。
  • @AlexDukhan 您不能只在末尾添加syscall 指令并期望它能够正常工作。使用 syscall 指令的 Linux 系统调用适用于 amd64,并且工作方式不同。我建议你坚持一个教程并在实际的 Linux 上运行你的代码,而不是 WSL。您似乎陷入了试图从多个教程中复制代码而不了解其实际作用的陷阱,然后当它不起作用时感到沮丧。
  • @AlexDukhan 请在您的问题中添加您尝试过的确切程序以及您键入的用于组装和运行该程序的确切命令 - 无论您如何组装,您刚刚发布的程序都无法工作,因为它实际上不包含要终止的代码,因此它只会在 write 系统调用后崩溃。此外,_main 是编写 Linux 程序时的错误入口点。做错事的方式有很多,所以对你来说,具体一点很重要,否则很难帮助你。

标签: assembly nasm


【解决方案1】:

每当我使用int 21hint 80h

int 指令是 call 指令的特殊变体,它调用操作系统中的某些函数。

这当然意味着int 指令在不同操作系统中的行为不同:

int 21h

在 MS-DOS 和 16 位 Windows (Windows 3.x) 中使用了中断 21h。因此该指令只能用于 MS-DOS 和 16 位 Windows 程序。

32 位(或 64 位)Windows 程序不支持中断。 Linux 也不支持这种中断。

int 80h

32 位 Linux 程序支持此中断。 64 位 Linux 版本可以运行 32 位 Linux 程序(但您必须确保您创建的程序确实是 32 位程序而不是 64 位程序)。

其他中断(如int 10h

... Linux 和最新的 Windows 版本都不支持。 (它们在 16 位 Windows 中受支持。)

int 80h ...它返回一个分段错误。

在 Linux 下,您可以运行 strace 命令来查看 int 80h 系统调用发生了什么。

我用你的程序做了这个,得到了以下输出:

$ strace ./x.x
execve("./x.x", ["./x.x"], [/* 54 vars */]) = 0
strace: [ Process PID=3789 runs in 32 bit mode. ]
write(1, "", 0)                         = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=NULL} ---

可以看到int 80h没有产生错误但是正确执行了。

但是edx 寄存器的值为 0。因此int 80h 将输出“Hello World”的前 0 个字节(= 无)。

您必须在 int 80h 指令之前添加指令 mov edx, 13

分段错误稍后发生!

作为一个汇编语言的初学者,你应该首先了解什么汇编程序是:每条汇编程序指令代表RAM内存中的一些字节。

例如指令mov eax, 4代表字节184, 4, 0, 0, 0或指令int 80h代表字节205, 128

您的汇编程序在指令int 80h 之后结束。然而,RAM 内存当然不会在字节205, 128 之后结束。 RAM 内存将在字节205, 128 之后包含随机数据。

也许在该字节之后找到的 RAM 中的字节是 160, 0, 0, 0, 0,它等于 mov al, [0]会导致分段错误。

您必须在int 80h 指令之后添加一些指令,这些指令将停止您的程序。否则CPU会将int 80h指令之后的RAM中的字节解释为指令并执行它们......

【讨论】:

  • 我关闭了这个作为另一个脱落-the-end-of-_start 问题的副本,但是如果你还没有发布这个好的答案,我会这样做的。也许这意味着我不应该有,但我认为这只是一个虚假的问题,其中有 2 种完全不同的事情正在发生:那个错误 + DOS 问题。
  • 感谢您的所有帮助。我会尽力使用它。再次感谢!
猜你喜欢
  • 2020-12-03
  • 2011-10-01
  • 2012-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 2013-08-25
相关资源
最近更新 更多