简体   繁体   English

rip 可以与具有 RIP 相对寻址的另一个寄存器一起使用吗?

[英]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 是某个大小(字节/字/双字/等), baseindex都是寄存器, 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM