定時器時間資料轉換子程式分析 (轉)
定時器時間資料轉換子分析
進日,我在看一時鐘TSR程式,分析其中一個把資料區中的定時器資料轉換成HH:MM:SS時間格式的資料(ASCII)的程式片段時,既學到一點東西,又發現了一寫自己弄不明白的問題。現在我把自己學到的好東西寫出來與大家分享,同時向各路高手請教請教。
程式片段如下:(語言程式)
... (省略)
HMS 8 dup(':')
...
time proc
lea di,position ;(1) --行號
mov ax,0 ;(2)
mov ds,ax ;(3)
mov al,ds:[46eh] ;(4)
call clk1 ;(5)
mov ax,ds:[46ch] ;(6)
mov dx,0 ;(7)
mov bx,444h ;(8)
call clk0 ;(9)
mov ax,dx ;(10)
mov cx,3ch ;(11)
mul cx ;(12)
clk0:
add di,3 ;(13)
div bx ;(14)
clk1:
aam ;(15)
add ax,3030h ;(16)
xchg ah,al ;(17)
mov cs:[di],ax ;(18)
ret ;(19)
time endp
程式片段實現的原理是把BIOS的INT 1CH時鐘控制中斷在BIOS資料區建立的0040:006CH(低字) 和0040:006EH(高字)單元32位時間數字計數器中的數值用一種比較簡明的方式轉換成HH:MM:SS時間格式(為ASCII字元),再用另一顯示子程式把轉換好的字元傳顯示在螢幕上。
INT1CH中斷每55毫秒發生一次中斷,每發出一次中斷就把0040:006CH--0040:006EH的32位時間數字計數器中的內容加一,一天24小時,最大的計數值為001800B0H,達到最大值,INT1CH把這個計數器復位為0,然後重新計數,新的一天又開始。
我搞不明白的是為什麼計數器的最大值會是1800B0H(1573040),1573040*55/1000=86517.2(秒)而24小時是86400秒,計數器的值比實際值大。INT1CH每55毫秒中斷一次,也就是說1秒鐘中斷18.1818181818...(無數個18)次,若按每秒中斷18.2次的話,一天24小時計數器的數值應為1572480,比1573040少了560(為30.8秒) 。一個小時3600秒中斷次數為65520(以18.2計算),比65535(2的16次方為65536)少15次(不足一秒)。一天少360次,與前面少560次又不同。真令我費解。
現假設一個時間計數器的數值,分析上述程式片段的過程。假設[0040:006EH]=0017H,[0040:006EH]=1AA3H。程式片段的執行過程為:
{(1)->(4)}->{(15)->(19)}->{(6)->(8)}->{(13)->(19)}->{(10)->(19)}
(小括號中的數字為行號,大括號中的箭頭為順序指令序列,大括號外的箭頭為指令跳轉)
(1)->(3): DS=AX=0,DI=HMS的位移,HMS是用以轉換後的時間值(ASCII)的單元。
(4): MOV AL,DS:[46EH]即AL=17H
(5): CALL CLK1 ;CLK1
CLK1的執行過程如下: ((15)->(19),此時轉換小時值)
(15): AAM指令,乘法的ASCII調整指令,把AL中的值調整為非的BCD格式,即把AL除以0AH(10),商放在AH中,餘數放在AL中.執行後,AX=0203H.
(16): ADD AX,3030H 令AX=3233H,就是2和3的ASCII值.
(17): XCHG AH,AL 令AX=3332H.
(18): MOV CS:[DI],AX 把轉換後的數值(ASCII)存在HMS中.
(19): RET 返回. (返回執行第6條指令)
此時,HMS為 (高字) ':',':',':',':',':',':','3','2'(低字)
(6): MOV AX,DS:[46CH] AX=1AA3H
(7),(8): BX=444H,DX=0
(9): CALL CLK0 ;呼叫CLK0
CLK0的執行過程如下: ((13)->(19),此時轉換分鐘值)
(12): ADD DI,3 把DI加3,即指向HMS的指標加3.
(14): DIV BX 把1AA3H除以444H. 444H=1092,1092/18.2=60(秒).指令執行完後AX=06H(商),DX=10BH(餘數)
(15)...(19): 即執行CLK1,執行過程與以上描述相同,把AX=06H(分鐘)轉換成能顯示的ASCII值.(19)句 RET 返回到第(10)句.
此時,HMS為(高字) ':',':',':','6','0',':','3','2'(低字)
開始轉換秒數值:
(10),(11):AX=10BH,CX=3CH.(3CH=60)
(12): 10BH*3CH=3E94,AX=3E94H
(13)...(19): 即再次執行CLK0. (14) DIV BX ;3E94H/444H AX=0EH,DX=2DCH.第三次執行CLK1,把AX=0EH(14)轉換成可顯示的ASCII字元.過程同上.(19) RET 返回撥用TIME
子程式處.從(10)到(14) 267*60/1092=267/18.2,(10BH=267)意思是中斷267次相當於多少秒.
最後,HMS為(高字) '4','1',':','6','0',':','3','2'(低字),時間為23:06:14。
由上可以看出,高字[0040:006EH]為時間值,低字[0040:006CH]為一小時發生中斷次數65520次。上述的轉換過程已經很清楚了。0040:006EH-0040:006CH中,高字直接呼叫CLK1轉換成可視字元。低字除以444H(次/分)得分鐘數值(商),再呼叫CLK1轉換成可視字元。然後把餘數(不足一分鐘的中斷次數)乘3CH,再除以444H,即把餘數除以18.2(次/秒)得秒數值(商),最後一次呼叫CLK1轉換成可視字元。所轉換得字元存在HMS記憶體單元中。
子程式TIME的演算法是很易懂的,但INT1CH中斷的執行的過程本人還沒有不清楚,也沒有相應的參考文件,有幾個疑問還解不開,特向各位超級大蝦(龍蝦?)請教。謝謝!
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-990875/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle資料庫的SCN轉換成時間和時間轉換成SCNOracle資料庫
- 時間轉換
- 時間轉換成時間戳時間戳
- C 時間轉換時間戳時間戳
- C 時間戳轉換成時間時間戳
- 時間相減和時間轉換
- 將時間戳轉換為時間例項程式碼時間戳
- UTC格式時間轉換為當地時間程式碼
- 時間日期字串轉換為時間物件字串物件
- utc時間轉換成標準時間
- 將時間戳轉換為時間日期程式碼例項時間戳
- 時間日期和時間戳相互轉換程式碼例項時間戳
- [時間格式的轉換]
- Java之時間轉換Java
- java時間的轉換Java
- 轉換UTC時間格式
- 工具方法:時間轉換
- python中的時間轉換,秒級時間戳轉string,string轉時間Python時間戳
- ORACLE資料庫中SCN與時間的轉換Oracle資料庫
- 如何將時間字串轉換為時間物件字串物件
- javascript將時間物件轉換為時間戳JavaScript物件時間戳
- 時間戳與時間字串的多時區轉換時間戳字串
- Excel中時間戳轉換時間Excel時間戳
- JavaScript 轉換成UTC時間JavaScript
- JavaScript 時間日期格式轉換JavaScript
- Mysql 查詢時間轉換MySql
- c++時間形式轉換C++
- javascript時間戳和時間格式的相互轉換JavaScript時間戳
- Python秒轉換成時間(時分秒)Python
- MSSQL-從字串轉換日期和/或時間時,轉換失敗SQL字串
- FFmpeg轉碼音影片時間戳設定分析時間戳
- oracle時間間隔轉換函式Oracle函式
- Perl中本地時間和UNIX時間戳間相互轉換時間戳
- js將時間日期物件轉換為時間日期字元JS物件字元
- 本地時間與UTC(世界協調時間)的轉換
- Logstash 時間轉換(YYYY-MM-dd HH:mm:ss轉Unix時間)
- SQL Server資料庫中Date/Time 時間格式的轉換SQLServer資料庫
- 把時間戳之差轉換成時分秒格式時間戳