←前へ :  INDEX :  次ページへ→


  では、除算エラーのエラーメッセージを変えてみよう。Windows98のコマンドプロンプトから 0で割るプログラムを実行すると下のようになる。

  このメッセージを変えてみるプログラム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レジスタは保管しなかった。


CODE SEGMENT ASSUME DS:CODE,CS:CODE,ES:CODE,SS:CODE .186 ORG 100h START: xor di,di xor ax,ax mov ds,ax mov bx,[di+0] mov es,[di+2] mov VECT0_SEG,es mov VECT0_OFF,bx ;割り込みベクタ保管 cli ;割り込み禁止 mov [di+0],offset VECT0 mov [di+2],cs ;割り込みベクタ設定 sti ;割り込み許可 push cs pop ds xor ax,ax div al ;0で割ってみる mov ah,9 mov dx,offset MSG int 21h ;メッセージ表示 mov dx,VECT0_OFF mov es,VECT0_SEG xor ax,ax mov ds,ax mov [di+0],dx mov [di+2],es ;割り込みベクタを戻す 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レジスタは保管しなかった。


←前へ :  INDEX :  次ページへ→