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

时间:2018-01-06 04:34:56

标签: assembly x86-64

我熟悉这种形式的记忆参考:

XXX ptr [base + index * size + displacement]

其中XXX是某种大小(字节/字/双字/等),baseindex都是寄存器,size是2的小幂,{{1}是签名值。

amd64引入了rip-relative寻址。据我了解,我应该可以使用displacement作为基址寄存器。但是,当我用clang-900.0.39.2尝试这个时:

rip

我明白了:

  

错误:无效的基数+索引表达式

mov r8b, byte ptr [rip + rdi * 1 + Lsomething]

使用mov r8b, byte ptr [rip + rdi * 1 + Lsomething] 作为基址寄存器时,是否无法使用索引寄存器?我是否必须使用rip来计算lea然后偏移到那个?

1 个答案:

答案 0 :(得分:3)

不,[RIP + rel32]是涉及RIP的唯一寻址模式。另请参阅Referencing the contents of a memory location. (x86 addressing modes)

如果要为静态数组建立索引的最高效率,则需要创建与位置相关的代码,以便在正常寻址模式下将表地址用作32位绝对disp32。在Linux中允许这种位置依赖的可执行文件,但不允许共享库(必须是PIC)。默认配置gcc以制作PIE时,请参阅32-bit absolute addresses no longer allowed in x86-64 Linux?了解如何使用-fno-pie -no-pie

它不是" RIP作为基址寄存器"在任意寻址模式下;机器码编码没有空间。 x86-64有16个可能的基址寄存器,在ModR / M或SIB字节中编码3位,在可选REX前缀中编码1位。使RIP可用作任意寻址模式的基础可能需要突破其他寄存器,并在32位和64位模式之间的有效地址解码中产生许多差异。

x86-32有2种冗余方式来编码[0x123456],即无基数+ disp32:有或没有SIB字节,因为SIB具有无基数和无索引的编码。有关漂亮的表格,请参阅http://wiki.osdev.org/X86-64_Instruction_Encoding#32.2F64-bit_addressing,或参阅英特尔手册。

无索引SIB编码可以编码[esp]而不是[esp+esp],因为ModR / M编码意味着base = RSP是转义代码,意味着"那里& #39; sa SIB"。他们可以设计它,以便您可以使用esp作为esp以外的基础的索引,但是没有人希望首先使用esp作为索引。有趣的事实:无基数(使用disp32)编码使用[ebp]没有位移的内容,这就是[ebp]实际编码为[ebp + disp8=0]的原因。在x86-64模式下,这也适用于R13。

x86-64将[disp32]的较短(无SIB)编码重新用于[RIP + disp32] ,又称[RIP + rel32]

32位绝对地址([disp32])仍可使用较长的SIB编码进行编码。 (如果您不使用default rel,这就是NASM默认执行的操作。)甚至没有[RIP + disp8](例如,用于加载附近的代码地址)。 ModR / M字节的Mod和M字段中只有一个位模式,用于编码RIP相对地址。