帮助发现bug
CPU的异常处理功能,还能帮助我们发现bug,比如下面的例子:
bug1.c:
void api_putchar(int c);
void api_end(void);
void HariMain(void)
{
char a[100];
a[10] = 'A'; /* 这句没有问题 */
api_putchar(a[10]);
a[102] = 'B'; /* 这句有问题 */
api_putchar(a[102]);
a[123] = 'C'; /* 这句也有问题 */
api_putchar(a[123]);
api_end();
}
由于数组保存在栈中,数组越界会产生栈异常。我们编写一个函数来处理栈异常,栈异常的中断号为0x0c。CPU说明书中,从0x00到0x1都是异常所使用的中断。IRQ的中断号都是从0x20之后开始的,其中0x00号是除零异常,当试图除以0时产生;0x06号是非法指令异常,当试图执行CPU无法理解的机器语言指令时产生。
naskfunc.nas
_asm_inthandler0c:
STI
PUSH ES
PUSH DS
PUSHAD
MOV EAX,ESP
PUSH EAX
MOV AX,SS
MOV DS,AX
MOV ES,AX
CALL _inthandler0c
CMP EAX,0
JNE end_app
POP EAX
POPAD
POP DS
POP ES
ADD ESP,4 ; 在INT 0x0c 中也需要这句
IRETD
发生异常时,应该能显示引发异常的指令地址,我们在console.c程序中加上这个功能。
console.c节选:
int *inthandler0c(int *esp)
{
struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec);
struct TASK *task = task_now();
char s[30];
cons_putstr0(cons, "\nINT 0C :\n Stack Exception.\n");
sprintf(s, "EIP = %08X\n", esp[11]);
cons_putstr0(cons, s);
return &(task->tss.esp0); /* 强制结束程序 */
}
int *inthandler0d(int *esp)
{
struct CONSOLE *cons = (struct CONSOLE *) *((int *) 0x0fec);
struct TASK *task =