【问题标题】:MOV DS, EAX segfaults?MOV DS,EAX 段错误?
【发布时间】:2020-11-11 14:45:12
【问题描述】:

当我运行mov ds,rax时,它会抛出错误Program terminated with signal SIGSEGV, Segmentation fault

汇编代码有什么问题?


global main

main:
    mov rax,0ffffH
    mov ds,rax
    mov rbx,6
    ret

【问题讨论】:

  • 请不要发布文字图片。

标签: assembly gdb x86-64 memory-segmentation


【解决方案1】:

mov 到段寄存器从the GDT (Global Descriptor Table) 加载内部段基础/限制/权限内容。 (在 64 位模式下,base 和 limit 分别被视为 0 / -1,但mov 到段寄存器仍然具有实际效果并且仍然检查内容。你不能期望任意值不会导致问题。 )

根据Intel's manual for mov,如果“段选择器索引”(GDT 或 LDT 的索引)“超出描述符表限制”,mov Sreg, r/m 会出现 #GP(selector) 故障。

如果用户空间导致无效页面错误或任何类型的#GP 异常,Linux 会提供 SIGSEGV。

由于设置了第 2 位 (1<<2),因此这是对 LDT(本地描述符表)的索引,而不是 GDT。如果您没有要求您的操作系统(Linux?)创建一个,那么您的进程可能根本没有 LDT,例如使用modify_ldt() 系统调用。

如果您清除了那个位 (mov eax, 0xfffb),它仍然在我的 Linux 桌面上出现故障。由此我们可以推断出 Linux 并没有配置那么大的 GDT。没有理由期望它会。它只需要少数段描述符即可正常操作。例如如果你使用info reg,你可以看到段寄存器的值是:

cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0

(0 用作“空选择器”,具有保持 x86-64 的最小分段残余快乐的特殊含义;它实际上不是描述符特权级别 0(仅内核数据段),即使低 2位是00cs 的低位是预期的11(环 3 = 用户空间)。)

其他可能的异常原因包括:“如果正在加载 DS、ES、FS 或 GS​​ 寄存器并且指向的段不是数据或可读代码段。


我假设您实际上并不了解分段,我也不想解释如何实际使用分段寄存器。我要说明的一点是,您不能只将ds 用作任意整数数据的 16 位暂存空间。

如果您想更详细地了解您可以在ds 中输入的确切内容,请阅读英特尔的手册。以及内核源代码,看看它是如何配置其 GDT 和 LDT 的,或者进行 modify_ldt() 系统调用。

【讨论】:

  • @MichaelPetch:谢谢,已修复。我懒得检查它,因为它不会影响答案的整体意义(ds 不是暂存空间),但很高兴能更正它。
猜你喜欢
  • 2022-12-18
  • 1970-01-01
  • 2015-01-25
  • 2012-10-10
  • 2017-05-05
  • 2016-05-29
  • 2011-03-14
  • 2017-04-06
  • 2013-09-10
相关资源
最近更新 更多