Win*_*ser 11 assembly x86-64 computer-architecture
当我objdump -D用来反汇编二进制时,典型的代码jmpq就像e9 7f fe ff ff是,用于表示负偏移.但是,x86-64的地址是64(48)位(据我所知),那么这个32位地址如何7f fe ff ff表示64位绝对地址的负偏移?
此外,还有像任何其他指令jmp和jmpq,但有64位地址位移?我怎样才能找到英特尔或AMD手册中的说明(我搜索jmpq但没有找到任何内容)?
当我搜索时,它似乎被称为RIP相对寻址.似乎并非所有说明都这样做.是否有64位相对寻址?如果是间接跳转,64位绝对地址将在寄存器或内存中,对吧?
正如其他人所指出的,x86-64的"jmp相对"指令仅限于32位有符号位移,用作相对于程序计数器的相对偏移.
OP问为什么 64位偏移没有相对跳跃.我不能代表英特尔的设计师,但似乎很清楚,这条指令根本不是很有用,尤其是在32位相对jmp的可用性方面.唯一需要的是当你的程序大小超过2千兆字节时,因此32位相对jmp无法从其中的任何一点到达所有这些.最近看过任何2Gb的目标文件?所以这些指令的明显效用似乎很小.
大多数情况下,当程序变得非常大时,它们就会被分解成更易于管理的元素,这些元素可以以不同的速率发展.(DLL就是这样的一个例子).这些元素之间的接口是通过更加神秘的手段(跳跃向量等)来完成的,以确保接口在进化过程中保持不变.可以使用一个非常长的jmp相对来从应用程序到另一个模块的入口点,但是将绝对地址加载到寄存器并进行寄存器间接调用的实际成本在实践中足够小以至于它不是不值得优化.现代CPU设计就是优化放置晶体管以最大限度地提高性能.
为了完成,x86(许多版本)也有非常短的jmp相关指令(8位有符号偏移).实际上,甚至很少需要32位jmp相关指令,特别是如果你有一个可以重新排列代码块的良好代码生成器.出于同样的原因,英特尔可能会将这些问题排除在外; 我怀疑它们的效用是否足以证明晶体管的合理性.
在许多架构中,"大文字操作数"的问题以有趣的方式出现.如果你检查代码中文字值的分布,你会发现小值(0,1,ascii字符代码)涵盖了相当不错的百分比; 几乎其他一切都是内存地址.所以你在程序中不需要"大文字值",但你必须以某种方式处理内存地址.Sparc芯片有一个着名的"将文字值加载到寄存器中"(意思是"小常量"),而不常使用"加载文字值高"(填充寄存器中的高位)作为第二条指令来制作大常量,以及使用频率较低.除非你需要一个大常数,否则这会使代码保持较小; 小代码意味着更高的有效指令获取率并且有助于提高性能.
64位模式下的E9操作码将32位符号位移符号扩展为64位:
E9 cd - > JMP rel32 - >跳转靠近,相对,RIP = RIP + 32位位移符号扩展到64位
FF操作码可用于跳转到64位地址:
FF/4 - > JMP r/m64 - >跳转接近,绝对间接,RIP = 64位偏移寄存器或存储器
引自JMP的英特尔指令集手册条目.