JMPマシン命令の16進コード変換について疑問があります。ジャンプしたい絶対アドレス、たとえば「JMP0x400835」があります。まず第一に、これは許可されていますか?はいの場合、対応する16進コードは何でしょうか?そうでない場合は、最初にアドレスをレジスター、たとえばEAXに格納してから、「JMP EAX」を配置できますか?私はx86(64b)アーキテクチャに取り組んでいます。
Gdbのダイアセム出力から16進コードを出力しようとしましたが、一貫性がありません。つまり、16進コードに宛先アドレスが表示されません。
私は16進コードと機械命令に不慣れなので、私の無知を許してください。
64ビットモードでは、JMP absaddr
の形式で絶対アドレスにジャンプすることはありません。ジャンプのオペランドは常にrip
に対する32ビットの相対変位であり、符号が64ビットに拡張されます。
一貫性が見られない理由は、オフセットが現在の命令ポインタに依存していて、それを認識していなかった可能性があります。
もちろん、64ビットアーキテクチャではアドレスは常に64ビット幅であるため、jmp eax
も許可されていません。シーケンス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
これらの16進コードをどのようにして知りましたか?さて、私は自分のコンパイラに尋ねました。 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]
yo ur ad dr re ss he re some random Assembly
ripは、jmp命令自体の後の命令ポインタを参照するため、アドレスへのポインタです。