首页 > 解决方案 > 为什么在 64 位模式下使用“DS:”段覆盖是非法的?

问题描述

我有几行非常简单的汇编代码,它围绕一些数据移动,如下所示:

mov rax,qword ptr gs:[60]                         
mov rcx,qword ptr ds:[rax+20]                                         
mov rax,qword ptr gs:[60]                         
mov rcx,qword ptr ds:[rax+20]                     
mov rbx,qword ptr ds:[rcx+28] 

但是,编译器返回

错误 A2202:非法使用段寄存器

我觉得这可能是我的编译器或版本的问题,任何指针都会有帮助

标签: assemblyx86-64masm

解决方案


cs/// 64ds位模式机器码中允许esss覆盖前缀。但是一些组装商选择不允许它们。

但请注意,它们实际上对带有内存操作数的指令没有影响。这可能就是为什么 masm 显然选择不允许它,以使您免于在此类前缀上浪费空间的“错误”。其他汇编程序,如 NASM,确实允许这样做。

所有这些段都具有相同的固定基地址 = 0,甚至不更改会引发哪个异常。

英特尔手册 vol.1 3.3.7.1 规范寻址:

如果指令使用基址寄存器 RSP/RBP 并使用段覆盖前缀来指定非 SS 段,则规范错误会生成 #GP(而不是 #SS)。在 64 位模式下,只有 FS 和 GS 段覆盖适用于这种情况。其他段覆盖前缀(CS、DS、ES 和 SS)被忽略。请注意,这也意味着应用于“非堆栈”寄存器引用的 SS 段覆盖将被忽略。这样的序列仍然会为规范错误生成#GP(而不是#SS)。

例如,如果mov eax, ds:[rbp]来自非规范地址的故障(高 16 位不是低 48 的符号扩展),它仍然是#SS 故障(因为基址寄存器是 RBP 或 RSP),而不是#GP。DS 前缀确实被忽略了。

您可以区分的唯一另一种方法是是否可以给 DS 一个段选择器,如果任何加载或存储尝试使用它,它将出错,然后运行mov eax, [ds:rbp]​​. 但我不确定这是否可能。mov ds, eax尝试在 Linux 中设置非零值时,我立即遇到了段错误。NULL 段选择器对 DS 和 ES “有效”。鉴于 NASM 和 FASM 的汇编器警告/行为,这些汇编器的开发人员至少认为段前缀确实没有意义。


fs并且gs是唯一在 64 位模式下执行任何操作的段覆盖。

它们可以具有非零基地址。

CS/DS/ES/SS 仅用于填充以使指令更长(出于对齐原因)在现代 x86 上可以使用哪些方法来有效地扩展指令长度?

请注意,这ds已经是除rbp/之外的所有基址寄存器的默认段,因此即使没有被忽略rsp,显式ds前缀也不会改变指令的含义如果您的汇编程序拒绝接受mov rcx,qword ptr ds:[rax+20],那么mov ecx, dword ptr ds:[eax+20]在 32 位模式下也拒绝接受是合理的。


对于某些汇编程序(例如 NASM),在 asm 源代码行中显式提及段会在指令上发出段前缀,即使它已经是默认值。 如果这就是 MASM 的工作方式,那么将其用于“文档”目的并不是一个好主意。

如果您确实想为填充发出 DS 前缀,只需显式编码它们:

mov   rax, gs:[60]
db    3Eh   ; ds prefix
mov   rcx, [rax+20]

其他组装商(GAS、NASM)

有趣的是,在 GAS .intel_syntax noprefix(类似于 MASM)中,ds:[rax+20]组装时没有明确的前缀(因为它已经是默认设置),但ss:[rax+20]确实发出了前缀。所以 GAS 不假设 cs/ds/es/ss 即使在 64 位代码中也是等价的。

NASM 警告:segments.asm:5: warning: ds segment base generated, but will be ignored in 64-bit mode

mov rax, [gs: 60]             ; NASM requires the seg: to be
mov rcx, [ds: rax+20]         ;  inside the [] if present
mov rcx, [rax+20]

用 NASM 组装到这个(objdump -drwC -Mintel输出):

  4000b0:       65 48 8b 04 25 3c 00 00 00      mov    rax,QWORD PTR gs:0x3c
  4000b9:       3e 48 8b 48 14          mov    rcx,QWORD PTR ds:[rax+0x14]
  4000be:       48 8b 48 14             mov    rcx,QWORD PTR [rax+0x14]

推荐阅读