OS(7) ソフトウェア割り込みを発生させてみる

ISRとIDTが作成できたので、ソフトウェア割り込みが実行されることを確認する。

実行結果


ipl.asmの修正

kernel.binが大きくなってきたので、ロードサイズを2から16へ増やす。変更部分は次の箇所。

                mov     ax, 0x0210      ; 16セクタ読み出し

kernel.asmの修正

変更内容は

  • 文字列表示ルーチンの変更
    • 呼ばれるたびに次の行から表示
    • 最下行まで表示したら最上行へ。ただし画面は消さない
  • IDT/ISRの作成
  • IDTで発生した割り込み番号を画面に表示

といったところ。

;
; kernel.asm
;
%include        "defs.inc"

[bits 32]
[org PROG_START]
;------------------------------------------------------------------------
PROETCT_start:  
                mov     ax, DSEG
                mov     ds, ax
                mov     es, ax
                mov     ss, ax
                mov     esp, 0xa0000    ; メモリホール直前からスタック

                xor     ax, ax
                mov     fs, ax
                mov     gs, ax

                mov     esi, msg
                mov     ah, 0x1f
                call    puts

                lidt    [IDTR]          ; IDTを設定
                
                int     0               ; ソフトウェア割り込み実行
                int     0x40
                int     0x80
                int     0xff

                jmp     $

msg:            db       'This is PROTECTED mode kernel', 0
;------------------------------------------------------------------------
; 文字列表示
puts:           push    edi
                push    eax
                mov     eax, 80 * 2
                mul     byte [.@y]
                add     eax, VRAM_OFS
                mov     edi, eax
                pop     eax
                push    eax
.@loop:         lodsb
                stosw
                or      al, al
                jnz     .@loop
                inc     byte [.@y]              ; 表示の都度次の行へ
                cmp     byte [.@y], 80
                jb      .@ret
                mov     byte [.@y], 0
.@ret:          pop     eax
                pop     edi
                ret
.@y             db      0                       ; 次に表示する行
;------------------------------------------------------------------------
IDTR:           dw      initial_IDT_end - initial_IDT - 1
                dd      initial_IDT
;------------------------------------------------------------------------
; 割り込み番号の表示
show_number:    cld
                mov     edx, eax
                mov     ax, DSEG
                mov     ds, ax
                mov     es, ax
                mov     eax, edx
                shr     al, 4
                and     al, 0xf
                add     al, '0'
                cmp     al, '9'
                jbe     .@next
                add     al, 'A' - ('9' + 1)
.@next:         mov     [msg_int_num], al
                mov     eax, edx
                and     al, 0xf
                add     al, '0'
                cmp     al, '9'
                jbe     .@next2
                add     al, 'A' - ('9' + 1)
.@next2:        mov     [msg_int_num + 1], al

                mov     esi, msg_int
                mov     ah, 0x1c
                call    puts
                ret

msg_int:        db      'INT '
msg_int_num:    db      '  ', 0
;------------------------------------------------------------------------
; ISR作成マクロ
%macro          make_ISR        1
ISR_%1:         pusha
                push    ds
                push    es
                mov     eax, %1
                call    show_number
                pop     es
                pop     ds
                popa
                iret
%endmacro

; ISR作成
%assign         n       0
%rep            256
                make_ISR        n
%assign         n       n + 1
%endrep
;------------------------------------------------------------------------
; IDT作成マクロ
%macro          make_IDT        1
%assign         ofs     (ISR_%1 - $$ + PROG_START)
                dw      ofs & 0xffff
                dw      CSEG
                db      0x0, 0x8e
                dw      (ofs >> 16) & 0xffff
%endmacro

; IDT作成
initial_IDT:
%assign         n       0
%rep            256
                make_IDT        n
%assign         n       n + 1
%endrep
initial_IDT_end:

defs.incの修正

CSEG            equ     0x10
DSEG            equ     0x18
VRAM_OFS        equ     0xb8000
PROG_START      equ     0x10200