x86匯編利用int 16h中斷實現偽多線程輸入


x86匯編利用int 16h中斷實現偽多線程輸入

我們都知道,如果想讓一個程序,同時又干這個,又干那個,最好的辦法就是多線程。這個在高級語言里面已經用爛了。

但是,DOS是只有單線程的。我如果想讓程序在運行的同時,又能接受我鍵盤的輸入,那要怎么辦呢?

例如,我有一個DOS彩票開獎軟件。屏幕上有十個數字在滾動,當我按下空格鍵的時候,它會停止跳動,按別的鍵無效。那么要怎么操作?

首先,接收輸入最常用的是int 21h中斷里的7號功能調用。但是它是一個中斷輸入,也就是為了接收這個輸入,我的程序就暫停在這兒不動了。但是我彩票開獎數字一直在滾動,那要怎么辦啊?不能說我按一下它滾動一下吧。

於是請來了今天的主角,int16h中斷。

首先我們看看int 16h中斷有哪些功能?

BIOS提供了int 16h中斷例程供程序員調用,且功能是從軟件層面上實現鍵盤I/O功能中斷調用,功能號為0,1,2,並且必須把功能號放在ah寄存器中。

0號功能調用

mov ah,01h
int 16h

功能:從鍵盤讀入字符送進al寄存器,執行時,等待鍵盤輸入,一旦輸入,輸入字符的ASCII碼放入al中。若al為0,則ah為輸入的擴展碼。但是,如果鍵盤緩沖區已有數據,則會讀取鍵盤緩沖區數據,並且將其從緩沖區中刪除。

0號功能的工作流程為:

  1. 檢測鍵盤緩沖區是否有數據;
  2. 沒有則回到1;
  3. 讀取緩沖區第一個字單元中的鍵盤輸入;
  4. 將讀取的掃描碼送入ah,ASCII碼送入al;
  5. 將已讀取的鍵盤輸入從緩沖區中刪除

1號功能調用

mov ah,01h
int 16h

功能:用於查詢鍵盤緩沖區,對鍵盤掃描但是不等待(也就是不會中斷程序),並設置標志寄存器中的ZF。如果有鍵盤輸入(即鍵盤緩沖區不空),則ZF=0,AL存放的是當前輸入的ASCII碼,AH存放的是輸入字符的擴展碼。若無鍵盤操作,則標志位ZF=1。

2號功能調用

mov ah,02h
int 16h

功能:檢查鍵盤上各特殊功能鍵的狀態。執行后,各種特殊功能鍵的狀態放入AL寄存器中,這個狀態字記錄在內存0040H:0017H單元中,若對應位為“1”,表示該鍵狀態為“ON”,處於按下狀態;若對應位為“0”,表示該鍵狀態為“OFF”,處於斷開狀態。

mov ah,02h
int 16h					;從鍵盤輸入
and al,04h				;判斷是否按下Ctrl
jnz Ctrl_on

Ctrl_on:
	......

了解了以上功能,我們來看如何實現偽多線程輸入。

mainLoop:
	mov ah,01h		;檢測是否有輸入
	int 16h
	jz offKey		;jz是當zf=1時跳轉,也就是無輸入
	;如果有輸入,沒有跳轉
	mov ah,00h		;那么鍵盤緩沖區已不為空
	int 16h
	cmp al,32		;和空格的ASCII碼比較
	je spaceProc
	...
spaceProc:
	...	
offKey:
	...

這個框架簡單易懂,先從mainLoop中判斷是否有輸入:

  • 如果沒有任何輸入,則直接執行offKey中的代碼內容;
  • 如果有輸入,會調用0號功能對鍵盤緩沖區進行檢索。因為我們已知它有輸入(鍵盤緩沖區不為空),所以不會中斷程序。
    • 如果鍵盤輸入為空格,就跳轉到spaceProc,否則再加別的代碼。
    • 當然,我們可以利用這個做很多事情,不只是判斷空格。

這樣,利用int 16h中斷中0號功能和1號功能的聯動,我們實現了在只支持單線程的DOS中,實現了偽多線程的輸入判斷。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM