far call
インテル資料は、x86を勉強する上で、とても重要な資料なのだが、
これだけでは、読みこなすのが難しい内容である。
上巻は、流し読みの後、拾い読みで、必要なところを繰り返し読み。
中巻は、最も使用頻度が高い、リファレンス。
下巻は、全く別のCPUの説明かと思うくらい、超難解。
で、中巻のリファレンスで、CALL を調べると、
オペコード命令説明 E8 cw CALL rel16 相対near コール、次の命令とディスプレースメント相対。 E8 cd CALL rel32 相対near コール、次の命令とディスプレースメント相対。 FF /2 CALL r/m16 絶対間接near コール、r/m16 でアドレスを指定。 FF /2 CALL r/m32 絶対間接near コール、r/m32 でアドレスを指定。 9A cd CALL ptr16:16 絶対far コール、オペランドでアドレスを指定。 9A cp CALL ptr16:32 絶対far コール、オペランドでアドレスを指定。 FF /3 CALL m16:16 絶対間接far コール、m16:16 でアドレスを指定。 FF /3 CALL m16:32 絶対間接far コール、m16:32 でアドレスを指定。
といった説明がある。
基本的に、リアルモードでは、16ビット処理になるので、
この中で、far call は、
9A cd CALL ptr16:16 絶対far コール、オペランドでアドレスを指定。 FF /3 CALL m16:16 絶対間接far コール、m16:16 でアドレスを指定。
この2つ。
near call は、
E8 cw CALL rel16 相対near コール、次の命令とディスプレースメント相対。 FF /2 CALL r/m16 絶対間接near コール、r/m16 でアドレスを指定。
この2つで、nasm で具体的に記述すると、
CALL label ; ラベルが相対オフセットに置き換わる CALL BX ; レジスタの値を絶対オフセットとする CALL [BP+4] ; 実効アドレスの内容を絶対オフセットとする
みたいな感じになる。
下2つは、r/m16 のレジスタとメモリロケーションのパターン。
なので、far call の方は、
CALL seg:off ; <こっちはOK CALL [seg:off] ; <こっちはNG
となると思ったら、違った。
インテル資料の表記が、紛らわしいと言うか、
それぞれのアセンブラで、それぞれの表記があると言うか、
その辺が、良く分かっていないと、正しく使えない。
nasm で far call を表記する場合は、
CALL FAR [r/m??] ; <これでOK
ちなみに、一つ目の表記に関しては、
CALL FAR seg:off ; <エラー!!
とすると、エラーになりまする。
知っている人からすれば、何を今更と思われるかも知れませんが、
知らなかった自分にとっては、大発見です。(笑)