Opecode JMP - HobbyOSs/opennask GitHub Wiki

オリジナルのnaskでもだいたいnasmと同じような動きをしているようだ。なので基本的な部分はx86命令セットに従うという感じで

0xEB cb	JMP rel8	次の命令との相対オフセットだけ相対ショートジャンプする
0xE9 cw	JMP rel16	次の命令との相対オフセットだけ相対ニアジャンプする
0xE9 cd	JMP rel32	次の命令との相対オフセットだけ相対ニアジャンプする
  • 実装メモ(ジャンプの形式について)

    • ショートジャンプ: プログラム内で相対的なアドレスを使用して、現在の命令から指定されたバイト数だけジャンプ
    • ニアジャンプ: プログラム内で絶対的なアドレスを使用して、指定されたアドレスにジャンプ
    • ファージャンプ: 別のセグメントにある命令にジャンプする場合に使用
  • 実装メモ(forward referenceについて)

    • JMPに限らずアセンブラのラベルジャンプの処理を作成するには、その絶対アドレスの計算の前にすべての命令を構文解析しないといけない
    • この問題は"forward reference"として知られ、一般的には「Pass1アセンブラ」という設計で克服可能

osask/naskのメモ

  • naskのJMP命令の判断基準
case OPE_JMP:
	/* JMP: (r/m) near:FF /4, far:FF /5, (imm) near:E9, far:EA, short:EB */
	/* CALL: (r/m) near:FF /2, far:FF /3, (imm) near:E8, far:9A */

https://github.com/hangingman/osask/blob/29d1f0d8cdcd62a0700b4c362705bac025da9a0c/28GO/28GO_K/nask/Nasuka_sub.c#L1794-L1796

  • 3日目harib00gにて、以下のようなアセンブラがある

命令と機械語を載せる

JMP 0xc200  ; 0xe9,0x55,0x45

要は、naskでは上記命令を絶対ファージャンプではなくnear:E9であるとみなしている。

たぶんnasmとかだと同じ命令を書くには以下のように書くのではないか。

JMP 0:0xc200  ; 0xe9,0x55,0x45
  • 他にもコードリーディングをしてみたところ、naskはニアジャンプは8ビット範囲内、ファージャンプは16ビットまたは32ビットの範囲内でしかジャンプすることができないという感じで判定しているようだ
  • 整理すると以下のような疑似言語に落とし込める
JMP命令で
if ( オペランド=(r/m) ) {
    near:FF /4
    far:FF /5
}
if ( オペランド=(imm) ) {
    if (-128 <= i && i <= 127) { // 8ビット範囲内
        short:EB
    } else if (-0x8000 <= i && i <= 0x7fff) { // 16ビット範囲内
        near:E9
    } else {
        near:E9 // 32ビット
    }

    // ファージャンプはどうやって判定しているのかな?(まだ使ってないので後で調べる)
    far:EA
}

https://github.com/hangingman/osask/blob/29d1f0d8cdcd62a0700b4c362705bac025da9a0c/28GO/28GO_K/nask/Nasuka_sub.c#L4547-L4557