忍者ブログ

Cyber Bird

   

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

割り込み実験

相変わらず割り込みがうまくいかない。
そこで、実験の足跡を残しておきたいと思う。きっともっと先に見返せばわかるかも?

#include "def.h"
#include "prot.h"

#define ADR_BOOTINFO	0x0ff0

BOOTINFO *binfo = (BOOTINFO *)ADR_BOOTINFO;

struct IDTR {
	short limit;
	int base;
}__attribute((__packed__));

void Main() {
	init_gdtidt();	// GDT/IDTの初期化
	init_pic();		// PICの初期化
	io_sti();		// 割り込み許可

	init_palete();	// パレットの初期化
	init_screen(binfo->scrnx, binfo->scrny);

	draw_mouse();

	io_out8(PIC0_IMR, 0xf8);	// PIC1とキーボードを許可
	io_out8(PIC1_IMR, 0xef);	// マウスを許可
	
	char s[30];

	struct IDTR idtr = {0};
	_sidt(&idtr);
	lsprintf(s, "idtr.limit = %x", idtr.limit);
	vprint(s, 0, 0, COL_FFFFFF);
	lsprintf(s, "idtr.base = %x", idtr.base);
	vprint(s, 0, 16, COL_FFFFFF);

	while(1) {
		io_hlt();
	}
}
今のところ、boot.cがこんな感じ。
IDTR構造体や28~33行目はあまり気にしないでほしい。%idtrの値が正しいか確かめていたんだけど、
LDTR命令で正しく設定されていることはわかったので、単にここで文字が表示されるのを確認する
だけになっている(笑)

注目するのは23行目。PIC0(マスター)に対して、0xf8(11111000)をマスクしている。
つまり、IRQ0~IRQ2に割り込み許可をしている。
ここで、IRQ0はタイマ、IRQ1はキーボード、IRQ2はスレーブPICとのカスケード接続。
自作本ではマスクは0xf9(11111001)になっている。
今回タイマの割り込み許可をしたのは、タイマは定期的に絶対割り込んでくれることがわかっているから。
キーボードはカチカチ押してもQEMUの設定で割り込めてないのかよくわからないけど、
タイマは絶対割り込んでくれるので、割り込みは少なくとも起こる。

で、タイマ用にも割り込みハンドラを用意してあげる。


// IDTの設定
set_gatedesc(idt + 0x21, (int)inthandler21, 2 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x2c, (int)inthandler2c, 2 * 8, AR_INTGATE32);
set_gatedesc(idt + 0x20, (int)inthandler21, 2 * 8, AR_INTGATE32);
面倒なので、タイマ用のハンドラはキーボード用に用意したものを流用。
さて、これでタイマが割り込めば…

Screenshot-QEMU-3.png

こうなるはず!
さあタイマよ、割り込め!



Screenshot-QEMU-1.png

Screenshot-QEMU-2.png

はい失敗(笑)

さて考察。

前者の方は単純にタイマから割り込みが来てないだけ。
割り込みが何も来ずにIDTRの情報が表示された。

後者は?

まず、boot.cでは23行目でタイマの割り込みが有効化されている。
つまり、これ以降、どのタイミングでタイマの割り込みが来るかは予期できない。
前者ではたまたま最後までタイマから割り込みが来なかっただけだ。

とすると、後者では恐らく、割り込みを有効化してからIDTRの情報が表示されるまでの間に
タイマから割り込みがきて、なんらかの原因で割り込み処理から戻ってこれなかったということでは
なかろうか。



じゃあ、アセンブラで書いた、Cの関数を呼び出す割り込みハンドラを見てみよう。


inthandler21:
	pushw %es
	pushw %ds
	pusha
	movl %esp, %eax
	pushl %eax
	movw %ss,%ax
	movw %ax, %ds
	movw %ax, %es
	call hInt21
	popl %eax
	popa
	popw %ds
	popw %es
	iret
まず、この処理は16行目にはたどり着いていないということは確実。
なぜなら、16行目でhInt21をcallすると、一番最初のイメージ画像のように、
割り込みメッセージが表示されるからだ。

ではどこで処理が止まっているのか。
callするまではひたすらpushしたり、レジスタを弄っているだけなので、
処理が止まるような箇所は見当たらない。

ということは、そもそもこの割り込みハンドラが呼ばれていないのでは?

つまり、CPUは割り込みハンドラを呼んだつもりだけど、アドレスを間違えちゃった、みたいな。



ここから先はさらに原因究明していくけど、これで少なくとも割り込みは正常に起こってることが
わかったので、よい収穫だったかな。
PR

COMMENT

NAME
TITLE
MAIL(非公開)
URL
EMOJI
Vodafone絵文字 i-mode絵文字 Ezweb絵文字
COMMENT
PASS(コメント編集に必須です)
SECRET
管理人のみ閲覧できます

無題

  • by NONAME
  • 2012/01/07(Sat)22:44
  • Edit
set_gatedesc(idt + 0x20, (int)inthandler21, 2 * 8, AR_INTGATE32);

「inthandler21」の部分、「inthandler20」だと思います。

Re:無題

  • by levelfour
  • 2012/01/08 11:16
ご指摘ありがとうございます。

そこは、単にタイマ用の割り込みハンドラ「inthandler20」を用意しても、
どうせメッセージを表示するだけなので、キーボード用に用意してある
割り込みハンドラ「inthandler21」を流用しただけです。

まあ、inthandler20を用意してもいいんですが、大した意味はありませんので…。

ブログ内検索

プロフィール

HN:
levelfour
性別:
男性
自己紹介:
ぼちぼち更新を再開する予定です。

twitter

最新コメント

[09/27 菜々氏]
[06/17 NONAME]
[04/30 mithril]
[04/29 Liva]
[01/30 NONAME]

最新トラックバック

コガネモチ

Copyright ©  -- Cyber Bird --  All Rights Reserved
Design by CriCri / Photo by Geralt / powered by NINJA TOOLS / 忍者ブログ / [PR]