組合語言(第3版,王爽著):實驗16 編寫包含多個功能子程式的中斷例程
阿新 • • 發佈:2022-05-26
1) 思路:
- 根據 “第 16 章中的程式碼示例” 以及 “安裝程式” 的套路,仿照著之前的例子,程式碼寫出來不會太難
- 需要注意以下幾點:
a. 在程式碼段中,“標號”或者是“資料標號”,都代表了該段內的某一個偏移地址。
b. 對於任何一個記憶體段來說,段地址可以開始於任何16 位元組對齊的地方,偏移地址則總是從 0x0000 開始遞增。
c. 在編譯階段,每條指令都被計算並賦予了一個彙編地址,就像它們已經被載入到記憶體中的某個段裡一樣。實際上,當編譯好的程式載入到實體記憶體後,它在段內的偏移地址和它在編譯階段的彙編地址是相同的。
d. 在安裝“中斷例程”程式時,如果“中斷例程”中的直接定址表有使用到多個子程式的“標號”,那麼我們需要在“中斷例程”第一行指令前面,使用 org 偏移地址設定程式段的起始地址,否則“中斷例程”中的標號對應的偏移地址,依然還是安裝程式在執行時的偏移地址。
溫馨提示:
- 對於 標號 對應的偏移地址有疑問的,請檢視 《x86組合語言:從真實模式到保護模式》(李忠) 第 5 章的 5.5 小節。
- 使用 org 偏移地址 設定程式段的起始地址(即 從“org 偏移地址”開始,後面指令的偏移地址將按照設定的起始地址(偏移地址)為起點開始遞增)。
2) int 7ch 中斷例程程式碼:
檔名:exp16.asm
assume cs:code code segment start: mov ax, cs mov ds, ax mov si, offset setscreen ; 設定 ds:si 指向源地址 mov ax, 0 mov es, ax mov di, 200h ; 設定 es:di 指向目的地址 mov cx, offset setscreenend - offset setscreen ; 設定 cx 為傳輸長度 cld ; 設定傳輸方向為正 rep movsb ; 設定中斷向量表 mov ax, 0 mov es, ax cli mov word ptr es:[7ch * 4], 200h mov word ptr es:[7ch * 4 + 2], 0 sti mov ax, 4c00h int 21h ; 新的 int 7ch 中斷例程 org 200h ; 設定 200h 作為以下指令的起始地址,後面指令的偏移地址將按照設定的起始地址(偏移地址)為起點開始遞增 setscreen: jmp short set table dw sub1, sub2, sub3, sub4 set: push bx cmp ah, 3 ; 判斷功能號是否大於 3 ja sret mov bl, ah ; ah 暫存器傳遞功能號 mov bh, 0 add bx, bx ; 根據 ah 中的功能號,計算對應子程式在 table 表中的偏移(table 表使用 dw 定義字型資料,所以需要 功能號*2) call word ptr table[bx] ; 呼叫對應的功能子程式 sret: pop bx iret sub1: push bx push cx push es mov bx, 0b800h mov es, bx mov bx, 0 mov cx, 2000 sub1s: mov byte ptr es:[bx], ' ' add bx, 2 loop sub1s pop es pop cx pop bx ret ; 清屏 sub2: push bx push cx push es mov bx, 0b800h mov es, bx mov bx, 1 mov cx, 2000 sub2s: and byte ptr es:[bx], 11111000b or es:[bx], al add bx, 2 loop sub2s pop es pop cx pop bx ret ; 設定前景色(字元顏色) sub3: push bx push cx push es mov cl, 4 shl al, cl mov bx, 0b800h mov es, bx mov bx, 1 mov cx, 2000 sub3s: and byte ptr es:[bx], 10001111b or es:[bx], al add bx, 2 loop sub3s pop es pop cx pop bx ret ; 設定背景色 sub4: push cx push si push di push es push ds mov si, 0b800h mov es, si mov ds, si mov si, 160 ; ds:si 指向第 n+1 行 mov di, 0 ; es:di 指向第 n 行 cld mov cx, 24 ; 共複製 24 行 sub4s: push cx mov cx, 160 rep movsb ; 複製一整行,一行有 160 個位元組 pop cx loop sub4s mov cx, 80 mov si, 0 sub4s1: mov byte ptr [160*24+si], ' ' ; 最後一行清空 add si, 2 loop sub4s1 pop ds pop es pop di pop si pop cx ret ; 向上滾動一行 setscreenend: nop code ends end start
3) 測試程式程式碼:
檔名:exp16d.asm
- 清屏
assume cs:code code segment start: mov ah, 0 ; 0 表示清屏,1 表示設定前景色,2 表示設定背景色,3 表示向上滾動一行 mov al, 2 ; 對於 1、2 號功能,用 al 傳送顏色值,(al)∈{0, 1, 2, 3, 4, 5, 6, 7} int 7ch ; 呼叫新的 int 7ch 中斷例程 mov ax, 4c00h int 21h code ends end
- 設定前景色
assume cs:code
code segment
start:
mov ah, 1 ; 0 表示清屏,1 表示設定前景色,2 表示設定背景色,3 表示向上滾動一行
mov al, 2 ; 對於 1、2 號功能,用 al 傳送顏色值,(al)∈{0, 1, 2, 3, 4, 5, 6, 7}
int 7ch ; 呼叫新的 int 7ch 中斷例程
mov ax, 4c00h
int 21h
code ends
end
- 設定背景色
assume cs:code
code segment
start:
mov ah, 2 ; 0 表示清屏,1 表示設定前景色,2 表示設定背景色,3 表示向上滾動一行
mov al, 2 ; 對於 1、2 號功能,用 al 傳送顏色值,(al)∈{0, 1, 2, 3, 4, 5, 6, 7}
int 7ch ; 呼叫新的 int 7ch 中斷例程
mov ax, 4c00h
int 21h
code ends
end
- 向上滾動一行
assume cs:code
code segment
start:
mov ah, 3 ; 0 表示清屏,1 表示設定前景色,2 表示設定背景色,3 表示向上滾動一行
mov al, 2 ; 對於 1、2 號功能,用 al 傳送顏色值,(al)∈{0, 1, 2, 3, 4, 5, 6, 7}
int 7ch ; 呼叫新的 int 7ch 中斷例程
mov ax, 4c00h
int 21h
code ends
end