彙編筆記_第十二章

內中斷

中斷的產生

中斷: 中斷分爲 軟件中斷硬件中斷,前者又稱爲內中斷後者又稱爲外部中斷;html

軟件中斷: 由CPU內部的某些事件引發的,不受中斷容許標誌IF的控制。包括:框架

<!-- more -->oop

  • 由終端指令 int n 引發,n指出中斷類型
  • 由CPU的某些錯誤引發,除法錯中斷(類型號0)、溢出中斷(類型號4)
  • 爲調試程序Debug設置的中斷,單步中斷(類型號1)、斷點中斷(類型號3)

硬件中斷: 由輸入輸出外設產生的中斷請求引發的中斷。 8086系統的硬件中斷可分爲 可屏蔽中斷不可屏蔽中斷。全部的中斷請求都有對應的中斷處理子程序與之對應;spa

補充:debug

  • 內中斷中,int n和into指令產生的中斷以及出發錯中斷都不能被禁止,而且比任何外部中斷的優先級都高;
  • 8086系統的硬件中斷都是經過CPU的引腳引入中斷請求型號,不可屏蔽中斷請求信號接到CPU的NMI引腳上,當發生電源故障,奇偶檢驗錯,io通道校驗錯等緊急狀況時有系統自動產生,NMI不可屏蔽中斷的類型號爲2;
  • 可屏蔽中斷是鍵盤、顯示器、打印機、磁盤、串口、並口等外設發出的。因爲可屏蔽中斷種類較多,系統專門有8259A中斷控制器來管理這些中斷。可屏蔽中斷指這些外設能夠用軟件設置容許或禁止器發出中斷請求。8086可屏蔽中斷的中斷類型號爲08H~0FH;
  • 優先級由高到低:內部中斷-非屏蔽中斷-可屏蔽中斷-單步中斷;
  • 硬件中斷時,CPU執行完一條指令後都會讀取INTR引腳信號;
  • 軟件中斷時,若爲0-4號中斷,CPU按相應的方式處理,若是是int n指令,則由n獲取中斷向量轉而執行中斷處理程序;
  • 單步中斷是int 1(TF=1);

中斷處理程序

CPU的設計者必須在中斷信息和其處理程序的入口地址之間創建某種聯繫,使得CPU能夠根據中斷信息能夠找到喲啊執行的處理程序;設計

中斷類型和中斷向量表

8086提供了256箇中斷類型,類型號爲0~FFH;調試

CPU用8位的中斷類型碼經過中斷向量表找到相應的中斷處理程序的入後地址;code

用中斷類型碼找到中斷向量,並用它設置CS和IP,這個工做是由CPU的硬件自動完成的,這個過程稱爲 中斷過程htm

8086中專門創建了一張中斷向量表用於保存全部的中斷向量。表位於內存最低地址區0開始的1KB單元。每一箇中斷向量佔用4個字節,高位放段地址,低位放偏移地址;blog

中斷向量表的地址爲:00000H~003FCH;

其中,

  • 5個專用中斷:類型0中斷(出發出錯)00000H~00003H,保存ip和cs內容、類型1中斷(單步中斷)00004H~00007H、類型2中斷(NMI)00008H~0000BH、類型3中斷(斷點中斷)0000CH~0000FH、類型4中斷(溢出中斷)00010H~00013H;
  • 27個系統保留中斷:類型5中斷~類型31中斷00014H~0007FH;
  • 224個用戶自定義中斷: 類型32中斷~類型255中斷00080H~003FCH;

中斷過程

8086CPU的中斷過程:

一、取得中斷類型碼

二、標誌寄存器的指入棧

三、設置標誌寄存器的第8位TF和第9位IF的值0

四、CS的內容入棧

五、IP的內容入棧

六、從內存地址位中斷類型碼*4和中斷類型碼*4+2的兩個字的單元中讀取中斷處理程序的入口地址設置IP和CS

  • 在使用call指令調用子程序時有一樣的問題,子程序執行後還要返回到原來的執行點繼續執行,因此,call指令先保存當前CS和IP值,而後設置CS和IP跳轉;

中斷處理程序和iret指令

CPU要隨時均可能執行中斷程序,因此中斷處理程序必須一直在內存的某段空間中;同時,中斷程序的入口地址,即中斷向量必須儲存在對應的中斷向量表表項中;

