[英]Can rip be used with another register with RIP-relative addressing?
I'm familiar with memory references of this form:我熟悉这种形式的内存引用:
XXX ptr [base + index * size + displacement]
where XXX is some size (byte/word/dword/etc), both base
and index
are registers, size
is a small power of two, and displacement
is a signed value.其中 XXX 是某个大小(字节/字/双字/等),
base
和index
都是寄存器, size
是 2 的小幂, displacement
是有符号值。
amd64 introduced rip-relative addressing. amd64 引入了 rip 相对寻址。 As I understand it, I should be able to use
rip
as a base register.据我了解,我应该能够使用
rip
作为基址寄存器。 However, when I try this with clang-900.0.39.2:但是,当我使用 clang-900.0.39.2 尝试此操作时:
mov r8b, byte ptr [rip + rdi * 1 + Lsomething]
I get:我得到:
error: invalid base+index expression
错误:无效的基数+索引表达式
mov r8b, byte ptr [rip + rdi * 1 + Lsomething]
Is it impossible to use an index register when using rip
as the base register?使用
rip
作为基址寄存器时,是否不能使用索引寄存器? Do I have to use lea
to compute rip + Lsomething
and then offset into that?我是否必须使用
lea
来计算rip + Lsomething
然后抵消它?
No, [RIP + rel32]
is the only addressing mode involving RIP.不,
[RIP + rel32]
是唯一涉及 RIP 的寻址模式。 See also Referencing the contents of a memory location.另请参阅引用内存位置的内容。 (x86 addressing modes) .
(x86 寻址模式) 。
If you want maximum efficiency for indexing a static array, you need to make position-dependent code so you can use the table address as a 32-bit absolute disp32
in a normal addressing mode.如果您希望索引静态数组的效率最高,则需要编写与位置相关的代码,以便在正常寻址模式下将表地址用作 32 位绝对
disp32
。 This is allowed in Linux in position-depended executables, but not shared libraries (which have to be PIC).这在 Linux 中与位置相关的可执行文件中是允许的,但不允许共享库(必须是 PIC)。 See 32-bit absolute addresses no longer allowed in x86-64 Linux?
看到x86-64 Linux 中不再允许使用 32 位绝对地址了吗? for how to use
-fno-pie -no-pie
when gcc is configured by default to make PIEs.当 gcc 默认配置为制作 PIE 时,如何使用
-fno-pie -no-pie
。
Otherwise for position-independent array indexing, lea rsi, [rip + Lsomething]
and use pointer-increments or [rsi + rdi*1 + constant]
addressing modes, or whatever other alternative works.否则对于位置无关的数组索引,
lea rsi, [rip + Lsomething]
并使用指针增量或[rsi + rdi*1 + constant]
寻址模式,或任何其他替代方法。 ( Non-indexed addressing modes sometimes save a uop on Intel CPUs so pointer-increments can be good, especially if you're unrolling so an add
for each pointer can more than pay for itself, vs. using the same index for multiple arrays.) ( 非索引寻址模式有时会在 Intel CPU 上节省一个 uop,因此指针增量可能会很好,特别是如果您正在展开,那么每个指针的
add
可以超过其自身的成本,而不是对多个数组使用相同的索引。 )
It's not "RIP as a base register" in arbitrary addressing modes;它不是任意寻址模式下的“RIP 作为基址寄存器”; there isn't room in the machine-code encoding for that .
机器代码编码中没有空间。 x86-64 has 16 possible base registers, encoded with 3 bits in the ModR/M or SIB byte + 1 bit in the optional REX prefix.
x86-64 有 16 个可能的基址寄存器,使用 ModR/M 或 SIB 字节中的 3 位 + 可选 REX 前缀中的 1 位进行编码。 Making RIP usable as a base with arbitrary addressing modes would have required bumping out some other register, and creating a lot of differences in effective-address decoding between 32 and 64-bit mode.
使 RIP 可用作具有任意寻址模式的基础将需要删除一些其他寄存器,并在 32 位和 64 位模式之间在有效地址解码方面产生许多差异。
x86-32 has 2 redundant ways to encode [0x123456]
, ie no-base + disp32: with or without a SIB byte, because SIB has an encoding for no-base and no-index. x86-32 有 2 种冗余方式来编码
[0x123456]
,即 no-base + disp32: 有或没有 SIB 字节,因为 SIB 有无基址和无索引的编码。 See http://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing for a nice table, or see Intel's manuals.请参阅http://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing以获得漂亮的表格,或参阅英特尔的手册。
The no-index SIB encoding makes it possible to encode [esp]
instead of [esp+esp]
, because the ModR/M encoding that would mean base=RSP is the escape code that means "there's a SIB".无索引 SIB 编码使得编码
[esp]
而不是[esp+esp]
成为可能,因为表示 base=RSP 的 ModR/M 编码是表示“有一个 SIB”的转义码。 They could have designed it so you could use esp
as an index for bases other than esp
, but nobody wants to use esp
as an index in the first place.他们可以设计的,所以你可以使用
esp
作为比其他基地的指数esp
,但没有人愿意使用esp
作为摆在首位的索引。 Fun fact: the no-base (with disp32
) encoding uses what would have been the [ebp]
with no displacement, which is why [ebp]
is actually encoded as [ebp + disp8=0]
.有趣的事实:无碱基(带有
disp32
)编码使用没有位移的[ebp]
,这就是为什么[ebp]
实际上被编码为[ebp + disp8=0]
。 In x86-64 mode, this applies to R13 as well.在 x86-64 模式下,这也适用于 R13。
x86-64 re-purposes the shorter (no SIB) encoding for [disp32]
into [RIP + disp32]
, aka [RIP + rel32]
. x86-64 将
[disp32]
的较短(无 SIB)编码重新用于[RIP + disp32]
,也称为[RIP + rel32]
。
32-bit absolute addresses ( [disp32]
) are still encodeable with the longer SIB encoding . 32 位绝对地址 (
[disp32]
) 仍然可以使用更长的 SIB 编码进行编码。 (This is what NASM does by default, if you don't use default rel
.) There's not even a [RIP + disp8]
(eg for loading nearby code addresses). (这是 NASM 默认情况下所做的,如果您不使用
default rel
。)甚至没有[RIP + disp8]
(例如用于加载附近的代码地址)。 There is exactly one bit-pattern in the Mod and M fields of the ModR/M byte that encodes a RIP-relative address. ModR/M 字节的 Mod 和 M 字段中恰好有一个位模式,用于编码 RIP 相对地址。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.