为什么要使用DS:'段在64位模式下覆盖非法?

时间:2018-05-17 20:47:33

标签: assembly x86-64

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

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:非法使用段寄存器

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

1 个答案:

答案 0 :(得分:3)

在64位模式下,机器代码中允许

cs / ds / es / ss段覆盖前缀,但它们对具有内存的指令几乎没有影响操作数。 (例如,如果来自非规范地址的mov eax, ds:[rbp]故障(高16位不是低48的符号扩展),它仍然是#SS故障(因为基址寄存器是RBP或RSP),而不是#GP。实际上忽略了DS前缀,而不仅仅是等效的,因为所有这些段都具有相同的固定基址= 0.英特尔手册vol.1 3.3.7.1规范寻址。

  

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

该部分的措辞可能仅意味着在这种情况下,为了例外类型,它们会被忽略。

唯一可以区分的另一种方法是,如果有任何加载或存储尝试使用它会导致DS出现故障的段选择器,然后运行mov eax, ds:[rbp]。但我不确定这是可能的;当我试图在Linux中设置一个非零值时,我正在mov ds, eax上得到一个段错误。 NULL段选择器为DS和ES“工作”。鉴于NASM和FASM的汇编警告/行为,这些汇编程序的开发人员至少认为段前缀确实毫无意义。

fsgs是在64位模式下执行任何操作的唯一段覆盖。它们可以具有非零的基址。

CS / DS / ES / SS仅用于填充以使指令更长(出于对齐原因)What methods can be used to efficiently extend instruction length on modern x86?

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

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

如果您确实要为填充发出DS前缀,只需明确编码:

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

有趣的是,在GAS的.intel_syntax noprefix(类似MASM)中,ds:[rax+20]在没有显式前缀的情况下进行汇编(因为它已经是默认值),但ss:[rax+20]确实会发出前缀。因此,即使在64位代码中,GAS也不认为cs / ds / es / ss是等效的。

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

mov rax, [gs: 60]
mov rcx, [ds: rax+20]
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]