このメッセージを変えてみるプログラム2つを下記に示した。上は、MS-DOSのシステムコールを用いて割り込みベクタの取得、設定を行っている。下は、システムコールを使わずに、割り込みベクタの取得、設定を行っている。
CODE SEGMENT ASSUME DS:CODE,CS:CODE,ES:CODE,SS:CODE .186 ORG 100h START: mov ax,3500h int 21h ;割り込みベクタ取得 mov VECT0_SEG,es mov VECT0_OFF,bx ;割り込みベクタ保管 push cs pop ds ;DS <= CS mov dx,offset VECT0 mov ax,2500h int 21h ;割り込みベクタ設定 xor ax,ax div al ;0で割ってみる mov ah,9 mov dx,offset MSG int 21h ;メッセージ表示 mov ax,2500h mov dx,VECT0_OFF mov ds,VECT0_SEG int 21h ;割り込みベクタを戻す mov ax,4c00h int 21h ;終了 ;------------------------------------- VECT0: cli ;割り込み禁止 ; push ax ;※注参照 push dx ;レジスタ保管 push ds ;レジスタ保管 push cs pop ds mov ah,9 mov dx,offset INT_MSG int 21h ;表示 pop ds pop dx mov al,20h out 20h,al ;割り込みコントローラーに終わりを告げる ; pop ax ;※注参照 sti ;割り込みを許可する iret ;終了 VECT0_SEG dw ? VECT0_OFF dw ? MSG db 'ゼロで割っちゃった',0dh,0ah,24h INT_MSG db '割り込み処理中です',0dh,0ah,24h ENDS END START ; 一部のコンパイラでは、 ;CODE ENDS ; END START ;と記述しなければいけないようです ;※ 本当ならすべてのレジスタを保管しなくてはならない。 ; 普通の割り込みでは割り込みが発生した命令の次の命令のIPが保存されるが、 ; 除算エラーの場合、原因となった命令のIPが保存される(80186以上)。 ; したがって割り込み処理が終わると、また除算命令に戻ってしまう。 ; このため、例外処理を無限に繰り返してしまうので、終了しなくなってしまう。 ; AXレジスタを保管しないことで、AXレジスタの内容を変え、エラーが ; 繰り返されないようにするため、わざとAXレジスタは保管しなかった。 |