对JMP机器指令的十六进制代码转换有疑问。我有我想跳转到的绝对地址,比如“JMP 0x400835”。首先,这是允许的吗?如果是,那么对应的十六进制代码是什么?如果没有,我可以先将地址存储在某个寄存器中,比如 EAX,然后输入“JMP EAX”吗?我正在研究 x86(64b) 架构。
我试图从gdb中的diassem输出中打印出十六进制代码,但是没有一致性,即我在十六进制代码中看不到目标地址。
我是十六进制代码和机器指令的新手,所以请原谅我的无知。
对JMP机器指令的十六进制代码转换有疑问。我有我想跳转到的绝对地址,比如“JMP 0x400835”。首先,这是允许的吗?如果是,那么对应的十六进制代码是什么?如果没有,我可以先将地址存储在某个寄存器中,比如 EAX,然后输入“JMP EAX”吗?我正在研究 x86(64b) 架构。
我试图从gdb中的diassem输出中打印出十六进制代码,但是没有一致性,即我在十六进制代码中看不到目标地址。
我是十六进制代码和机器指令的新手,所以请原谅我的无知。
在 64 位模式下,没有格式跳转JMP absaddr
到绝对地址。跳转的操作数始终是 32 位的相对位移rip
,其符号扩展到 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
如果您出于某种原因不想使用寄存器,也可以将 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 指令本身之后的指令指针,因此它是指向您的地址的指针。