MOV DS,EAX 段错误?
MOV DS, EAX segfaults?
当我运行mov ds,rax
时,会报错Program terminated with signal SIGSEGV, Segmentation fault
汇编代码有什么问题?
global main
main:
mov rax,0ffffH
mov ds,rax
mov rbx,6
ret
mov
到段寄存器加载内部段 base/limit / 来自 the GDT (Global Descriptor Table) 的权限内容。 (在 64 位模式下,base 和 limit 分别被视为 0 / -1,但是 mov
到段寄存器仍然有实际效果并且仍然检查东西。你不能期望任意值不会导致问题。)
根据 Intel's manual for mov
,如果“段选择器索引”(GDT 或 LDT 中的索引)“在描述符 table 之外,mov Sreg, r/m
会出现 #GP(selector)
错误限制”。
Linux 如果用户-space 导致无效页面错误或任何类型的 #GP
异常,则传送 SIGSEGV。
由于位 2 已设置 (1<<2
),这是对 LDT(本地描述符 Table)而非 GDT 的索引。如果您没有要求 OS (Linux?) 创建一个 LDT,那么您的流程可能根本就没有 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 位是 00
。cs
的低位是预期的 11
(ring 3 = user-space)。)
其他可能的异常原因包括:“如果正在加载 DS、ES、FS 或 GS 寄存器并且指向的段不是数据或可读代码段。
我假设您实际上对分段知之甚少,而且我并不是要解释如何实际使用段寄存器。我想说的是,你不能只使用 ds
作为任意整数数据的 16 位临时 space。
如果您想更详细地了解可以和不能放入 ds
的内容,请阅读英特尔的手册。和内核源码看看它是如何配置它的GDT和LDT的,或者做一个modify_ldt()
系统调用。
当我运行mov ds,rax
时,会报错Program terminated with signal SIGSEGV, Segmentation fault
汇编代码有什么问题?
global main
main:
mov rax,0ffffH
mov ds,rax
mov rbx,6
ret
mov
到段寄存器加载内部段 base/limit / 来自 the GDT (Global Descriptor Table) 的权限内容。 (在 64 位模式下,base 和 limit 分别被视为 0 / -1,但是 mov
到段寄存器仍然有实际效果并且仍然检查东西。你不能期望任意值不会导致问题。)
根据 Intel's manual for mov
,如果“段选择器索引”(GDT 或 LDT 中的索引)“在描述符 table 之外,mov Sreg, r/m
会出现 #GP(selector)
错误限制”。
Linux 如果用户-space 导致无效页面错误或任何类型的 #GP
异常,则传送 SIGSEGV。
由于位 2 已设置 (1<<2
),这是对 LDT(本地描述符 Table)而非 GDT 的索引。如果您没有要求 OS (Linux?) 创建一个 LDT,那么您的流程可能根本就没有 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 位是 00
。cs
的低位是预期的 11
(ring 3 = user-space)。)
其他可能的异常原因包括:“如果正在加载 DS、ES、FS 或 GS 寄存器并且指向的段不是数据或可读代码段。
我假设您实际上对分段知之甚少,而且我并不是要解释如何实际使用段寄存器。我想说的是,你不能只使用 ds
作为任意整数数据的 16 位临时 space。
如果您想更详细地了解可以和不能放入 ds
的内容,请阅读英特尔的手册。和内核源码看看它是如何配置它的GDT和LDT的,或者做一个modify_ldt()
系统调用。