割り込み情報はCPUの内部と外部から発生しますが、CPU内部で処理が必要な場合には、すぐに処理が必要な割り込み情報が発生し、割り込み処理が発生します。http://t.csdn.cn/jihpGでは、割り込み処理と2つの内部割り込みの処理について説明しています。
この章では、もう 1 つの重要な内部割り込みである int 命令による割り込みについて説明します。
int命令
int 命令の形式は次のとおりです: int n
n は割り込みタイプ コードであり、その機能は割り込み処理をトリガーすることです。
CPUは、n割り込みを発生させる割り込み処理に相当するint n命令を実行します。
(1) 割り込みタイプ コード n を取得します。
(2) フラグ レジスタがスタックにプッシュされます (IF=0、TF=0)。
(3) CS と IP がスタックにプッシュされます。
(4)(IP)=(n*4)、(CS)=(n*4+2)
プログラム内で int 命令を使用すると、任意の割り込みの割り込みハンドラーを呼び出すことができます。たとえば、次のようなプログラムです。
このプログラムをDOSモードで実行すると、画面中央に「!」が表示され、その後「ディバイドオーバーフロー」が表示されてシステムに戻ります。「!」は表示するためにプログラムするものですが、「除算オーバーフロー」はどこから来たのでしょうか? 私たちのプログラムには除算がないため、除算オーバーフローは不可能です。
このプログラムでは除算は行わず、最後に int 0 命令を使用します。CPU が int 0 命令を実行すると、割り込み処理が発生し、割り込みハンドラ 0 番が実行されます。システムが設定した割り込みハンドラ 0 番の機能は、「除算オーバーフロー」を表示してシステムに復帰することです。
一般に、システムは、特定の機能を備えたサブルーチンを割り込みハンドラの形式でアプリケーション プログラムに提供します。プログラミングするとき、int 命令を使用してこれらのサブルーチンを呼び出すことができます。もちろん、他の人が使用できるように、いくつかの割り込みハンドラーを自分で作成することもできます。今後、割り込みハンドラを単に割り込みルーチンと呼ぶことにします。
アプリケーションによって呼び出される割り込みルーチンを作成します。
以前、割り込み 0 の割り込みルーチンを作成しました。次に、アプリケーション プログラムから呼び出すことができる割り込みルーチンを作成する方法について説明します。以下で 2 つの質問について説明します。
質問1: 割り込み7chの割り込みルーチンを作成してインストールしてください。
機能: ワードデータの二乗を求めます。
パラメータ: (ax)= 計算されるデータ。
戻り値: 結果の上位 16 ビットと下位 16 ビットが dx と ax に格納されます。
アプリケーション例: 検索: 2*3456^2。
分析するには、次の 3 つの作業を行う必要があります。
(1) 二乗関数を実装するプログラムを作成します;
(2) プログラムをインストールし、0:200 にインストールします。
(3) 割り込みベクタテーブルを設定し、プログラムのエントリアドレスを7chエントリに保存し、7chに割り込む割り込みルーチンとします。
インストール手順は次のとおりです。
assume cs:code
code segment
start:
;安装sqr程序
mov ax,cs
mov ds,ax
mov si,offset sqr ;设置ds:si指向源地址
mov ax,0
mov es,ax
mov di,200h ;设置es:di指向目的地址
mov cx,offset sqrend-offset sqr ;设置cx为传输长度
cld ;设置传输方向为正
rep movsb
;设置中断向量表
mov ax,0
mov es,ax
mov word ptr es:[7ch*4],200h
mov word ptr es:[7ch*4+2],0
mov ax,4c00h
int 21h
sqr:mul ax ;求平方
iret
sqrend:nop
code ends
end start
なお、割り込みルーチン sqr の最後には iret 命令が使用されます。
iret 命令の機能をアセンブリ構文で説明すると、次のようになります。
ポップIP
ポップCS
ポップ
CPU が int 7ch 命令を実行して割り込みルーチンに入る前に、フラグレジスタ、現在の CS、IP がスタックにプッシュされますので、割り込みルーチン実行後、iret 命令を使用してフラグレジスタ、CS、IP を復元する必要があります。アプリケーションの実行を継続するための int 7ch 実行値。
int 命令と iret 命令の組み合わせは、call 命令と ret 命令の組み合わせと同様の考え方です。
int、iret、stack についての深い理解
質問: ループ命令の機能を完了するには、7ch 割り込みルーチンを使用します。
ループ s の実行にはループ回数と s への変位の 2 つの情報が必要となるため、7ch 割り込みルーチンもループ命令の機能を完了するためのパラメータとしてこれら 2 つの情報を必要とします。cx を使用してサイクル数を保存し、bx を使用して変位を保存します。
応用例:画面中央に80個の「!」を表示
assume cs:code
code segment
start:
;
mov ax,0b800h
mov es,ax
mov di,160*12+0
mov bx,offset s-offset se ;计算从标号s到标号se的转移位移
mov cx,80
s:mov byte ptr es:[di], '!'
add di,2
int 7ch ;如果(cx)≠0,转移到标号s处,就是完成loop s的功能
se:nop
mov ax,4c00h
int 21h
code ends
end start
上記プログラムでは、int 7chで転送用の7ch割り込みルーチンを呼び出し、bxで転送した変位を転送しています。
分析: ループ命令をシミュレートするには、7ch 割り込みルーチンに次の機能が必要です。
(1)dec cx;
(2) (cx)≠0 の場合はラベル s に進み、それ以外の場合は下方向に実行します。
次に、7ch 割り込みルーチンが宛先アドレスへの転送をどのように実行するかを解析します。
(1) ラベル s に移動するには、(CS) = ラベル s のセグメント アドレス、(IP) = ラベル s のオフセット アドレスであることが明らかです。
(2) では、割り込みルーチンはどのようにしてラベル s のセグメントアドレスとオフセットアドレスを取得するのでしょうか?
int 7ch が割り込み処理を起動した後、7ch 割り込みルーチンに入りますが、割り込み処理中にカレントフラグレジスタ、CS、IP が取得されなければなりません。スタック、このときプッシュされるCSとIPの内容は、それぞれ呼び出し元プログラムのセグメントアドレス(ラベルsのセグメントアドレスと考えてよい)とint 7ch以降の命令のオフセットアドレス(つまり、 、ラベル se) のオフセット アドレス。
割り込みルーチンでは、ラベル s のセグメント アドレスとラベル se のオフセット アドレスがスタックから取得でき、ラベル s のオフセット アドレスはラベルのオフセット アドレスを加算することで取得できることがわかります。 se と bx. アドレスに保存されている転送変位を加算します。
(3) ラベルのセグメント アドレスとオフセット アドレスがスタックから直接的または間接的に取得できることがわかりました。それでは、それらを使用して CS:IP を設定するにはどうすればよいでしょうか? iret 命令を使用できます。オフセット アドレスを設定します。 bxの
転送ディスプレースメントを加算すると、スタック内の se のオフセット アドレスが s のオフセット アドレスになります。次に iret 命令を使用して CS と IP にスタックの内容を設定し、それによってラベル s に転送します。
7ch割り込みルーチンは以下の通りです。
lp:push bp
mov bp,sp
dec cx
jcxz lpret ;cx=0就转移
add[bp+2],bx ;产生中断时,pushf push cs push ip,进入中断程序后又push bp
;(bp+2)就是se标号ip
;(bp+2)加上位移bx就是s的偏移地址
;之后iret过程中pop ip获取的就是s的偏移地址
lpret:pop bp
iret
BIOS および DOS 割り込みルーチンのインストール プロセス
前のレッスンでは、独自の割り込みルーチンを作成してインストーラーに配置し、インストーラーを実行して指定されたメモリ領域にそれらをインストールしました。その後、他のアプリケーションがそれを呼び出すことができます。BIOS および DOS によって提供される割り込みルーチンはどのようにしてメモリにインストールされるのでしょうか? 以下でそのインストール プロセスについて説明します。
(1) 電源投入後、CPU に電源を投入すると、(CS)=0FFFFH、(IP)=0 に初期化され、自動的にユニット FFFF:0 からプログラムの実行を開始します。FFFF: 0 にジャンプ命令があります。CPU がこの命令を実行した後、BIOS でハードウェア システムの検出および初期化プログラムが実行されます。
(2) 初期化プログラムは、BIOS がサポートする割り込みベクタを設定します。つまり、BIOS が提供する割り込みルーチンのエントリアドレスを割り込みベクタ テーブルに登録します。なお、BIOS が提供する割り込みルーチンは、ROM 化されたプログラムであり常にメモリ上に存在するため、割り込みベクタテーブルにエントリアドレスを登録するだけで済みます。
(3) ハードウェア システムの検出と初期化が完了したら、int 19h を呼び出してオペレーティング システムを起動します。コンピュータはオペレーティング システムによって制御されるようになりました。
(4) DOS が起動すると、他のタスクを完了するだけでなく、DOS が提供する割り込みルーチンもメモリにロードし、対応する割り込みベクトルを確立します。
BIOS 割り込みルーチン アプリケーション
BIOS 割り込みルーチンのアプリケーションを確認するために、いくつかの例を示します。
int 10h 割り込みルーチンは、BIOS が提供する割り込みルーチンで、画面出力に関する複数のサブルーチンが含まれています。
一般に、プログラマによって呼び出される割り込みルーチンには複数のサブルーチンが含まれることが多く、渡されたパラメータは割り込みルーチン内でどのサブルーチンを実行するかを決定するために使用されます。BIOS および DOS によって提供される割り込みルーチンはすべて、ah を使用して内部サブルーチンの番号を渡します。int 10h 割り込みルーチンのカーソル位置を設定する機能
を見てみましょう。
(ah)=2は割り込みルーチンNo.10hのサブルーチンNo.2を呼び出すことを意味します。機能はカーソル位置を設定することであり、行番号(80*25文字モード時:0~24)と列番号(80)を与えることができます※25文字モード時:0~79)、ページ番号をパラメータとします。
bh のページ番号の意味: メモリ アドレス空間では、B8000H ~ B FFFFH は合計 32kB の空間を持ち、これは 80*25 色文字モードの表示バッファです。1 画面のコンテンツは表示バッファー内で合計 4000 バイトを占めます。
表示バッファは 8 ページに分割されており、各ページは 4KB (~4000B) であり、モニターは任意のページの内容を表示できます。通常は0ページ目の内容が表示されます。つまり、通常の状況では、B8000H ~ B8F9FH の 4000 バイトのコンテンツがディスプレイに表示されます。
int10h 割り込みルーチンのカーソル位置に文字を表示する機能をもう一度見てみましょう。
(ah)=9は割り込みルーチンNo.10hのサブルーチンNo.9を呼び出すことを意味します カーソル位置の文字を表示する機能です 表示する文字、色属性、ページ番号、繰り返し文字数を指定できますパラメータとして。
blにおけるcolor属性の形式は以下の通りです。
プログラミング: 画面の 5 行 12 列に、背景が赤で 3 つの 'a が強調表示され、緑色に点滅して表示されます。
点滅効果は全画面 DOS モードで表示する必要があることに注意してください。
DOS割り込みルーチンアプリケーション
int 21h 割り込みルーチンは、DOS によって提供される割り込みルーチンです。これには、プログラミング時に呼び出すために DOS がプログラマに提供するサブルーチンが含まれています。int 21h 割り込みルーチンの 4ch 関数、つまりプログラムリターン関数を以下のように
使用しています。
mov ああ、4ch; プログラムが戻ります
mov al,0 ;戻り値
int 21h
(ah)=4ch は、21h 割り込みルーチンの 4ch サブルーチンを呼び出すことを意味し、関数はプログラムリターンであり、戻り値をパラメータとして渡すことができます。以前にこの関数を使用したとき、よく次のように書きました。
mov ax、4c00h
int 21h
カーソル位置に文字列を表示するint 21h 割り込みルーチンの関数を見てみましょう。
ds:dx;文字列へのポインタ。表示する文字列は終端文字として「$」を使用する必要があります。
mov ah,9; 関数番号 9、カーソル位置に文字列を表示することを意味します
int 21h
(ah)=9 は、割り込みルーチン番号 21h のサブルーチン番号 9 を呼び出すことを意味し、その機能はカーソル位置に文字列を表示することであり、表示する文字列のアドレスをパラメータとして指定できます。
上記のプログラムは、文字列「Welcome to masm!」を「$」に遭遇するまで画面の 5 行 12 列に表示します (「$」自体は表示されず、境界としてのみ機能します)。
文字列が比較的長く、行末に達すると、プログラムは自動的に次の行の先頭に移動して表示を継続し、最終行に達すると、自動的に 1 行上にスクロールします。