x86_64 汇编 Linux 系统调用混淆

2024-11-11 08:27:00
admin
原创
216
摘要:问题描述:我目前正在学习 Linux 上的汇编语言。我一直在使用《从头开始编程》这本书,所有示例都是 32 位的。我的操作系统是 64 位的,我一直试图用 64 位来完成所有示例。但我遇到了麻烦:.section .data .section .text .global _start _start: mov...

问题描述:

我目前正在学习 Linux 上的汇编语言。我一直在使用《从头开始编程》这本书,所有示例都是 32 位的。我的操作系统是 64 位的,我一直试图用 64 位来完成所有示例。但我遇到了麻烦:

.section .data

.section .text
.global _start
_start:
movq $60, %rax
movq $2, %rbx
int $0x80

这仅仅只是调用了 Linux 退出系统调用,或者它应该这样做。相反,它导致了 SEG FAULT,当我这样做时

.section .data

.section .text
.global _start
_start:
movq $1, %rax
movq $2, %rbx
int $0x80

它有效。显然问题在于我移动到 %rax 的值。我在第二个示例中使用的值 $1 是“从头开始编程”中所说的值,但是互联网上的多个来源都说 64 位系统调用号是 $60。参考
我做错了什么?此外,我还应该注意哪些其他问题,我应该使用什么作为参考?以防万一你需要知道,我正在阅读“从头开始编程”的第 5 章。


解决方案 1:

您遇到了 i386 和 x86_64 之间的一个令人惊讶的差异:它们不使用相同的系统调用机制。正确的代码是:

movq $60, %rax
movq $2,  %rdi   ; not %rbx!
syscall

中断0x80总是调用 32 位系统调用。它用于允许 32 位应用程序在 64 位系统上运行。

出于学习目的,您可能应该尝试严格遵循教程,而不是临时转换为 64 位——您可能会遇到其他一些重大的行为差异。一旦您熟悉了 i386,可以单独选择 x86_64。

解决方案 2:

请阅读此文:x86-64 上 UNIX 和 Linux 系统调用的调用约定是什么

并注意int 0x80在 x64 系统上使用 syscall 是一个旧的兼容层。您应该syscall在 x64 系统上使用指令。

您仍然可以使用这种旧方法,但是您需要在 x86 模式下编译您的二进制文件,请参阅您的编译器/汇编器手册以了解详细信息。

解决方案 3:

duskwuff的回答正确指出了 64 位 x86 Linux 与 32 位 Linux 的系统调用机制不同。

然而,这个答案并不完整,而且具有误导性,原因如下:

  • 这一变化实际上是在 64 位系统流行之前引入的,其动机int 0x80是 Pentium 4 上的速度非常慢。Linus Torvalds使用/指令编写了一个解决方案SYSENTER`SYSEXIT(该指令由 Intel 在 Pentium Pro 时代引入,但存在缺陷且没有实际好处)。因此**现代 32 位 Linux 系统实际上使用的是SYSENTER,而不是int 0x80`**。

  • 64 位 x86 Linux 内核实际上并不使用SYSENTERSYSEXIT。它们实际上使用非常相似的SYSCALL/SYSRET指令。

正如评论中指出的那样,它实际上在许多 64 位 Linux 系统(即 64 位AMDSYSENTER 系统)上不起作用

这确实是一个令人困惑的情况。详细情况如下,但归根结底是这样的:

对于 32 位内核,SYSENTER/SYSEXIT 是[AMD 和 Intel CPU 之间]唯一兼容的对

对于长模式下的 64 位内核... SYSCALL/SYSRET 是[AMD 和 Intel CPU 之间]唯一兼容的对

看起来,在64 位模式的Intel CPU 上,您可以使用,SYSENTER因为它执行的操作与相同SYSCALL,但对于 AMD 系统而言并非如此。

底线:始终SYSCALL在 64 位 x86 系统上的 Linux 上使用。这是 x86-64 ABI 实际指定的。(有关更多详细信息,请参阅这个很棒的wiki 答案。)

解决方案 4:

i386 和 x86_64 之间有很多变化,包括用于进入内核的指令和用于携带系统调用参数的寄存器。以下是与您的代码等效的代码:

.section .data

.section .text
.global _start
_start:
movq $60, %rax
movq $2, %rdi
syscall

引用这个相关问题的答案:

系统调用编号位于 Linux 源代码的 arch/x86/include/asm/unistd_64.h 下。系统调用编号在 rax 寄存器中传递。参数位于 rdi、rsi、rdx、r10、r8、r9 中。调用由“syscall”指令调用。系统调用覆盖 rcx 寄存器。返回值位于 rax 中。

解决方案 5:

如果您检查/usr/include/asm/unistd_32.h退出对应于1但在
/usr/include/asm/unistd_64.h退出对应于60

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用