web-dev-qa-db-ja.com

JMP命令-16進コード

JMPマシン命令の16進コード変換について疑問があります。ジャンプしたい絶対アドレス、たとえば「JMP0x400835」があります。まず第一に、これは許可されていますか?はいの場合、対応する16進コードは何でしょうか?そうでない場合は、最初にアドレスをレジスター、たとえばEAXに格納してから、「JMP EAX」を配置できますか?私はx86(64b)アーキテクチャに取り組んでいます。

Gdbのダイアセム出力から16進コードを出力しようとしましたが、一貫性がありません。つまり、16進コードに宛先アドレスが表示されません。

私は16進コードと機械命令に不慣れなので、私の無知を許してください。

13

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
30
Gunther Piez

何らかの理由でレジスタを使用したくない場合は、64ビットの絶対即時ジャンプを次のようにエンコードすることもできます。

ff 25 00 00 00 00           jmp qword ptr [rip]
yo ur ad dr re ss he re     some random Assembly

ripは、jmp命令自体の後の命令ポインタを参照するため、アドレスへのポインタです。