首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >x64:怎么做一个相对的jmp *%rax?

问x64:怎么做一个相对的jmp *%rax?
EN

Stack Overflow用户
提问于 2015-11-02 09:49:20
回答 2查看 5.3K关注 0票数 -1

我想编码一个64位的相对跳转到x64汇编中存储在%rax中的地址。AFAIK,没有操作码,所以我手动计算相对地址对应的绝对地址,然后进行绝对跳转到绝对地址:

代码语言:javascript
复制
# destination address, relative to end of jmp instruction, is stored in %rax
00007ffff7ff6020: 0x0000488d1505000000   lea 0x5(%rip),%rdx # load %rip+5 (rip + size of add and jmpq) into %rdx
00007ffff7ff6027: 0x0000000000004801d0   add %rdx,%rax # calculate absolute address based on %rdx (behind jmpq) and %rax (the relative address)
00007ffff7ff602a: 0x00000000000000ffe0   jmpq *%rax # do an absolute jump to absolute address

但对我来说,这看起来是不必要的复杂。有没有更好的方法,用更少的指令?还是应该避免64位相对跳转的另一个原因?

EN

回答 2

Stack Overflow用户

发布于 2015-11-02 11:51:45

所有相对跳转指令在指令中将跳转距离编码为立即数(=整数常量)操作数。在正常执行过程中,存在相对跳转(和调用)以将执行从代码中的一个已知位置转移到另一个位置,例如执行条件跳转(想想许多高级编程语言中的if操作符)、无条件跳转(想想BASIC或C/C++中的goto或隐藏在if或for语句中的无条件跳转),或者调用子例程。要达到这个目的(这实际上很重要),这就足够了。

如果您需要访问与RIP相关的数据,您可以这样做,因为在64位模式下,有一种方法可以将内存操作数编码为RIP-relative (32位模式下没有这种编码)。这有助于生成与位置无关的代码,并有助于减少将所有代码和静态数据放入2 2GB内存的程序中完整64位地址的开销。

其他与xIP相关的用法则不太常见。计算的跳转也是如此(子例程返回除外)。计算跳转是实现诸如switch语句之类的东西的一种常见方法,该语句可以在C/C++、Java中找到。有几种方法可以实现switch,但最明显的一种方法是有一个跳转到何处的地址数组/表,然后只需使用一个整数索引来检索对应于它的地址。然后,您可以使用间接跳转,例如jmp rax (或AT&T语法中的其他名称)。您可以从数组/表中获取地址并一次性跳转:jmp [table + rax*8] (根据您的AT&T语法进行调整)。

票数 1
EN

Stack Overflow用户

发布于 2019-04-18 08:50:52

应该避免64位相对跳转,因为jmp rel32直接跳转的+-2GiB代码大小范围通常很大。

如果你的目标在更远的地方,你通常只知道绝对地址,一开始就不应该计算64位的相对位移。

只有当位移是链接时间常数时,相对位移才有意义,在这种情况下,您(链接器)通常将源和目标放置在彼此2GiB的范围内,以便可以使用jmp rel32。

如果你不能做到这一点,那么通常你会使用movabs $imm64, %rax / jmp *%rax (对于一个“巨大的”代码模型,假设其他地址都在32位之外)。不过,这仍然很糟糕。(而且它不是位置独立的,所以如果您想随机化它的加载地址,那么您需要一个64位绝对目标地址的加载时间修正。但Linux上的ELF等可执行文件格式确实支持这一点,因此您可以在跳转表中使用64位绝对地址,即使在PIE可执行文件或PIC共享库代码中也是如此。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33469531

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档