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とも作成できたのだけれど、マクロでラベル(シンボル)を生成するときは、コード上、作成→参照の順となっていあいとエラーになるのが判明。普通のジャンプラベルだと前方参照できるけれど、マクロで扱うときは別の模様。