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	; <エラー!!

とすると、エラーになりまする。
知っている人からすれば、何を今更と思われるかも知れませんが、
知らなかった自分にとっては、大発見です。(笑)