CALLの種類

さて、モニタ的な物を作っているところで、CALL機能を実装しようと思っている。
今のところ、リアルモードなので、セグメントとオフセットを入力し、
セグメントの値が、現在のセグメントと一致すれば、オフセットのみ、
一致しなければ、セグメント:オフセットによるCALLを実行する。
そんな事を考えている。


で、どんな実装にすれば良いのかな?という話なんだが、
正直、CALLなんて、

CALL     ラベル名

しか使った事がない気がするよ?<おぃおぃ
なんせ、初心者なんで... (^^;;;


いつも通りインテルの資料でCALLを調べてみる。
上記のパターンは、いわゆる、相対nearコールという奴である。
ラベル名は、アセンブラによって解析され、アドレスに置き換わり、
更に、呼び出し元からの相対アドレスとして再計算される。
「セグメント内コールとも呼ばれる」と説明がある通り、セグメント内でしか使えない。
セグメントごと、どこぞに再配置しても、そのまま動くという事になるわけですね。
この辺は、short jmp や near jmp と一緒だと考えれば良さそうです。
ただ、相対アドレスを計算するのって、微妙〜、って思ったり。
例えば、上記のパターンのラベル名を、即値にしたとしましょう。
ラベル=0x0123だと仮定します。

CALL     0x0123

で、とりあえず、ラベル名の時と同じように動きそうに思うのですが...
この前に、ORG 0x7C00 だとかしてあったら、もう動きません。
ラベル名は、アドレスを計算する時に、ORG を考慮しているようですが、
即値に対しては、そんな物は考慮してくれないようです。
即値は即値です、って事なんでしょうか?
まぁ、そんな問題より、そもそもラベルを使う理由を考えれば、
このケースで、即値を指定する事が、いかにナンセンスな事であるか分かるという物です。
ソースを少しいじれば、該当するアドレスが、簡単に変化してしまう事は、
実際に自分でやってみれば、すぐに確認出来ると思います。
即値表記は、出来る、けれど、実用的ではないような気がします。


それでは、別のCALLを調べてみましょう。

CALL     レジスタ
もしくは
CALL     [アドレス]

このパターンは、絶対間接nearコールと呼ばれる物です。
なんだよ?絶対間接って?と、正直、私は、最初にそう思いましたよ。
まず、絶対の方は、レジスタもしくはアドレスが指し示すメモリに格納されている値が、
すなわち、呼び出し先の絶対アドレスになるという意味です。
間接の方は、その値を、レジスタもしくはアドレスを介して、間接的に与えるって事ですかね?
こちらも、nearコールですので、セグメント内コールとなりますね。
とりあえず、同一セグメントで完結している間は、
呼び出し先のアドレスが固定されている場面で、こちらのCALLが使えそうです。
いや、まぁ、アドレスが固定されていれば、相対指定でも良さそうなんだが...
アドレスを入力する事を考えると、入力値をそのままレジスタに設定するだけで良さそうなので、
こっちの方が、やっぱり楽かな?、とか思う。


farコールについては、まだ関係ないので、とりあえず、ここまで。