Vla*_*iev 2 x86 assembly x86-64 disassembly addressing-mode
我在反汇编程序(浮点逻辑c ++)中找到了以下汇编代码。
842: movss 0x21a(%rip),%xmm0
Run Code Online (Sandbox Code Playgroud)
我知道,当进程rip将一直为842且此0x21a(%rip)将为const。使用该寄存器似乎有些奇怪。
我想知道使用rip相对地址代替其他寻址有什么好处。
RIP
是指令指针寄存器,这意味着它包含紧随当前指令之后的指令地址。
例如,考虑以下代码:
mov rax, [rip]
nop
Run Code Online (Sandbox Code Playgroud)
在的代码有第一行中,RIP
指向下一个指令,使其指向在NOP
。因此,此代码将NOP
指令的地址加载到RAX
寄存器中。
因此,它是没有的情况下,RIP
仅仅是一个常数。您RIP
在此过程中“将永远是842”的理解是不正确的。的值RIP
将改变,具体取决于将代码加载到内存中的位置。842只是从调试符号中提取的行号;一旦代码被编译成二进制,就不再有行号了。:-)
在您的反汇编中,常数为偏移量(0x21A
)。那是与中的当前值的偏移量RIP
。另一种写法是:%rip + 0x21A
。
RIP
相对寻址是64位长模式引入的一种有效寻址的新形式。关键是它使编写位置无关的代码变得更加容易,因为您可以使任何与内存相关的引用RIP
都是相对的。实际上,RIP
-relative寻址是64位应用程序中的默认寻址模式。几乎所有以64位模式寻址存储器的指令都是RIP
相对的。我引用肯·约翰逊(又名Skywing)的博客,因为我自己无法说得更好:
与x86相比,x64的较大更改(但经常被忽略)之一是,以前仅通过绝对寻址引用数据的大多数指令现在可以通过RIP相对寻址引用数据。
RIP相对寻址是一种模式,其中提供的地址参考是距当前指令指针的32位(有符号)位移。虽然通常只在x86上将其用于控制传输指令(调用,jmp和forsoth),但x64扩展了指令指针相对寻址的使用,以覆盖更多的指令集。
使用RIP相对寻址的优势是什么?好吧,主要好处是生成位置无关的代码或不依赖于其在内存中加载位置的代码变得容易得多。在当今(相对)自包含的模块(例如DLL或EXE)中,该模块既包含数据(全局变量),也包含与之相关的代码,这尤其有用。如果在x86上使用了平面寻址,则假设模块在其首选基地址处加载,则通常需要对全局变量进行引用来对所涉及全局的绝对地址进行硬编码。如果随后无法在运行时将模块加载到首选基址,则加载器必须执行一组基址重定位 实质上重写了具有绝对地址操作数组件以供参考的所有指令,以考虑到模块的新地址。
[。。。]
但是,如果使用包含RIP相对寻址的指令进行了重定位,则在加载时通常不需要任何基址重定位(也称为“固定”)。这是因为,只要模块的各部分没有在内存中进行内部重新排列(PE格式不支持该内容),任何地址引用都相对于当前指令指针,并且引用该地址范围内的某个位置无论在加载时将图像放置在哪里,当前图像都将继续引用正确的位置。
结果,由于大多数操作可以以相对RIP的方式执行,因此许多x64图像的固定数量大大减少。
他是在Windows环境下发言,但是在概念上类似的内容也适用于其他操作系统。
您拥有的代码将一个常量值(存储在二进制映像中的某个位置)加载到XMM0
寄存器中,并且由于其许多优点,因此使用RIP相对寻址来实现。
归档时间: |
|
查看次数: |
1378 次 |
最近记录: |