为什么x86-64的jmpq只需要32位长度的地址? [英] Why does jmpq of x86-64 only need 32-bit length address?

查看:32
本文介绍了为什么x86-64的jmpq只需要32位长度的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我使用objdump -D反汇编一个二进制文件时,jmpq的典型代码就像e9 7f fe ff ff,它是用于表示负偏移量.但是,x86-64 的地址是 64(48) 位(据我所知),那么这个 32 位地址如何7f fe ff ff 表示 64 位绝对地址的负偏移量?

As I use objdump -D to disassemble a binary, the typical code of jmpq is like e9 7f fe ff ff, which is used for representing a negative offset. However, the address of x86-64 is 64(48)-bit (to my knowledge), so how can this 32-bit address 7f fe ff ff represent the negative offset of 64-bit absolute address?

另外,是否还有其他指令,如jmpjmpq,但有64 位地址位移?我如何在 Intel 或 AMD 的手册中找到说明(我搜索了 jmpq 但什么也没找到)?

Additionally, are there any other instructions like jmp and jmpq, but have 64-bit address displacement? How can I find the instructions in Intel's or AMD's manual (I searched for jmpq but found nothing)?

正如我搜索的那样,它似乎被称为 RIP 相对寻址.而且似乎并非所有指令都这样做.是否有 64 位相对寻址?如果是间接跳转,64位绝对地址应该在寄存器或内存中吧?

As I searched, it seems to be called RIP-relative addressing. And it seems that not all instructions do this. Is there 64-bit relative addressing? If it is an indirect jump, the 64-bit absolute address would be in a register or memory, right?

推荐答案

正如其他人所指出的,x86-64 的jmp relative"指令仅限于 32 位有符号位移,用作相对于程序计数器.

As others have noted, the "jmp relative" instruction for x86-64 is limited to a 32 bit signed displacement, used as a relative offset with respect to the program counter.

OP 问为什么没有 64 位偏移的相对跳转.我不能代表英特尔的设计人员说话,但很明显,这条指令不会很有用,尤其是在 32 位相对 jmp 可用的情况下.唯一需要它的时候是当您的程序大小超过 2 GB 时,因此 32 位相对 jmp 无法从其中的任何一点到达所有程序.最近看到任何 2Gb 目标文件吗?因此,此类指令的明显效用似乎非常小.

OP asked why there is no relative jump with a 64 bit offset. I can't speak for the designers at Intel, but it seems pretty clear that this instruction would simply not be very useful, especially with the availability of the 32-bit relative jmp. The only time it would be needed is when your program was 2+ gigabytes in size, so that the 32 bit relative jmp could not reach all of it from any point within it. Seen any 2Gb object files recently? So the apparent utility for such instructions seems really small.

大多数情况下,当程序变得非常大时,它们会开始分解为更易于管理的元素,这些元素可以以不同的速度发展.(DLL 就是一个例子).这些元素之间的接口是通过更神秘的方式(跳跃向量等)完成的,以确保接口在面对进化时保持不变.一个非常长的 jmp relative 可用于从应用程序到达另一个模块的入口点,但将绝对地址加载到寄存器中并进行寄存器间接调用的实际成本在实践中足够小,以至于不值得优化.现代 CPU 设计就是要优化晶体管的放置位置,以最大限度地提高性能.

Mostly when programs get really large, they start to be broken into more manageable elements that can evolve at different rates. (DLLs are an example of this). Interfacing between such elements is done by more arcane means (jump vectors, etc) to ensure that the interfaces stay constant in the face of evolution. An extremely-long jmp relative could be used to reach from an application to an entry point in another module, but the actual cost of loading an absolute address into a register and doing an register-indirect call, is small enough in practice that it isn't worth optimizing. And modern CPU design is all about optimizing where you put your transistors to maximize performance.

为了完整起见,x86(许多版本)也有非常短的 jmp 相关指令(8 位有符号偏移).实际上,即使是 32 位 jmp 相关指令也很少需要,特别是如果您有一个可以重新排列代码块的良好代码生成器.出于同样的原因,英特尔可以说本可以将这些排除在外.我怀疑它们的效用略高,足以证明晶体管的合理性.

Just to be complete, the x86 (many flavors) have very short jmp relative instructions (8 bit signed offset), too. In practice, even the 32 bit jmp relative instructions are rarely needed, especially if you have a good code generator that can rearrange code blocks. Intel arguably could have left these out for the same reason; I suspect their utility is marginally high enough to justify the transistors.

大文字操作数"的问题在许多架构中以有趣的方式出现.如果您检查代码中字面值的分布,您会发现小值(0,1、ascii 字符代码)覆盖了相当多的百分比;几乎所有其他内容都是内存地址.所以你在程序中不需要大文字值",但你必须以某种方式处理内存地址.Sparc 芯片以将低字面值加载到寄存器中"(意思是小常量")而著称,而不太常用的将字面值高"(填充寄存器中的高位)用作生成大常量的第二条指令,并且较少使用.这使得代码很小,除非你需要一个大的常量;小代码意味着更高的有效指令提取率,这有助于提高性能.

The question of "big literal operands" shows up in funny ways in many architectures. If you examine the distribution of literal values in code, you'll discover that small values (0,1, ascii character codes) cover a pretty good percentage; almost everything else are memory addresses. So you kind of don't need "big literal values" in programs but you do have to handle memory addresses somehow. The Sparc chip famously has "load literal value low into register" (meaning "small constants") and less often used "load literal value high" (to fill upper bits in a register) used as a second instruction to make big constants, and used less often. This keeps the code small, except when you need a big constant; small code means higher effective instruction fetch rates and that contributes to performance.

这篇关于为什么x86-64的jmpq只需要32位长度的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