中斷處理程序的編寫方法:

  • 一、保存用到的寄存器
  • 二、處理中斷
  • 三、恢復用到的寄存器
  • 四、用 iret 指令返回

iret指令的功能用匯編語法描述爲:

pop IP
pop CS
popf

iret一般和硬件自動完成的中斷程序配合使用;

入棧的順序時標誌寄存器、CS、IP,和iret的出棧相反;

編寫處理0號中斷

當發生出發溢出時,CPU將進行如下工做:

  • 一、取得中斷類型碼0
  • 二、標誌寄存器入棧,TF、IF設置爲0
  • 三、CS、IP入棧
  • 四、(IP)=(0*4),(CS)=(0*4+2)

中斷處理程序do0,只需顯示"overflow!"

  • 一、相關處理
  • 二、向顯示緩衝區送入字符串"overflow!"
  • 三、返回dos

由於除法溢出隨時可能發生,CPU隨時可能將cs:ip指向do0的入口,執行程序,因此爲了簡單能夠將中斷處理程序do0放到中斷向量表的0000:0200處;

因此最後的處理是;

  • 一、編寫能夠顯示"overflow!"的中斷程序do0;
  • 二、將do0送到內存0000:0200處
  • 三、將do0的入口地址0000:0200存儲在中斷向量表0號表項中

大體的框架:

assume cs:code
code segment
start:
    do0安裝程序
    設置中斷向量表
    mov ax,4c00h
    int 21h

do0:
    顯示字符串:"overflow!"
    mov ax,4c00h
    int 21h
;do0程序在這段程序中並不執行,只是做爲數據傳送到中斷向量表中,即安裝程序
code ends
end start

安裝

中斷程序的安裝可使用 rep movsb 來將do0的代碼送入到0000:0200處;

大體框架:

assume cs:code
code segment
start:
    設置es:di指向目的地址
    設置ds:si指向源地址
    設置cx的長度
    設置傳送方向爲正
    rep movsb

    設置中斷向量表

    mov ax,4c00h
    int 21h

do0:
    顯示字符串:"overflow!"
    mov ax,4c00h
    int 21h

code ends
end start

使用 rep movsb 要肯定的信息:

  • 目的地址:0000:0200
  • 源地址:code:offset do0
  • 傳送的長度cx: do0的代碼的長度
  • 傳送方向爲正: cld

由於do0的長度根據不一樣的序求需求會改變,沒有必要每一次都計算,能夠在最後加一個 do0end:nop,這樣 mov cx,offset do0end-offset do0便可,"-"是編譯器識別的運算符號,編譯器能夠用它來進行兩個 常數 的減法,同時,也能夠處理表達式;

最後的安裝程序:

assume cs:code
code segment
start:
    mov ax,0
    mov es,ax
    mov di,0200h        ;目的地址
    mov ax,cs
    mov ds,ax
    mov si,offset do0   ;源地址
    mov cx,offset do0end-offset do0
    cld
    rep movsb

    設置中斷向量表

    mov ax,4c00h
    int 21h

do0:
    顯示字符串:"overflow!"
    mov ax,4c00h
    int 21h
do0end:nop

code ends
end start

do0

do0的任務是顯示字符串,大體的框架:

do0:
    設置ds:si指向字符串
    mov ax,0b800h
    mov es,ax
    mov di,12*160+36*2
    ;設置es:di指向顯存空間中間位置

    mov cx,9    ;設置cx爲字符串長度
  s:
    mov al,[si]
    mov es:[di],al
    inc si
    add di,2
    loop s

    mov ax,4c00h
    int 21h

do0end:nop

這裏的字符串的存放不能像以前的程序那樣放在總程序的數據段中,由於當總程序運行完後數據段也就釋放,不能保證中斷程序所顯示的字符串仍是"overflow!";

因此要將字符串放在do0中,將其以通送到中斷向量表的0000:0200處;

這樣在發生除法溢出時,cs中存放的是do0的段地址,同時也是字符串的段地址,而由於程序要跳過字符串,不把他看成代碼執行,因此在字符串以前要有一個jmp指令跳過字符串到實際的代碼處,因此字符串的偏移地址就爲0000:0200加2即0000:0202處(jmp佔兩個字節)

最後的程序:

do0:
    jmp short do0start
    db "overflow!"

