TL:DR: IDA 混淆使用cs:
指示 64 位代码中的 RIP 相对寻址模式。
In IDA mov eax, x
means mov eax, DWORD [x]
这又意味着从变量中读取 DWORDx
.
为了完整性,mov rax, OFFSET x
means mov rax, x
(即将地址x
in rax
).
在 64 位位移中仍然是 32 位,因此,对于位置无关的可执行文件,并不总是可以通过对其地址进行编码来寻址变量(因为它是 64 位,并且不适合 32 位字段)。在位置无关的代码中,这是不可取的。
反而,RIP 相对寻址用来。
在 NASM 中,RIP 相对寻址采用以下形式mov eax, [REL x]
,在气体中它是mov x(%rip), %eax
.
另外,在 NASM 中,如果DEFAULT REL
处于活动状态,指令可以缩短为mov eax, [x]
这与 32 位语法相同。
每个反汇编器都会以不同的方式反汇编 RIP 相关操作数。正如您所评论的,Ghidra 给出了mov eax, DWORD PTR [x]
.
国际开发协会用途mov eax, cs:x
意思是mov eax, [REL x]
/mov x(%rip), %eax
.
;IDA listing, 64-bit code
mov eax, x ;This is mov eax, [x] in NASM and most likely wrong unless your exec is not PIE and always loaded <= 4GiB
mov eax, cs:x ;This is mov eax, [REL x] in NASM and idiomatic to 64-bit programs
简而言之,您基本上可以忽略cs:
因为这正是 64 位模式下变量寻址的方式。
当然,如上面的列表所示,使用或不使用 RIP 相对寻址告诉您该程序可以加载到任何位置或刚好低于 4GiB。
The cs
IDA 显示的前缀让我很失望。
我可以看到它在精神上类似于“代码”,因此rip
注册,但我不认为 RIP 相对寻址意味着cs
段覆盖。
在 32 位模式下,代码段通常是只读的,因此像这样的指令mov [cs:x], eax
会出错。
在这种情况下,放置一个cs:
在操作数前面是错误的。
在 64 位模式下,段覆盖(除了fs
/gs
)被忽略(并且代码段的读取位无论如何都被忽略),因此存在cs:
并不重要,因为ds
and cs
实际上是无法区分的。 (甚至一个ss
or ds
override 不会更改非规范地址的 #GP 或 #SS 例外。)
可能 AGU 甚至不再读取段基址以外的段影子寄存器fs
or gs
。 (尽管即使在 32 位模式下,对于段基数 = 0 的正常情况,也有较低延迟的快速路径,因此硬件可能会让它完成其工作。)
Still cs:
我认为有误导性 - a 2E
前缀字节在机器代码中仍然可以作为填充。大多数工具仍然称其为 CS 前缀,尽管http://ref.x86asm.net/coder64.html在 64 位模式下将其称为“空前缀”。这里没有这样的字节,并且cs:
不是暗示 RIP 相对寻址的明显或明确的方式。