【问题标题】:JMP instruction - Hex codeJMP 指令 - 十六进制代码
【发布时间】:2012-04-06 14:39:53
【问题描述】:

对JMP机器指令的十六进制码转换有疑问。我有我想跳转到的绝对地址,比如“JMP 0x400835”。 首先,这是允许的吗?如果是,那么对应的十六进制代码是什么? 如果没有,我可以先将地址存储在某个寄存器中,比如 EAX,然后输入“JMP EAX”吗? 我正在研究 x86(64b) 架构。

我尝试从gdb中的diassem输出中打印出十六进制代码,但是没有一致性,即在十六进制代码中看不到目的地址。

我是十六进制代码和机器指令的新手,请原谅我的无知。

【问题讨论】:

标签: assembly hex x86-64 machine-code


【解决方案1】:

如果您出于某种原因不想使用寄存器,也可以将 64 位绝对立即跳转编码为

ff 25 00 00 00 00           jmp qword ptr [rip]      jmp *(%rip)
yo ur ad dr re ss he re     some random assembly

rip 指的是 jmp 指令本身之后的指令指针,因此它是指向您的地址的指针。

【讨论】:

    【解决方案2】:

    在 64 位模式下,没有 JMP absaddr 形式的跳转到绝对地址。跳转的操作数始终是相对于rip 的 32 位相对位移,其符号扩展为 64 位。

    您看到不一致的原因可能是偏移量取决于当前指令指针,而您没有意识到这一点。

    jmp eax 也是不允许的,因为在 64 位架构上地址当然总是 64 位宽。一个序列mov rax, addr + jmp rax 是可能的,它看起来像

    48 c7 c0 35 08 40 00            mov rax, 0x00400835
    ff e0                           jmp rax
    

    48 b8 35 08 40 00 00 00 00 00   mov rax, 0x0000000000400835
    ff e0                           jmp rax
    

    我是怎么知道这些十六进制代码的?好吧,我确实问过我的编译器。我用gcc -c 编译并用objdump 反汇编。我没有费心使用 Intel 语法,因为我不需要它。所以这是 AT&T 语法。

    echo 'asm("mov $400835, %rax\n jmp *%rax\n");' > test.c
    gcc -c test.c
    objdump -d test.o
    

    【讨论】:

    • 感谢您的回答。这真的帮助了我。 objdump 真的是个好工具!
    • 嘿..我已将您的帖子标记为“有用”..我猜这就是需要的,对吧?
    • 您的意思是“jmp absaddr”将是“jmp %rip + absaddr”(其中 absaddr 必须等于或小于 32 位)?
    • @ManofOneWay 也不确定您要问什么,因为没有 jmp absaddrjmp %rip+absaddr 不是绝对的。如果您告诉汇编器以jmp someaddr 的形式翻译一些代码,它将计算从当前地址(稍后将在%rip)到someaddr 的相对距离并发出e9 xx xx xx xx,其中四个 xx 字节对应计算出的地址差。
    • 这里写“jmp *%rax”。你能告诉我在哪里可以找到这种语法的描述吗?因为到处都解释了 AT&T 语法,所以没有列出这个 JMP 语法。
    猜你喜欢
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 2014-10-08
    • 1970-01-01
    • 2019-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多