OS(6) ISRとIDTを nasm のマクロでまとめて作成
個々の割り込み番号毎に割り込みハンドラを定義するのにnasmのマクロを使用しようとしてはまる。
マクロ定義と繰り返し
nasm では %macro 〜 %endmacro でマクロ定義が可能なので、次のようなマクロを記載する。
これは IRS_<番号>: というラベル定義と、eaxに番号を入れて show_number を呼び出すのを256個分定義するもの。
%macro make_ISR 1 ISR_%1: pusha push ds push es mov eax, %1 call show_number pop es pop ds popa iret %endmacro %assign n 0 %rep 256 make_ISR n %assign n n + 1 %endrep
として問題なく定義完了。
同じ様にIDTを作成してみる
ISRが作成できたので、それらのラベルからIDTを作成するマクロを別に定義してやる。
%macro make_IDT 1 dw ISR_%1 & 0xffff dw CSEG db 0x0, 0x8e dw (ISR_%1 >> 16) & 0xffff %endmacro %assign n 0 %rep 256 make_IDT n %assign n n + 1 %endrep
これがそのマクロなのだけれど、アセンブルできません。
色々悩んだ結果、「フラットモデルで、ISR_<番号>のオフセットを直接数値として演算できる」と思い込んでいたのが敗因と判明。ISR_<番号>はあくまでシンボルなので、スカラーとして演算ができないのでした。
そこで $$ を登場させ、
%macro make_IDT 1 %assign ofs (ISR_%1 - $$) dw ofs & 0xffff dw CSEG db 0x0, 0x8e dw (ofs >> 16) & 0xffff %endmacro
として解決。
マクロで扱うラベルの生成と参照
これでIDT、ISRとも作成できたのだけれど、マクロでラベル(シンボル)を生成するときは、コード上、作成→参照の順となっていあいとエラーになるのが判明。普通のジャンプラベルだと前方参照できるけれど、マクロで扱うときは別の模様。