JMP命令のセグメントとオフセット - HobbyOSs/opennask GitHub Wiki
- はりぼてOS3日目harib00i、のJMP命令には一部「:」つなぎでアドレスを指定する謎記法が出てくる
- これ
JMP DWORD 2*8:0x0000001b
- これ
- これに関する説明はOS自作入門の書籍において下記部分で現れる
- 8-5: 32ビットモードへの道 p.171
- 15: マルチタスク-1 p.294
- p.171でははりぼてOSのメモリマップについて記載される、これはJMPで
2*8:0x0000001b
を指定する理由に関わる - p.294ではJMP命令におけるFARジャンプ(↑に現れる記法を使うとFARジャンプになる)について述べられている
このページではまずJMP命令におけるFARジャンプの仕組みと出力される機械語の仕様について備忘録を残す。
- はりぼてOSのメモリマップについては別ページ参照
- まず、このJMPのアドレスに「:」を使う謎記法は下記のようなオペランドが使用可能
0xEA cd | JMP ptr16:16 | オペランドで指定されるアドレスに絶対ファージャンプする
0xEA cp | JMP ptr16:32 | オペランドで指定されるアドレスに絶対ファージャンプする
0xFF /5 | JMP m16:16 | m16:16で指定されるアドレスに絶対間接ファージャンプする
0xFF /5 | JMP m16:32 | m16:32で指定されるアドレスに絶対間接ファージャンプする
- JMPの命令の説明を読み進めると、以下のような記載がある
実アドレスモードまたは仮想 8086 モードでfarジャンプを実行すると、 プロセッサはターゲット・オペランドで指定されたコード・セグメントとオフセットにジャンプする。 この場合は、ターゲット・オペランドは、 絶対farアドレスをポインタ( ptr16:16 または ptr16:32)で直接に、 またはメモリ・ロケーション(m16:16 または m16:32)で間接的に指定する。
- 今回気になる部分はこちら
ポインタ方式では、4 バイト(16 ビット・オペランド・サイズ) または 6 バイト(32 ビット・オペランド・サイズ)の far アドレス即値を使用して、 コール先プロシージャのセグメントおよびアドレスが命令内にコード化される。
- 今回気になる部分はこちらではない
間接方式では、ターゲット・オペランドが 4 バイト(16 ビット・オペランド・サイズ) または 6 バイト(32 ビット・オペランド・サイズ)の far アドレスを内容とする メモリ・ロケーションを指定する。
far アドレスは、CS および EIP レジスタに直接ロードされる。 オペランド・サイズ属性が 16 である場合は、EIP レジスタの上位 2 バイトはクリアされる。
- 「far アドレスは、CS および EIP レジスタに直接ロードされる」という部分はOS自作入門p.294でも述べられている
- わかりやすく書くと、
JMP <CS>:<EIP>
という感じで読み込まれる- EIPはCPUが次に実行するアドレスとなるので、
JMP DWORD 2*8:0x0000001b
は次に0x0000001b
のアドレスにCPUの処理を飛ばしてなにかさせたいわけである
- EIPはCPUが次に実行するアドレスとなるので、
- 実際に表題のアセンブラをアセンブルしてみると下記のようになる
- 「:」を挟んで左がセグメントアドレス(=セグメントベース)、右がオフセットアドレスと呼ぶことにしよう
JMP DWORD 2*8:0x0000001b ; 66ea 1b000000 1000 ; JMP ptr16:32
^^^^^^^^ ^^^^
offset ptr16
- 仕様書にはない
1000
が現れているが、これはセグメントアドレスであるようだ-
1000
は10進数で16であるところがリトルエンディアンの16進数で格納されてる -
1b000000
は10進数で27であるところがリトルエンディアンの16進数で格納されてる
-
物理アドレスは、最終的にセグメントベースとオフセットアドレスを加算した数値になります
足し算すればいいはず
- ptr16 = 16 (=2*8)
- offset = 27 (=0x0000001b)
↓
43
- この項はChatGPTに聞きながら書き進めたのだが、通常のシステムプログラミングではセグメントアドレスはセグメントレジスタに入れてやれば直接指定する必要はない
- 単にセグメントアドレスを16にして、
0x0000001b
にジャンプしたいだけならば下記でもよかったのではないか
MOV AX, 16
MOV DS, AX
JMP 0x0000001b