对JMP机器指令的十六进制代码转换有疑问。我有要跳转的绝对地址,说“JMP 0x400835”。 首先,这是允许的吗?如果是,相应的十六进制代码是什么? 如果没有,我可以先将地址存储在某个寄存器中,比如EAX,然后输入“JMP EAX”吗? 我正在研究x86(64b)架构。
我试图从gdb中的diassem输出打印出十六进制代码,但是没有一致性,即我没有在十六进制代码中看到目标地址。
我是十六进制代码和机器指令的新手,所以请原谅我的无知。
答案 0 :(得分:28)
在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
进行了反汇编。我没有费心使用英特尔语法,因为我不需要它。所以这是AT& T语法。
echo 'asm("mov $400835, %rax\n jmp *%rax\n");' > test.c
gcc -c test.c
objdump -d test.o
答案 1 :(得分:2)
如果出于某种原因不想使用寄存器,也可以将64位绝对立即跳转编码为
ff 25 00 00 00 00 jmp qword ptr [rip]
yo ur ad dr re ss he re some random assembly
rip指的是jmp指令之后的指令指针,因此它是指向您地址的指针。