do0start:
    mov ax,cs
    mov ds,ax
    mov si,0202h
    ;設置ds:si指向字符串

    mov ax,0b800h
    mov es,ax
    mov di,12*160+36*2
    
    mov cx,9

  s:
    mov al,[si]
    mov es:[di],al
    inc si
    add di,2
    loop s

    mov ax,4c00h
    int 21h

do0end:nop

設置中斷向量

設置中斷向量即爲將do0的入後地址0000:0200寫入到中斷向量表的0號表項中,使do0成爲0號中斷的中斷處理程序;

0號表項的地址爲0:0,其中0:0字單元存放偏移地址(ip),0:2字單元存放段地址(cs),

mov ax,0
mov es,ax
mov word ptr es:[0*4],0200h
mov word ptr es:[0*4+2],0

綜上,最後的程序以下:

assume cs:code
code segment
start:
	mov ax,0
	mov es,ax
	mov di,0200h
	mov ax,cs
	mov ds,ax
	mov si,offset do0
	mov cx,offset do0end-offset do0
	cld
	rep movsb
	
	mov ax,0
	mov es,ax
	mov word ptr es:[0*4],0200h
	mov word ptr es:[0*4+2],0
	
	mov ax,1000h
	mov bh,1
	div bh
	
	mov ax,4c00h
	int 21h
	
do0:
	jmp short do0start
	db "overflow!"
do0start:
	mov ax,cs
	mov ds,ax
	mov si,202h
	
	mov ax,0b800h
	mov es,ax
	mov di,12*160+36*2
	
	mov cx,9
	
  s:
  	mov al,[si]
  	mov es:[di],al
  	inc si
  	add di,2
  	loop s
  	
  	mov ax,4c00h
  	int 21h
  	
do0end:nop

code ends
end start

單步中斷

CPU在執行完一條指令後,若是檢測到標誌寄存器的TF位爲1,則產生單步中斷,單步中斷的中斷類型碼爲1;

他引起的中斷類型以下:

  • 一、取得中斷類型碼1
  • 標誌寄存器入棧,TF、IF置0
  • CS,IP入棧
  • (IP)=(14),(CS)=(14+2)

使用t命令時,debug將TF設置爲1,使得cpu執行完這條指令後引起單步中斷;

執行單步中斷的中斷程序,全部寄存器的內容顯示,等待輸入;

中斷處理程序也是由一條條指令組成的,若是在執行中斷處理程序以前,TF=1,則CPU在執行完中斷處理程序的第一條指令後,又要產生單步中斷,則又要轉去執行單步中斷的中斷處理程序…… ?

解決方法是在進入中斷程序以前設置TF=0,也就是在前面說的中斷過程當中的第二步標誌寄存器入棧後設置TF=0的緣由;

CPU提供單步中斷功能的緣由就是,爲單步跟蹤的執行過程,提供了實現機制。

響應中斷的特殊狀況

有些狀況下,CPU在執行完當前指令後,即便發生中斷,也不相應,例如:在執行完向ss寄存器傳送數據的指令後,發生中斷時,CPU也不會響應,由於,ss:sp聯合指向棧頂,對他們的設置應該連續完成;

若是在執行完設置ss的指令後,CPU響應中斷,引起中斷過程,要在棧中壓入標誌寄存器、CS和IP的值。 而ss改變,sp並未改變,ss:sp指向的不是正確的棧頂,將引發錯誤。

因此CPU在執行完設置ss的指令後,不響應中斷。 這給連續設置 ss和sp,指向正確的棧頂提供了一個時機。 即,咱們應該利用這個特性,將設置ss和sp的指令連續存放,使得設置sp的指令緊接着設置ss的指令執行,而在此之間,CPU不會引起中斷過程

解釋了實驗2中的(3)

Debug 利用單步中斷來實現T命令的功能, 也就是說,用T命令執行一條指令後,CPU響應單步中斷,執行Debug設置好的處理程序,才能在屏幕上顯示寄存器的狀態,並等待命令的輸入。

而在mov ss,ax指令執行後,CPU根本就不響應任何中斷,其中也包括單步中斷,

因此Debug設置好的用來顯示寄存器狀態和等待輸入命令的中斷處理程序根本沒有獲得執行,因此咱們看不到預期的結果。

CPU接着向下執行後面的指令mov sp,10h,而後響應單步中斷,咱們纔看到正常的結果

(以上引用來自彙編老師的課件,轉載請註明地址) https://www.cnblogs.com/31415926535x/p/10206507.html (end)

相關文章
相關標籤/搜索