※ [本文轉錄自 ric 信箱]
發信人: dv.bbs@csie.nctu (皮皮), 信區: programming
標 題: 優良信件轉載
發信站: 交大資工鳳凰城資訊站 (Sat Mar 18 16:18:40 1995)
轉信站: bridge!bbsroute!phoenix
以下信件, 原載於 90-assembly, 是關於 PC 鍵盤,
並非我寫的, 我作的只有轉載的工作. 希望對您有幫助.
--------------------------------------------------------------- 90-ASSEMBLY -
Msg : 63 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 19:56:00
To : All
Subj : 關於鍵盤
-----------------------------------------------------------------------------
近來看了看許多網友討論鍵盤的控制,並不是非常熟悉,
故將我寫好關於鍵盤方面的資料上傳給諸位參考,
希望對各位有所助益. 這些資料原是我準備寫"軟體保護技術研究"
一書中的文章,但因工作忙碌,一直無法順利寫完 (寫了半年多才寫
這麼一點...). 除了鍵盤資料外,我也將一些硬體控制方面的資料
一併上傳,其中關於146818 (CMOS控制)以前已上傳過,因此不再重
複上傳. 8237 (DMA控制) 尚未完全寫完,以後再說.
所有上傳的資料都是我參考多本書籍,並親自寫程式測試過的,
正確性應極高. 當然,若文中有錯誤的地方,也請指正一下,免得
我繼續"誤"人. 如果有進一步興趣的話,以下是一些參考書籍,
可供進一步研究.
7.PC系統程式設計, 吳宗穎&賴明宏譯, 格致, 1990.
8.DOS技術手冊(二)徹底研究篇, 施威銘著, 旗標, 1987.
9.BIOS系統呼叫, 林鴻明編譯, 格致, 1989.
10.IBM PC介面技術與週邊設備實習, 謝聿婷編著, 全欣, 1989.
11.IBM PC BIOS程式剖析, 林書華著, 儒林, 1985.
12.IBM PC/XT硬體線路精解, 劉紹漢編著, 全華, 1991.
13.IBM PC/AT硬體技術手冊, 趙健雄譯, 儒林, 1986.
14.386/AT硬體徹底剖析, 陳柏村編著, 全華, 1991.
15.Intel Total Solution Component & Development Tool Handbook,
Intel, 1987.
16.Microsystem Components Handbook, Microprocessors and Peripherals,
Volume I, II, Intel, 1985.
17.The TTL Data Book, Volume I,II,III, TEXAS Instruments, 1984.
[7,8,9]為介紹PC系統的相關書籍,[7]的內容幾乎涵蓋了所有的PC系統相
關知識,但介紹並不是很深入,頗適合技術參考使用。[8]及[9]則分別對
於DOS及BIOS有更詳細的介紹,較適合初學者閱讀。[10,11,12,13,14,15,
16,17]則是介紹PC硬體控制的書籍,[10]的介紹頗詳細,但硬體的種類也
較少,頗適合初學者閱讀;[11]為解析BIOS的書籍,所涵蓋的硬體較多,
但介紹也較不深入;[12]則對PC的線路設計加以說明,以上三本都是針對
PC/XT的架構做說明的。[13,14]則以PC/AT為主做說明,[13]主要是針對
286/AT的硬體線路及控制部份加以說明,其中還附有完整的AT BIOS程式,
頗適合程式設計師閱讀。[14]則是針對386/AT的元件加以詳細說明,主要
的內容為電路的設計,對純學軟體的人來說,看來會比較吃力些,但是其
中一些關於軟體控制方式仍頗具參考價值。至於[15,16,17]則是以零件的
觀點說明該零件的控制方式,頗適合搭配上述的書籍參考使用。[15,16]
均為INTEL的80系列零件,其中[16]較偏重於AT的機器,[17]則為TTL零件
的參考手冊。
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
--------------------------------------------------------------- 90-ASSEMBLY -
Msg : 64 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 19:46:00
To : All
Subj : 鍵盤1
-----------------------------------------------------------------------------
一.鍵盤
想要中斷鍵盤與追蹤者的連繫,首先我們必須完全了解鍵盤的輸入到
追蹤者取得的整個過程,如此我們才能從這個過程中找到中斷的地方。在
早期的XT上,鍵盤控制器是使用8048,當鍵盤有任何按鍵按下時,首先由
8048取得該按鍵的掃描碼(Scan Code)後,將掃描碼傳給8255(8255同
時也控制著是否允許鍵盤工作),然後送出岔斷訊號給8259,由8259發出
IRQ1岔斷訊號給CPU,然後跳入INT 9h的岔斷處理程式執行。而在AT上,
鍵盤控制器改用了功能較強的8042,同時也取消了8255這個週邊界面元件,
因此掃描碼便不經由8255傳送,而直接由8042傳送。雖然XT和AT有這些差
異,但事實上各I/O Port的功能大致上仍頗相容,因此大部份的XT程式還
是可以在AT上正確的執行。
INT 9h的岔斷處理程式主要是從8255取得Scan Code,然後將之換算
成ASCII碼,最後再將兩者放到鍵盤緩衝區內(鍵盤緩衝區的位址由BIOS
的一些參數決定)。這之中當然還處理了一些特殊的按鍵,如Ctrl-Alt-Del、
Caps Lock等等。而電腦的執行程式便經由岔斷INT 16h來偵測及取得在鍵
盤緩衝區內的按鍵資料,最後依照所得到的按鍵資料進行指定的工作。整
個連繫的過程大致是這樣子。如果你對於前面所說的過程中,關於硬體部
份如8255、8042、8259等不是很了解的話,請你隨時參閱附錄一中的說明
後再繼續往下閱讀。
由這個連繫的過程,我們大概可推出下類幾種截斷鍵盤輸入的方式:
1.控制8042,使得鍵盤無法輸入或不可輸入。
2.控制8255,阻止鍵盤的輸入。
3.控制8259,阻止鍵盤岔斷的產生或進入鍵盤岔斷處理程式。
4.破壞或截斷鍵盤岔斷處理程式。
5.破壞、改變或檢查鍵盤緩衝區內的資料及其輸入指標值。
6.破壞或截斷鍵盤資料輸入岔斷處理程式。
以下我們便仔細說明這些截斷鍵盤輸入的方法。
技術一 利用8042控制命令將鍵盤禁能
在說明如何利用8042控制命令將鍵盤禁能之前,我們先說明8042控制
命令的下達方式:
;
; ========================================================
; 以下為8042界面函數之內部呼叫函數
; ========================================================
;
Flush8042 PROC
; 清除所有的輸出緩衝器資料
push ax
FlushOBF: in al,64h
test al,1
jz NotOBF
in al,60h
jmp short FlushOBF
NotOBF: pop ax
retn
Flush8042 ENDP
;
WaitIBF PROC
; 等待8042輸入緩衝器有空
WaitIBFLoop: push ax
in al,64h
test al,2
pop ax
jnz WaitIBFLoop
retn
WaitIBF ENDP
;
WaitOBF PROC
; 等待8042輸出緩衝器有資料送來
WaitOBFLoop: push ax
in al,64h
test al,1
pop ax
jz WaitOBFLoop
retn
WaitOBF ENDP
;
Read8042Data PROC
; 讀取8042回應資料
; 傳回: AL = 回應資料
call WaitOBF ; 等待資料回庄
in al,60h
retn
Read8042Data ENDP
;
Write8042Data PROC
; 送出資料給8042
; 參數: AL = 8042系統命令或資料
; 備註: 本函數亦為送出系統命令或資料的函數
call WaitIBF ; 等待輸入緩衝區有空
out 60h,al ; 送出資料
call WaitIBF ; 確認8042收到
retn
Write8042Data ENDP
;
RealSend8042Cmd PROC
; 送出一般命令碼給8042
; 參數: AL = 8042一般控制命令
; 備註: 8042命令之參數或傳回值由外界處理
call WaitIBF ; 等待輸入緩衝區有空
out 64h,al ; 送出命令
call WaitIBF ; 確認8042收到
retn
RealSend8042Cmd ENDP
;
RealSend8042Sys PROC
; 送出系統命令碼或參數給8042
; 參數: AL = 8042系統控制命令或參數
; 傳回: AL = 8042回應值
; 備註: 除回音外,其餘命令或參數應檢查是否傳回ACK
call Flush8042
call Write8042Data
call Read8042Data
retn
RealSend8042Sys ENDP
;
; ========================================================
; 以下為8042界面函數,使用前必須使用CLI將岔斷禁能
; ========================================================
;
Send8042Cmd PROC
; 送出一般命令碼給8042
; 參數: AL = 8042一般控制命令
call RealSend8042Cmd
retn
Send8042Cmd ENDP
;
Read8042Cmd PROC
; 送出讀取命令給8042
; 參數: AL = 8042讀取命令
; 傳回: AL = 讀取值
call Flush8042
call RealSend8042Cmd
call Read8042Data
retn
Read8042Cmd ENDP
;
Write8042Cmd PROC
; 送出寫入命令給8042
; 參數: AL = 8042寫入命令
; AH = 寫入資料
; 備註: AX值會被破壞
call RealSend8042Cmd
xchg al,ah
call Write8042Data
retn
Write8042Cmd ENDP
;
Echo8042 PROC
; 送出8042回音命令
; 傳回: AL = EEh
mov al,0EEh ; 回音命令
call RealSend8042Sys
retn
Echo8042 ENDP
;
Send8042Sys PROC
; 送出系統命令碼或參數給8042
; 參數: AL = 8042系統控制命令或參數
; 備註: 本函數會自動一直傳送,直到8042回應ACK
RetrySysCmd: push ax
call RealSend8042Sys
cmp al,0FAh ; ACK訊號?
pop ax
jne RetrySysCmd
retn
Send8042Sys ENDP
;
Write8042Sys PROC
; 送出系統寫入命令給8042
; 參數: AL = 8042系統寫入命令
; AH = 寫入資料
; 備註: AX值會被破壞
call Send8042Sys
xchg al,ah
call Send8042Sys
retn
Write8042Sys ENDP
;
Read8042Sys PROC
; 送出系統讀取命令給8042
; 參數: AL = 8042系統讀取命令
; AH = 寫入資料
; 備註: AX值會被破壞
call Send8042Sys
call Read8042Data
retn
Read8042Sys ENDP
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
--------------------------------------------------------------- 90-ASSEMBLY -
Msg : 65 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 19:47:00
To : All
Subj : 鍵盤2
-----------------------------------------------------------------------------
以上8042界面函數的使用方式可區分如下:
1.一般控制命令
Read8042Cmd = 8042讀取命令(有回送值者)使用。
Write8042Cmd = 8042寫入命令(有參數者)使用。
Send8042Cmd = 其他無回送值或參數者使用。
2.系統命令
Echo8042 = 回音命令專用。
Read8042Sys = 8042讀取命令(有回送值者)使用。
Write8042Sys = 8042寫入命令(有參數者)使用。
Send8042Sys = 其他無參數者使用。
記得這些函數在使用前一定要使用CLI指令將岔斷禁能,否則會無法
正常執行。現在我們正式開始探討利用8042控制命令將鍵盤禁能的技術:
1.改變8042命令位元組位元4的值以抑制鍵盤。一般的寫法如下:
mov al,20h ; 讀取8042命令位元組
call Read8042Cmd
or al,10h ; 將位元4設成1以抑制鍵盤
mov ah,al
mov al,60h ; 將8042命令位元組寫回
call Write8042Cmd
還原的方式便是:
mov al,20h ; 讀取8042命令位元組
call Read8042Cmd
and al,0EFh ; 將位元4設成0以啟動鍵盤
mov ah,al
mov al,60h ; 將8042命令位元組寫回
call Write8042Cmd
由於我們已知8042命令位元組之初值大都使用45h,因此上面的抑制的
程式也可以直接寫成:
mov ax,5560h
call Write8042Cmd
還原的方式為:
mov ax,4560h
call Write8042Cmd
另外亦可直接使用控制命令還原命令位元組位元4的值,請參見第三點
的說明。
2.改變8042命令位元組位元0的值以抑制岔斷訊號的產生。寫法和第一點
類似,因此不再多做說明:
mov al,20h ; 讀取8042命令位元組
call Read8042Cmd
and al,0FEh ; 將位元0設成0以抑制岔斷
mov ah,al
mov al,60h ; 將8042命令位元組寫回
call Write8042Cmd
還原的方式為:
mov al,20h ; 讀取8042命令位元組
call Read8042Cmd
or al,01h ; 將位元0設成1以啟動岔斷
mov ah,al
mov al,60h ; 將8042命令位元組寫回
call Write8042Cmd
另一種寫法:
mov ax,4460h
call Write8042Cmd
還原方式:
mov ax,4560h
call Write8042Cmd
3.使用鍵盤失效命令抑制鍵盤,該命令會自動將8042位元組之位元4設成0。
寫法如下:
mov al,0ADh
call Send8042Cmd
還原方式為:
mov al,0AEh
call Send8042Cmd
亦可直接更動8042命令位元組的值,請參見第一點的說明。
4.使用系統預設失效命令,暫停鍵盤功能。寫法如下:
mov al,0F5h
call Send8042Sys
還原方式為:
mov al,0F4h
call Send8042Sys
但是這個命令會影響到鍵盤的延遲與重複率(回復到預設值),對於已
將鍵盤的延遲與重複率設成最快的使用者會覺得很不方便,可以下列方
式重新設回:
mov ax,00F3h
call Write8042Sys
技術二 改變8042之模式狀態
將可程式化硬體的執行模式改變,使之無法與外部線路或處理程式相
配合,如此也可以達到保護的效果。當然這項改變必須是可以回復,而且
不損及原系統之正常運作為前提才行的。以下為8042可改變的模式:
1.改變命令位元組位元6的斷開碼格式。藉由將這個位元設定成0使之成為
雙斷開碼格式(PC上為使用單斷開碼),原PC之鍵盤岔斷INT 9h將無法
再正常地處理8042所送入之鍵盤資料,但是在還原之前必須將岔斷禁能,
以避免出現一大堆原INT 9h解出的錯誤鍵盤資料。改變斷開碼的寫法如
下:
mov al,20h ; 讀取8042命令位元組
call Read8042Cmd
and al,0BEh ; 將位元6設成0以使用雙斷開碼
mov ah,al
mov al,60h ; 將8042命令位元組寫回
call Write8042Cmd
還原的方式為:
mov al,20h ; 讀取8042命令位元組
call Read8042Cmd
or al,40h ; 將位元6設成1以使用單斷開碼
mov ah,al
mov al,60h ; 將8042命令位元組寫回
call Write8042Cmd
另一種寫法:
mov ax,0460h
call Write8042Cmd
還原方式:
mov ax,4560h
call Write8042Cmd
這個技術特別適合自行撰寫的鍵盤岔斷處理程式,以做為密碼等資料輸
入使用。即使在密碼輸入中途被岔斷欲破解,只要自行撰寫的鍵盤岔斷
處理程式不和原INT 9h的鍵盤岔斷處理程式相容的話,追蹤者將再也無
法藉由鍵盤對電腦下命令,從而達到保護的效果。當然使用這種方式還
要考慮到其他的輸入裝置,如滑鼠的INT 33h等,這方面不在本書的討
論範圍內。以下為一個雙斷開碼轉單斷開碼之鍵盤岔斷處理程式:
NewInt9h PROC
; 處理雙斷開碼轉單斷開碼的鍵盤岔斷處理程式
push ax
in al,60h ; 讀取鍵盤送來資料
cmp al,0F0h ; 雙斷開碼第一位元組?
jne NormalInt9h
WaitSecond: in al,64h ; 等待第二個斷開碼過來
test al,1
jz WaitSecond
in al,60h
or al,80h
NormalInt9h: ; 自己寫的單斷開碼處理程式放在此處
; 該程式可參考AT BIOS的書籍
; 但要注意暫存器值的保存
; AL = 鍵盤讀出的資料 (單斷開碼格式)
mov al,20h ; 送出EOI給第一個8259
out 20h,al
pop ax
iret
NewInt9h ENDP
2.將命令位元組位元0改成值1,使用Polling處理方式。這個位元的設定
與還原方式,請參見技術一的第二點。不使用岔斷而使用Polling的處
理方式,也適合用在輸入密碼上,以下為鍵盤資料輸入的Polling處理
方式:
Poll8042 PROC
; 使用Polling方式取得鍵盤資料
; 傳回: Carry On = 鍵盤沒有資料輸入
; Carry Off時, AL = 鍵盤資料
in al,64h
test al,1
jz NoKBData
in al,60h
clc
retn
NoKBData: stc
retn
Poll8042 ENDP
上面這個函數所讀取到的資料仍會受斷開碼格式的影響。使用Polling
處理方式時,要特別注意因處理不及導致的資料覆蓋問題,因此這種處
理方式通常不適於組合鍵的處理(如Ctrl-A)。如果沒有組合鍵,一般
都可以不管資料覆蓋的問題。
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
--------------------------------------------------------------- 90-ASSEMBLY -
Msg : 66 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 19:48:00
To : All
Subj : 鍵盤3
-----------------------------------------------------------------------------
技術三 利用8042存取重要指令或資料
8042的命令位元組是一個可以完全讀寫的暫存器,而這個位元組的值
與鍵盤的作用是息息相關的,因此若要完全隔絕使用者對鍵盤的控制,又
要避免使用者跳過對此位元組的讀寫,最有效的方法便是將一些重要資料
或指令暫存在這個暫存器內,而在稍後再讀回使用。若大量使用此一方法,
勢必造成追蹤者在破解過程中極大的困擾,必須時時記錄該值並跳過讀寫
的程式。若再混用技術二不可跳略的鍵盤輸入處理方式,要破解便要費上
極大的功夫。但是在設回原值前,記得必須要將岔斷禁能。以下為寫入的
方式:
mov ah,<資料>
mov al,60h
call Write8042Cmd
讀取方式為:
mov al,20h
call Read8042Cmd
如此AL便傳回原寫入的資料。最後還原的方式便是:
mov ax,4560h
call Write8042Cmd
讀寫的資料可以是指令、位址、資料、密碼、鍵值等等。另外,某些會輸
出固定值的8042命令,其回送值也可以當成上述資料運算使用,只不過這
些命令較死,效果不若命令位元組來得好。以下為會傳送固定值的8042命
令:
AAh(一般命令) -> 55h
ABh(一般命令) -> 00h
EEh(系統命令) -> EEh
FFh(系統命令) -> AAh(會影響鍵盤延遲與重複率)
技術四 控制8255將鍵盤禁能
8255之Port B位元7用來控制鍵盤的啟用與否,因此藉由改變這個位
元值便能達到使鍵盤禁能的目的。以下為使鍵盤禁能的方式:
in al,61h
or al,80h
out 61h,al
還原的方式為:
in al,61h
and al,7Fh
out 61h,al
由於AT並不使用8255,因此這個技術只對XT有效,對於AT並無效。但
因為AT Port 61h高四位元為僅讀位元,因此這項技術即使用在AT上也不
會造成其他不良的影響。
技術五 改變8259的岔斷位址
由於8259可以更改岔斷的起始位址,因此如果我們將8259重新初始化,
改變它的岔斷起始位址,則鍵盤插斷便不會再呼叫INT 9h,如此再配合其
他技術便可達到鍵盤禁用的目的。例如:
1.將INT 08h~INT 0Fh岔斷位址複製到INT 00h~INT 07h,然後改變
8259的岔斷起始位址為00h,則鍵盤岔斷將改在INT 1h,這個岔斷
剛好就是追蹤程式常用的單步岔斷。如此便可使得追蹤者一但使用
單步追蹤便無法使用鍵盤,要使用鍵盤便無法使用單步追蹤。這個
方式特別適合自己寫的鍵盤岔斷處理程式和資料輸入程式,使得在
輸入密碼過程中不易被岔斷破解。
2.將8259的岔斷起始位址隨便改到一個位址,並將岔斷禁能。由於追
蹤者在追蹤過程中一定要用到岔斷,因此一但他將岔斷允能,便會
因鍵盤岔斷跳入不名的程式位址而導致當機或其他結果。
重新初始化8259以改變岔斷起始位址的方式如下:
(一)PC/XT
in al,21h ; 先取得並記錄原來的IMR值
push ax
mov al,13h ; 送出ICW1
out 20h,al
jmp short $+2 ; 延遲
mov al,<起始位址> ; 送出ICW2 (原值08h)
out 21h,al
jmp short $+2
mov al,09h ; 送出ICW4
out 21h,al
jmp short $+2
pop ax
out 21h,al ; 設回原來的IMR值
(二)AT第一個8259
in al,21h ; 先取得並記錄原來的IMR值
push ax
mov al,11h ; 送出ICW1
out 20h,al
jmp short $+2 ; 延遲
mov al,<起始位址> ; 送出ICW2 (原值08h)
out 21h,al
jmp short $+2
mov al,04h ; 送出ICW3
out 21h,al
jmp short $+2
mov al,01h ; 送出ICW4
out 21h,al
jmp short $+2
pop ax
out 21h,al ; 設回原來的IMR值
(三)AT第二個8259
in al,0A1h ; 先取得並記錄原來的IMR值
push ax
mov al,11h ; 送出ICW1
out 0A0h,al
jmp short $+2 ; 延遲
mov al,<起始位址> ; 送出ICW2 (原值70h)
out 0A1h,al
jmp short $+2
mov al,02h ; 送出ICW3
out 0A1h,al
jmp short $+2
mov al,01h ; 送出ICW4
out 0A1h,al
jmp short $+2
pop ax
out 0A1h,al ; 設回原來的IMR值
在改變8259岔斷起始位址的初始化過程中,必須記得使用CLI命令將
岔斷關掉,而在一切均妥當或復原後再用STI命令啟用岔斷。注意程式結
束前(指轉交給受保護程式前)必須設回原來的岔斷起始位址,該值可以
參見上面的ICW2後面的註解。
由於一般的I/O Port命令較容易被解開,因此建議所有有關I/O Port
動作的命令,最好將之分散到保護程式各處。例如上面的8259初始化命令,
最好能再與其他命令(特別是其他I/O Port的命令)交叉相混合,如此不
但中間JMP SHORT $+2的延遲命令可以省略,也較不容易被追蹤者解析出
來。若再使用下一章會提到指令隱藏技術,則保護的成效將會更好。
技術六 利用8259 IMR值遮斷鍵盤岔斷
利用8259 IMR值來遮斷鍵盤岔斷是一種相當普遍的作法,已不具保護
的作用了。但它能確實有效地防止鍵盤岔斷的發生,因此運用也很廣。以
下遮斷鍵盤岔斷的方式:
in al,21h
or al,02h
out 21h,al
還原的方式為:
in al,21h
and al,0FDh
out 21h,al
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
-------------------------------------------------------------- 90-ASSEMBLY -
Msg : 67 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 19:49:00
To : All
Subj : 鍵盤4
-----------------------------------------------------------------------------
技術七 不送出EOI以停止鍵盤岔斷
PC的鍵盤岔斷處理程式結束前,必須以下列方式送出一個EOI命令給
第一個8259,否則下個鍵盤岔斷將無法產生:
mov al,20h
out 20h,al
如果我們改掉鍵盤岔斷處理程式,使之在結束前不送出EOI命令,如此亦
有禁止鍵盤岔斷的功用。以下為該鍵盤岔斷處理程式:
NoEOIInt9h PROC
; 不送出EOI的鍵盤岔斷處理程式
push ax
in al,60h ; 讀取鍵盤送來資料
pop ax
iret
NoEOIInt9h ENDP
但是如何使鍵盤自動產生一岔斷,使得這個岔斷處理程式被執行呢?只要
隨便下個鍵盤會回送資料的命令即可,例如8042回音命令:
cli
<<取得並暫存原鍵盤岔斷處理程式位址>>
<<設定新的鍵盤岔斷處理程式>>
call Echo8042 ; 送出回音命令,其他有回送資料之命令亦可
sti
<<保護程式其他處理,途中會產生一鍵盤岔斷>>
mov al,20h ; 送出EOI結束鍵盤岔斷
out 20h,al
以上是AT的作法。XT上並非使用8042,因此必須利用8255來處理。以下為
XT不送出EOI的鍵盤岔斷處理程式(註:下述兩程式係直接延用XT BIOS之
部份程式):
NoEOIInt9h PROC
; XT不送出EOI的鍵盤岔斷處理程式
push ax
in al,60h ; 讀取鍵盤送來資料
push ax
in al,61h ; 清除本次送來之鍵盤資料
mov ah,al ; (同時亦禁能)
or al,80h
out 61h,al
xchg al,ah ; 再度啟用鍵盤
out 61h,al
pop ax
iret
NoEOIInt9h ENDP
至於使XT鍵盤自動產生一岔斷的方式為:
in al,61h ; 將鍵盤時基降為低電位
and al,0BFh
out 61h,al
mov cx,10582 ; 延遲20ms (8088 CPU下)
WaitInt9h: loop WaitInt9h
or al,40h ; 恢復鍵盤時基
out 61h,al ; (此時將產生鍵盤重置訊號)
技術八 破壞或截斷鍵盤岔斷處理程式或輸入程式
鍵盤的岔斷程式包括INT 9h的硬體岔斷處理程式,和INT 16h的資料
輸入程式。藉由對這兩種岔斷程式的破壞或截斷,均有助於中斷鍵盤與使
用者之間的連繫。以下為幾種破壞或截斷岔斷處理程式的方法,這些方法
也適用於其他的岔斷處理程式。
1.直接破壞岔斷向量表,這是一種相當簡單卻又頗實用的方法。你可以單
純地破壞岔斷向量表,而在稍後再將之還原回來,或是拿岔斷向量表做
為變數存放資料,甚至將岔斷向量表做為程式執行的地方。愈是有意義、
混亂、且不斷地更動岔斷向量表的值,保護程式愈難以破解(註:以後
所提的資料或程式破壞,均指此一方式,將不再多做說明)。鍵盤硬體
岔斷INT 9h的岔斷向量在位址0:24h處,而鍵盤資料輸入岔斷INT 16h的
岔斷向量則在位址0:58h處。
2.取得原岔斷處理程式的向量位址後,破壞原岔斷處理程式碼。破壞的方
式可參考前項之說明,但必須先測試該位址的程式內容是否為僅讀,因
為該岔斷處理程式很有可能是在ROM區。如此,即使有任何其他除錯程
式或常駐程式將被破壞的岔斷向量還原,也會因原岔斷處理程式已遭受
破壞而無法正常執行,進而達到反追蹤的目的。
3.改寫鍵盤岔斷處理程式及鍵盤輸入岔斷處理程式。這種方式較適合於需
要輸入密碼,而又想避免被岔斷追蹤的情況。由於這類程式,大部份的
BIOS程式討論的書籍中均有列出,因此在此處便不多做說明。但記得在
改寫時,必須考慮執行密碼輸入時可能被岔斷追蹤的狀況,以便加以反
制。例如採用非正規的鍵盤雙斷開碼格式、破壞追蹤環境等,讓追蹤程
式即使岔斷成功,亦無法正常執行。
技術九 破壞、修改或檢查鍵盤緩衝區的指標與資料
當鍵盤有資料輸入時,均會更動鍵盤緩衝區的指標值,以及緩衝區內
的資料。因此在岔斷禁能的情況下,若這部份的內容有所更動,我們便可
判定有其他追蹤程式的執行。當然,我們也可以破壞這些指標值內容,以
防止追蹤程式岔斷後的正常執行。
1.檢查鍵盤緩衝區內容或輸入指標值是否更動。鍵盤緩衝區輸入指標在位
址0:41Ah~041Dh處,鍵盤緩衝區則在0:41Eh~0:43Dh處(由鍵盤緩衝
區位置指標決定),共32 byte。
2.破壞鍵盤資料緩衝區之輸入資料指標。
3.更改或破壞鍵盤資料緩衝區位置指標。鍵盤資料緩衝區位置指標在0:480h
~0:483h處,初值分別為1Eh和3Eh。
關於鍵盤資料緩衝區和各指標的關係,請參閱其他相關書籍。
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
--------------------------------------------------------------- 90-ASSEMBLY -
Msg : 68 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 19:49:00
To : All
Subj : 8042資料
-----------------------------------------------------------------------------
(二)8042
8042為AT使用的鍵盤控制器,內部有一個狀態暫存器,供外界檢測鍵
盤狀態;一個輸出埠和一個輸入埠,用來做為與外界的控制訊號使用;一
個輸入緩衝器和一個輸出緩衝器,用來存放與外界的界面資料,包括命令
和資料等。以下為這些元件的意義。
1.狀態暫存器
位元7 = 同位錯誤
位元6 = 接收逾時錯誤
位元5 = 傳送逾時錯誤
位元4 = 鍵盤啟用開關,0表禁能,1表允能
位元3 = 命令/資料指示位元,0表資料,1表命令
位元2 = 系統旗標,由外界設定
位元1 = 輸入緩衝器已滿,但尚未被8042讀走
位元0 = 輸出緩衝器已滿,但尚未被外界讀走
說明:狀態暫存器為一僅讀暫存器,各位元反應了鍵盤的某項狀態。例如
8042所使用的同位位元為奇同位,因此如果取得的鍵盤資料偵測為
偶同位的話,位元7的值便會設立成1,以便反應出同位錯誤。位元
3的值由線路所控制,反應出輸入緩衝器內的資料型態(即命令或
資料),以供8042決定處理的方式。在AT上,命令的寫入是經由I/O
Port 64h,而資料的寫入則經由I/O Port 60h。因此若輸入緩衝器
內的資料是經前者(Port 64h)寫入者,位元3的值便會設立成1,
若是經由後者(Port 60h)寫入者,則位元3的值便會設立成0。位
元2的值由外界所送入的命令所控制,請參閱後面所述之命令。位
元1和位元0是用來指示外界是否可對8042的緩衝器寫入或讀取資料。
當位元1為0時,外界才能再將資料送到8042的輸入緩衝器;當位元
0為1時,外界才能從8042的輸出緩衝器讀取資料。當不是上述的情
況時,外界程式便必須一直等待到上述的情況成立,否則不能對8042
的緩衝器進行I/O動作。
備註:位元4的值根據其他書籍所言為用來反應鍵盤抑制開關的狀態,但
經作者試用所有抑制鍵盤的命令均無法使之變成0。猜想可能這個
位元值係接至輸入埠位元7,但由於無法找到8042內部線路圖,因
此作者也無法確定。
2.輸入埠
位元7 = 鍵盤抑制開關,0為抑制,1為開啟
位元6 = 顯示器型態選擇,0為彩色,1為單色
位元5 = 0表已裝設製造時跳線
位元4 = 1表啟動系統電路板上的第二個256KB RAM
位元3~0 = 保留
說明:輸入埠的資料僅能讀取,且必須透過命令方式讀取。輸入埠各位元
的資訊均來自外界,其值因機器而異,因此便略而不提。位元7接
至一個5支腳的Jumper的第4腳,這支腳的訊號同時也控制著外界
RESET訊號的進入,若能改變這支腳的值成為0(也就是低電位),
則不但鍵盤不能作用,外界RESET也無法重新啟動電腦,必須整個
關機重開,只可惜這個Jumper是做死的,無法利用軟體來控制(作
者曾在某本書中看到這個位元值可以用軟體改變,但該書中所寫的
I/O Port為64h,似乎不太可能,再查閱各相關書籍及AT線路,已
確認該書內容是錯誤的)。
備註:由於8042輸入埠的值均依連接線路而定,並無法由軟體控制或改變,
因此大都無實用價值。作者曾在不同廠牌PC上讀取輸入埠的值(均
使用彩色螢幕),結果所得到的值由FFh、FBh、FCh、E7h等不定,
其中位元6的值並不正確,但查閱線路圖和各參考書籍均指出位元6
為接地時為彩色顯示器,再由AT BIOS程式追蹤發現顯示器單彩色
的判斷並非由這個位元來決定,因此這個輸入埠的值並不是很可靠,
最好不要使用。
3.輸出埠
位元7 = 鍵盤資料線
位元6 = 鍵盤時脈
位元5 = 輸入緩衝器已滿
位元4 = 輸出緩衝器已滿
位元3~2 = 保留
位元1 = A20位址線控制
位元0 = 系統重置
說明:輸出埠的資料是可以讀寫的,但必須透過命令方式讀寫(註:請參
閱D1h輸出埠寫入命令的說明)。鍵盤資料線傳送的便是由8042送
出的資料,如掃描碼或回應資料等,其傳送的數據結構和RS232相
似:
第1位元 = 開始位元
第2~9 = 資料,由低位元先送
第10 = 奇同位位元
第11 = 停止位元
而鍵盤時脈便是用來分辨鍵盤資料線各位元的時序的。因此這兩個
位元的值並不固定,端視讀取時的狀態而定。位元1是用來控制CPU
的A20位址線輸出,當其值為0時,將強迫A20位址線輸出為0,此時
系統將無法讀寫HMA上的資料,也就是位址FFFF:10h將存取到0000:0
位址。當其值為1時,A20位址線才由CPU的輸出決定。位元0用來重
置系統,當其值為0時,整個系統將會重置(也就是重新開機)。
由於位元0和位元1關係到整個系統的運作,因此最好不要加以隨意
更動。
4.輸出緩衝器
用來供外界讀取按鍵的掃描碼,或是鍵盤送出的回應資料。這個緩衝
器必須在狀態暫存器位元0值為1時才可以讀取。
5.輸入緩衝器
用來供外界輸入命令或資料使用,必須在狀態暫存器位元1值為0時才
可以寫入。
在AT上,8042狀態暫存器的讀取,必須經由I/O Port 64h,輸出緩衝
器的讀取,則經由I/O Port 60h。輸入緩衝器則分成60h和64h兩個Port,
分別用來輸入資料和命令。至於8042的輸入埠和輸出埠的值,則必須籍由
命令來取得或設定。送出命令給8042的方式,是先將命令寫入Port 64h,
再依需要將資料寫入Port 60h,如此命令便算送出完畢。之後8042根據命
令的處理結果,可能會回送一些資料回來,此時由Port 60h便可讀回這些
回應資料。以下為一些8042常用的命令:
20h = 讀取8042命令位元組。
60h = 寫入8042命令位元組,各位元意義如下:
位元7 = 保留
位元6 = 0表雙斷開碼,1表單斷開碼
位元5 = 1表不做同位檢查
位元4 = 1表抑制鍵盤
位元3 = 1表不理會鍵盤抑制
位元2 = 系統旗標
位元1 = 保留
位元0 = 啟用岔斷輸入(IRQ1)
位元6用來控制斷開碼的格式,也就是按鍵在放開時8042所送
出的資料格式。當值為0時,表示採用雙斷開碼格式,首先送
出F0h,然後後面跟著放開鍵的掃描碼。當值為1時,則採用單
斷開碼格式,也就是將掃描碼的位元7設成1,用以表示這是個
斷開碼。由於PC的BIOS程式均採用單斷開碼方式解譯8042送來
的資料,因此這個位元大都設成1。位元5的值較有爭議,在有
些書上寫明必須設成1,做為IBM PC的相容模式,但有的書上
則只說明這是用來檢查同位位元的而已。經作者實際在多種PC
上測試,結果這個位元的初值有的為0,有的為1,而且不管這
個位元的值設成0或1,系統均仍正常運作。因此作者建議還是
將之設成0,啟用同位檢查比較好些(原某書上標明IBM PC相
容模式應為錯誤的)。位元4用來抑制鍵盤,當值設成1時,將
使得時脈線路成為低電位,使得鍵盤界面失效。位元3根據各
相關書籍所述為使鍵盤的抑制功能失效,但經作者試過,即使
將這個位元設成1,各種鍵盤抑制命令仍然會抑制鍵盤的功能,
因此它的實際用途不明。位元2用來設定狀態暫存器位元2,也
就是系統旗標的值,這個旗標並沒什麼作用,一般在PC均設成
1。位元0用來控制是否採用岔斷輸入,一般均設成1。若將之
設成0,則必須使用Poll方式處理,較為麻煩。位元7和位元1
為保留值,可任意寫入0或1。
AAh = 自我測試,OK時輸出55h。注意這個命令會重設8042命令位元
組的值,因此在命令之後應重設8042命令位元組的值,否則鍵
盤功能將會被抑制而失去作用。
ABh = 介面測試,傳回結果:
00 = 正常
01 = 鍵盤時脈保持在低電位
02 = 鍵盤時脈保持在高電位
03 = 鍵盤資料線保持在低電位
04 = 鍵盤資料線保持在高電位
ACh = 診斷傾印(diagonstic dump),將16位元組的控制器記憶體、
輸入埠目前狀態、輸出埠目前狀態、以及控制器的程式狀態字
組送至系統。事實上,經作者在各種PC上測試的結果發現,實
際送出的資料差異性很大,有的完全不送資料,有的只送一個
byte,而有的一送便是十幾個byte。其資料的意義找遍各書籍
均未說明,因此此部份的說明也只好省略了。
ADh = 鍵盤失效(即將8042命令位元組之位元4設成1)。
AEh = 啟用鍵盤(即將8042命令位元組之位元4設成0)。
C0h = 讀取輸入埠,必須輸出緩衝器有空的時才可使用。
D0h = 讀取輸出埠,必須輸出緩衝器有空的時才可使用。
D1h = 寫入輸出埠。但是這個命令經作者實際測試過,並不會將給定
的資料寫入輸出埠。因此若要改變輸出埠的輸出值,應使用後
面會提到的Fxh命令,但這個命令只能改變輸出埠位元3~0的
值。
E0h = 讀取測試輸入埠,各位元值意義如下:
位元7~2 = 固定為0
位元1 = 鍵盤資料線
位元0 = 鍵盤時脈
其中位元0~1係由輸出埠位元7~6所回送的輸入資料,以做為
鍵盤自我測試時使用。同樣的,這個命令所讀出的值也因輸出
埠的狀態而異,請參閱輸出埠中的說明。
Fxh = 脈波輸出,x中4個位元分別對應到輸出埠的位元3~0,命令中
被選到的位元(以0選定)會有6us的低電位脈衝(也就是邏輯
值0)。請參閱輸出埠中的說明。
以下則為8042的系統命令。系統命令和一般命令的送出方式不同,必須經
由資料埠,也就是I/O Port 60h送出。8042收到後,除了EEh回音命令以
外,均會回送ACK訊號FAh(收到命令或資料均會回送)。以下為各系統命
令的意義:
EDh = 設定模式指示器,輸入值意義為:
位元7~3 = 固定為0
位元2 = Caps Lock指示器
位元1 = Numeric Lock指示器
位元0 = Scroll Lock指示器
設定之後,鍵盤上對應的LED便會亮起來。
EEh = 回音,鍵盤以EEh回應。
F3h = 設定鍵重複率及延遲,送入值意義為:
位元7 = 固定為0。
位元6~5 = 延遲參數,延遲(1+x)*250ms。
位元4~0 = 重複參數,假設位元2~0值為A,位元4~3值
為B,則重複週期為(8+A)*2^B*4.17ms。
F4h = 系統啟用,並清除輸出緩衝器。
F5h = 使用鍵盤預設值、清除輸出緩衝器,最後將系統失效,等待進
一步指令。若要再啟用必須使用系統命令F4h。
F6h = 使用鍵盤預設值設定重複率及延遲率,並清除輸出緩衝器。
FEh = 重送命令,鍵盤回送上次的輸出。
FFh = 重置命令,鍵盤接收後清除輸出緩衝器,並使用預設值,最後
開始自我測試,完畢回送AAh表正常,其他值表有誤(注意,
此命令會先送出ACK後再送出AAh)。
EFh~F2h、F7h~FDh = 保留命令,不運作(NOP)。但事實上經作者
測試之後,發現其中有些命令在某些機器上似乎有作用,有些
會使鍵盤失效,有些則會回送一些額外的值。由於這部份的資
訊無法確定,因此只能建議讀者不要隨便使用這些保留命令。
以下為一些鍵盤可能回送的資料或命令:
00h = 覆蓋(Overrun),當輸出緩衝器已滿而且又有輸出時,便會
送出此一資料。
AAh = 基本測試完成碼。
EEh = 回音回應。
F0h = 斷開碼第一位元組,用來指示某個鍵已被放開。斷開碼由兩個
位元組組成,第一位元組便是F0h,第二位元組則為鍵盤掃描
碼。
FAh = ACK訊號,用以回應系統命令使用。
FEh = 重送命令,當鍵盤接到一個無效或錯誤的輸入時,均會發出此
命令要求外界重送。
FDh = 診斷錯誤,當鍵盤週期性自我診斷時發現錯誤,便發出此資料。
注意在對8042進行命令控制時,必須將岔斷禁能,以免外界鍵盤輸入
岔斷影響正常之鍵盤命令傳送。
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
--------------------------------------------------------------- 90-ASSEMBLY -
Msg : 69 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 19:51:00
To : All
Subj : 8255資料
-----------------------------------------------------------------------------
(五)8255
8255為可程式化的週邊界面,只用在XT上,AT則已取消使用這個元件,
因此對於8255,我們只說明和XT相關且較重要的內容,至於詳細的內容,
請參閱其他相關書籍。8255具有24位元的I/O線,並區分為兩組:Group A
和Group B,分別佔用12位元。而這24位元的I/O線又可區分為三個輸出入
埠,其中Port A和Port B係由Group A和Group B中的8個位元I/O線所組成,
Port C則分為高四位元和低四位元,分別由Group A和Group B剩下的四位
元所組成。因此在規劃上,Port C可針對高四位元和低四位元分別程式化
成不同的輸出入方式和處理模式,Port A和Port B則不行。8255對於這24
位元I/O線的規劃方式,係經由其內部控制字組來完成的,這個控制字組
的意義如下:
1.模式定義格式
位元7 = 必須固定為1
位元6~5 = Group A模式,當位元6為1時,一律為模式2
位元4 = Port A輸出入方式,0表輸出,1表輸入
位元3 = Port C高四位元輸出入方式,0表輸出,1表輸入
位元2 = Group B模式
位元1 = Port B輸出入方式,0表輸出,1表輸入
位元0 = Port C低四位元輸出入方式,0表輸出,1表輸入
說明:XT的設定值為99h,即Port A、Port C為輸入,Port B為輸出,採
用的模式均為模式0。至於8255可規劃的三種模式名稱分別為:
模式0 = Basic Input/Output
模式1 = Strobed Input/Output
模式2 = Bi-Directional Bus
2.位元重置格式
位元7 = 必須固定為0
位元6~4 = 不使用
位元3~1 = 選擇的位元
位元0 = 設定值
說明:位元重置格式只用在模式1和模式2上,用來控制岔斷訊號產生的禁
能和允能。
在XT上,控制字組是在I/O Port 63h,而Port A、Port B、Port C則
分別在I/O Port 60h、61h、62h。其中Port A除了用來做為鍵盤資料的輸
入外,亦可做為DIP開關1的輸入值,這項差別由Port B位元7來控制。Port B
、Port C各位元的意義如下:
1.Port B
位元7 = 0表啟用鍵盤,允許鍵盤岔斷的發生,Port A將讀取鍵盤掃
描碼;1表鍵盤禁能,並清除鍵盤的輸入,Port A將讀取DIP
關閉1的值。
位元6 = 0表強迫鍵盤時基於低電位,1表鍵盤時基正常作用
位元5 = 0表啟用I/O通道檢查
位元4 = 0表啟用RAM同位檢查
位元3 = 控制錄音機馬達,0表運轉
位元2 = 值1表PC0讀取DIP開關2的位元0,0表讀取位元4
位元1 = 喇叭資料輸入控制
位元0 = 計時器Gate 2控制
說明:喇叭的資料輸入係接至計時器2,而計時器2的輸出與否由Gate 2控
制。在輸至喇叭前還有一個AND閘控制,因此欲使喇叭發聲,必須
使得位元1和位元0均成為1,此時喇叭便會以計時器2的輸出頻率發
聲。關於計時器的部份,請參閱8237的說明。
2.Port C
位元7 = 1表RAM同位檢查錯誤
位元6 = 1表I/O通道檢查錯誤
位元5 = 計時器2輸出訊號
位元4 = 錄音機資料輸入
位元3~0 = DIP開關2讀取值。
在AT上,8255已不再使用。原Port 60h改接至8042鍵盤控制器,仍做
為鍵盤資料讀取使用。Port 61h則改用ALS175來取代,並集結了Port B和
Port C中幾個較重要的位元。至於Port 62h和63h,則均捨棄不用了。以
下為AT中Port 61h各位元的意義,其中高4位元為僅讀位元:
位元7 = 1表RAM同位檢查錯誤
位元6 = 1表I/O通道檢查錯誤
位元5 = 計時器2輸出訊號
位元4 = RAM Reflesh訊號
位元3 = 1表啟用I/O通道檢查
位元2 = 1表啟用RAM同位檢查
位元1 = 喇叭資料輸入控制
位元0 = 計時器Gate 2控制
備註:以上關於8255各I/O位元在XT上的作用,作者參閱多本XT書籍後,
發現所著內容均有所出入。雖然作者針對相異的部份,儘量和BIOS
程式及線路圖搭配來做判斷,但因找不到XT機器做實際測試,因此
不敢保證內容完全正確,但至少錯誤的機會應已較少。
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
--------------------------------------------------------------- 90-ASSEMBLY -
Msg : 70 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 19:52:00
To : All
Subj : 8259資料
-----------------------------------------------------------------------------
(六)8259
8259為一種可程式化的優先序岔斷控制器,所有PC週邊硬體的岔斷均
必須透過這個元件來觸發所對應的岔斷處理程式。以下我們先說明8259的
硬體特性。8259共分成四個啟始命令字組ICW和三個操作命令字組OCW,前
者做為初始化時使用,後者則可供程式自行使用。8259初始化的過程為:
送出ICW1
送出ICW2
if 串接模式 then 送出ICW3
if 需要ICW4 then 送出ICW4
各啟始命令字組的意義為:
1.ICW1
位元7~5 = 岔斷向量位址(只用在MCS-80模式)
位元4 = 固定為1
位元3 = 0為邊緣觸發(edge trigger)
1為位準觸發(level trigger)
位元2 = 呼叫位址間隔(只用在MCS-80模式)
0為呼叫位址間隔8
1為呼叫位址間隔4
位元1 = 0為串接模式(cascade mode)
1為單一模式(single mode)
位元0 = 0不需要ICW4
1需要ICW4
說明:8259除了可供8088系列使用外,也可供MSC-80系列使用,因此當任
何位元若標明只使用在MSC-80模式時,PC上均不需使用。另外,由
於PC上使用的是8088系列的CPU,必須利用ICW4指定為8088模式,
因此本啟始命令的位元4、1均必須固定為1,位元7~5、2則可為0
可為1。至於採用何種觸發方式,則依電路特性而定,PC上通常採
用邊緣觸發,因此位元3也大致固定為0。比較有爭議的是位元1的
值。在舊型的PC/XT上,由於只使用一個8259做為岔斷控制用,因
此必須使用單一模式,故它的初值為13h。但到了PC/AT時,由於系
統功能加強,原來的一個8259已不敷使用,於是便擴增為兩個8259
串接在一起,因此這兩個8259便都必須使用初值11h。
2.ICW2
(1) MCS-80模式
位元7~0 = 岔斷向量位址
(2) 8088模式
位元7~3 = 岔斷向量位址
位元2~0 = 固定為0
說明:這個命令是用來設定硬體岔斷時,所要執行的岔斷向量啟始值。
PC/AT的第一個8259觸發的岔斷在08h~0Fh,因此初值為08h;第二
個8259觸發的岔斷在70h~77h,因此初值為70h。這些初值若在不
影響系統的岔斷功能下,是可以隨意改變的。
3.ICW3
(1) 主控制器(master device)
位元7~0 = 各位元分別表示IRQx是否有串接另一個8259控制器,
0表示沒有,1表示有。
(2) 次控制器(slave device)
位元7~3 = 固定為0
位元2~0 = 次控制器的識別碼。
說明:這個初始命令必須有兩個以上的8259串接在一起時才使用的,因此
PC/XT並不使用這個初始命令。至於PC/AT上的兩個8259,由於是串
接在IRQ2上的,因此主控制器(也就是第一個8259)的初值便必須
為04h。至於次控制器,由於必須配合所串接的IRQ來做編號,因此
次控制器的初值便必須為02h,否則無法正常工作。
4.ICW4
位元7~5 = 固定為0
位元4 = 0為非特別全巢狀模式
1為特別全巢狀模式
位元3~2 = 0x 不帶緩衝模式
10 主控制器帶緩衝模式
11 次控制器帶緩衝模式
位元1 = 0表非自動結束岔斷(EOI)
1表自動結束岔斷
位元0 = 0表MSC-80模式
1表8088模式
說明:特別全巢狀模式(special fully nested mode),主要用在大系
統中使用多個8259串接模式時,以便規劃不同的岔斷權限,詳細資
料請參閱相關書籍。通常我們均使用非特別全巢狀模式,也就是初
始化時以IRQ0優先權最高,IRQ7最低(這個優先權是可以改變的)。
而在某個岔斷發生處理時,優先權更高的岔斷允許再發生,以岔斷
目前正在處理的岔斷,而相同或較低優先權的岔斷則不允許發生。
至於是否要規劃成緩衝模式,必須視所連接系統之Data Bus線路而
定。對於是否使用自動結束岔斷,則由作業系統或岔斷處理程式的
設置程式來決定。一般使用自動結束岔斷對於岔斷處理程式會比較
方便些,不會因忘了送出EOI命令(參閱OCW2命令)而使得系統功
能停止或當機。但是它最大的缺點是,如果相同的IRQ岔斷一再發
生,而該岔斷程式又使用了STI命令允許岔斷發生時(為了讓更高
優先權的岔斷產生),則可能造成岔斷程式再被岔斷,導致重入問
題,以及岔斷順序更動等問題。因此在絕大部份的情況下,大都會
採用非自動岔斷結束,在PC上亦然。不過若使用非自動EOI的結束
方式時,岔斷處理程式在處理完岔斷後必須送出一個EOI命令給8259,
表示岔斷已處理完,否則8259便視為該岔斷未結束而不再產生下個
岔斷了。
備註:關於本初始命令的初值,由XT的BIOS查得為09h,由286 AT的BIOS
查得為01h,也就是前者採用緩衝模式,後者並不採用緩衝模式。
經查閱有關8259零件的手冊,其中說明緩衝模式主要用在具有BUS
驅動緩衝區的Data Bus,由8259的SP/EN訊號來控制緩衝區。當不
是緩衝模式時,這個訊號接腳在主控制器上必須接Vcc,而在次控
制器上則必須接地。再查閱86 XT和286、386 AT的線路圖,發現確
實XT的設計電路是使用緩衝模式,而286、386 AT的設計電路則為
非緩衝模式。因此在初始化時,必須依PC的種類而有不同的初始化
值(事實上,XT只有一個8259,在初始化過程方面便一定會有不太
一樣的地方,必須與AT分別處理),如果未與設計的電路做好匹配
的規劃,則有當機之虞(但並不一定會當機。據作者實際測試過,
在某些AT上將8259規劃成緩衝模式會當機,而在某些AT上則不管是
否規劃成緩衝模式卻仍都正常工作,這和主機電路板的線路設計有
關)。
以下為各操作命令字組的意義:
1.OCW1
位元7~0 = 分別表示IRQx是否啟動,0表示允能(enable),1表示
禁能(disable)。
說明:本命令也就是設定岔斷的罩遮值(IMR,Interrupt Mask Register)。
在使用時,通常先讀取原值後,再設置所要處理的岔斷所對應的位
元,以避免影響到其他岔斷。
2.OCW2
位元7~5 = 000 取消自動EOI時旋轉優先權模式
001 不特別指定IRQx方式結束岔斷
010 無作用
011 指定IRQx方式結束岔斷
100 設定自動EOI時旋轉優先權模式
101 不特別指定IRQx結束岔斷時旋轉優先權
110 設定優先權
111 指定IRQx結束岔斷時旋轉優先權
位元4~3 = 固定為0
位元2~0 = 指定的IRQx
說明:本命令是用來指定岔斷優先權的處理方式(請參閱相關書籍),以
及指示岔斷是否處理完畢。一般在PC上大都使用20h做不特別指定
IRQx方式來結束8259的岔斷。所謂不特別指定IRQx方式,指的是要
處理的IRQ編號並不由位元2~0來指定,而以目前已發生且優先權
最高的岔斷為準。
3.OCW3
位元7 = 固定為0
位元6~5 = 0x 無作用
10 取消特殊罩值(reset special mask)
11 設定特殊罩值(set special mask)
位元4 = 固定為0
位元3 = 固定為1
位元2 = 0表使用岔斷方式服務
1表不使用岔斷方式服務(poll command)
位元1~0 = 0x 無作用
10 讀取岔斷需求暫存器(IRR)
11 讀取內部服務暫存器(ISR)
說明:特殊罩值功能,主要是提供給需要任意改變岔斷的禁能、允能,而
又不希望因未送出EOI命令,而導致其他較低優先權的岔斷無法發
生的程式使用。當設定了特殊罩值後,則每次在OCW1重設罩值時,
均會將所有未被罩遮掉的IRQ重新啟用。IRR及ISR這兩個暫存器的
值可用來辨別各岔斷的產生與否。IRR(Interrupt Request
Register)記錄了硬體已產生岔斷需求,但8259尚未發出岔斷訊號
或CPU尚未回應確認訊號的岔斷;ISR(Interrupt Service Register)
則記錄了CPU已接收到岔斷訊號但處理程式尚未回應EOI命令的岔斷。
當要讀取這兩個暫存器值時,首先必須送出OCW3指定所要讀取的暫
存器,然後再由相同的輸出入埠將之讀取。
備註:不使用岔斷服務的方式(poll command),依8259之零件說明為RD
訊號會讀取Priority Level值,其值意義如下:
位元7 = 1表有岔斷發生
位元6~3 = 保留
位元2~0 = 岔斷發生的編號
又說明Poll Command是使用在8259的岔斷輸出訊號不使用,或CPU
線路已將岔斷訊號輸入禁能的情況。據作者實際測試結果,在PC上
將OCW3修改成Poll Command形態,並不影響到原岔斷的執行,讀取
而得的值也並非Priority Level的值。至於為何如此,作者遍尋相
關書籍,也問過許多硬體設計從業人員,竟找不到答案。作者猜測
可能是因PC CPU仍然接收並使用8259的岔斷輸出訊號,使得8259的
岔斷確認訊號並非由Poll Command的RD訊號確認所致,至於真正原
因,則不得而知了。
當8259重新初始化後,IMR的值均會重設為00h(也就是允許所有的岔
斷產生),並取消特殊罩值功能。因此當我們要重新初始化8259時,必須
記錄原來的IMR值,並在初始化後將之設回,以免初始化後某些原已被禁
能的岔斷再次產生而發生問題。當然,初始化後視情況也必須重新設定
OCW3的值。
上述所有命令字組在PC上均透過I/O Port 20h、21h(第一個8259)
和A0h、A1h(第二個8259)來讀寫。I/O Port 20h和A0h做為ICW1、OCW2
和OCW3命令的輸入,以及IRR、ISR暫存器值的輸出。I/O Port 21h和A1h
則做為ICW2、ICW3、ICW4和OCW1命令的輸入,以及IMR暫存器值的輸出。
至於8259是如何去分辨送來的是那個命令字組,這倒不必我們費心,因為
這些命令字組中大都已安排好某些位元均固定為0或1。由這些固定位元,
8259便能輕易地辨別出所輸入的命令種類。以下是目前在PC/AT中兩個8259
所處理的16個硬體岔斷內容:
┌ IRQ0 計時岔斷
│ IRQ1 鍵盤岔斷
│ IRQ2 串接第二個8259
第一個8259 ─┤ IRQ3 次串列通訊埠(COM2)
│ IRQ4 主串列通訊埠(COM1)
│ IRQ5 印表機岔斷(LPT2)
│ IRQ6 軟碟岔斷
└ IRQ7 印表機岔斷(LPT1)
┌ IRQ0 即時時脈岔斷
│ IRQ1 保留
│ IRQ2 保留
第二個8259 ─┤ IRQ3 保留
│ IRQ4 保留
│ IRQ5 數學處理單元岔斷
│ IRQ6 硬碟岔斷
└ IRQ7 保留
以下為各岔斷在本附錄中所對應的硬體說明:
計時岔斷 = 8253、8254
鍵盤岔斷 = 8042、8255
即時時脈岔斷 = 146818
其餘之硬體岔斷由於和本書內容無關,因此不予列入。
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
--------------------------------------------------------------- 90-ASSEMBLY -
Msg : 71 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 20:00:00
To : All
Subj : 8253/8254資料
-----------------------------------------------------------------------------
(四)8253與8254
8253和8254均為PC使用之計時器,兩者除了外接的頻率限制不同外(
前者最多只能接2MHz,後者可接至8MHz,8254-2更可接至10MHz),其餘
部份均相容。但以PC計時器外接頻率才1.19MHz來看,兩者在使用上並沒
有什麼差別,因此以下之計時器,我們均以8253來稱呼。
8253具有三個16位元的計數器,可分別加以規劃。每個計數器均具有
一個輸入的頻率、一個控制閘(GATE)和一個輸出端,其中控制閘便是用
來控制輸出端是否輸出結果。以下為PC對於這三個16位元計數器的佈線方
式及作用:
計數器0
作用 = 系統計時器
輸入頻率 = 1,193,180Hz
GATE0 = 接至+5V
輸出 = 第一個8259之IRQ0
計數器1
作用 = DRAM更新要求產生器
輸入頻率 = 1,193,180Hz
GATE1 = 接至+5V
輸出 = 更新要求週期
計數器2
作用 = 喇叭音調頻率
輸入頻率 = 1,193,180Hz
GATE2 = 接至Port 61h位元0
輸出 = 喇叭
由上面的資料我們可以知道,在PC上,除了GATE2(也就是Port 61h
的位元0)可以控制計數器2是否有輸出外(控制喇叭是否發聲),其餘兩
個計數器我們均無法禁止其計數結果的輸出,頂多是更改其輸出頻率和輸
出波形而已。對於三個計數器的輸出規劃及計數值讀寫,首先必須寫出控
制字組到控制暫存器中,這個暫存器在PC上是經由Port 43h寫入的,之後
再分別由Port 40h~42h讀寫計數器0~2的值。控制字組的格式為:
位元7~6 = 計數器選擇(0~2)
位元5~4 = 操作方式
00 = Latch住目前的計數值
01 = 讀寫計數值的高位元組
10 = 讀寫計數值的低位元組
11 = 依次讀寫計數值的低、高位元組
位元3~1 = 模式,各值意義為
000 - 模式0
001 - 模式1
x10 - 模式2
x11 - 模式3
100 - 模式4
101 - 模式5
位元0 = 0表二進制計數,1表BCD制計數
以下為各輸出模式的意義:
1.模式0(Interrupt on Terminal Count)
計數時輸出為Low,當計數完畢後,輸出昇至High,然後重新計數,
並將輸出再還原為Low。
2.模式1(Programmable One-Shot)
當GATE由Low昇成High時開始計數,計數時輸出為Low,當計數完畢後,
輸出昇至High並結束計數。
3.模式2(Rate Generator)
當GATE為High時開始計數,計數時輸出為High,當計數完畢後,輸出
降為Low一個Clock後升為High,然後繼續重新計數。
4.模式3(Square Wave Generator)
當GATE為High時開始計數,且以2遞減,當計數完畢後,輸出高低互
變,並繼續重新計數。
5.模式4(Software Triggerd Strobe)
計數時輸出為High,當計數完畢後,輸出降為Low一個Clock後升為
High,並停止計數。若GATE為Low時停止計數。
6.模式5(Hardware Triggerd Strobe)
當GATE由Low昇成High時開始計數,計數時輸出為High,當計數完畢
後,輸出降為Low一個Clock後升為High,並停止計數。
由於在PC上,各計數器之用途及外接線路均已定死,因此計數器0必
須採用模式3;計數器1必須採用模式2;計數器2則必須採用模式3,否則
輸出之波形將無法與線路配合,而產生奇怪的現象。以下,作者再進一步
介紹各計數器的計數值在PC上的規劃方式:
1.計數器0
計數器0在PC上是做為時序之控制,以18.2Hz定頻觸發INT 8h。其初
值為0,也就是每計數65536岔斷一次INT 8h,因此1,193,180/65536=
18.2Hz。通常這個計數值是不加以更動的,以免影響到系統時間的運
作,但是若欲做為短時間定頻岔斷之特殊運用時,更動也是允許的。
不過相同功能也可以運用146818(INT 70h)來完成,因此更改計數
器0的計數值便不是那麼的需要。以下為本計數器的計數值寫入方式:
out 43h,36h
out 40h,計數值低位元組
out 40h,計數值高位元組
2.計數器1
計數器1在PC上是做為DRAM定時更新使用,在XT上是接到8237 DMA通
道0上,但在AT上已不再使用DMA式更新了。這個計數器的初值為18,
也就是每隔15us更新DRAM一次。由於DRAM的更新頻率對於程式運用上
較無關,因此這個計數器的計數值通常我們不會加以改變。以下為本
計數器的計數值寫入方式:
out 43h,74h
out 41h,計數值低位元組
out 41h,計數值高位元組
3.計數器2
計數器2在PC上是用來控制喇叭發聲的頻率,應寫入的計數值為
1,193,180/頻率。以下為本計數器的計數值寫入方式:
out 43h,0B6h
out 42h,計數值低位元組
out 42h,計數值高位元組
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
-------------------------------------------------------------- 90-ASSEMBLY -
Msg : 72 of 72
From : Chi'u I-Nan 90:1013/622 16 Mar 95 20:17:00
To : All
Subj : 鍵盤補遺
----------------------------------------------------------------------------
列完了一堆資料後,順便講講前述資料的運用方式.
在90-C區中曾有人問到如何產生某個按鍵,而回信
的內容大都指明使用int 16h的功能來完成. 雖然
大部份的情況下,這種作法是可以滿足的,但對於
那些特殊的按鍵(指不輸入到鍵盤緩衝區的按鍵),
或是截取int 9h程式的熱鍵,int 16h便無法完成此
一需求,只能控制8042來完成. 作法如下:
1.首先要知道按鍵的掃描碼,假設為a.
2.執行cli,避免岔斷產生
3.讀取8042命令位元組值並暫存.
4.設定8042命令位元組的值為a.
5.再次讀取8042命令位元組值.
6.設回原8042命令位元組值
7.使用8042系統重送命令,但不要讀取回送值.
8.執行sti,稍延遲一下. 此時因8042會送出值a,因此
會岔斷int 9h,於是便相當於按下了掃描碼a的按鍵.
9.重複步驟2-8,但送出的掃描碼改成 a or 80h,表示這個
鍵放開.
利用上述的方式可以產生任何你要的按鍵. 如果是組合
鍵,例如左Shift+右Shift,則分別產生按下鍵,最後再分別送出
兩個鍵的放開鍵便可以了. 道理很簡單,因為int 9h判斷按
鍵是以port 60h的值(也就是鍵盤掃描碼)為準, 利用更改
port 60h回傳值,並產生int 9h的岔斷,自然便能夠模擬鍵盤
按鍵的發生. 至於實作方式,就看你自己了...
* 青衫詩客 -- 小邱 *
-+- Via 中文銀版快信 V2.28C
+ Origin: 檔案貨櫃, 歡迎您來挖寶, 28800 BPS, 04-230-2080; (90:1013/622)
--- Via Offline Auto BBS Email Post
--
自由的風,吹得心醉.........
--
※ 發信站: 批踢踢實業坊(ptt.twbbs.org)
◆ From: Rick.m5.ntu.edu