假設在.NET平台下要實現像下面這張圖的效果,我們可以很簡單地用幾行代碼來實現:
預設10個狀態值作為“跑馬燈”每一張圖片的輸入值,加上一個Timer控制項設定一個Interval值,在Elapased事件下寫輸出值的代碼並重新整理UI。當然,前提是有像8255單片機這樣的類比機與程式通訊。
但在彙編下要實現這樣的效果可真要費一番功夫。先說一下題目要求:
當開關K1 合上其餘斷開時,L1~L8從右至左逐個點亮直到開關狀態改變
當開關K1、K2 合上其餘斷開時,L1~L8從右至左成對逐次點亮直到開關狀態改變
當開關K1、K2、K3合上其餘斷開時,L1~L8從右至左以3個為一組逐次點亮直到開關狀態改變
……
開關K1~K8全部合上時停止
這裡需要注意的是每種狀態下點亮燈的個數,左移的效果可以用ROL指令來現實,過程中還要儲存左移後的值,還有當運行時改變開關狀態(2個燈增加到3個燈)時燈的效果也要隨著改變。
那天電腦硬體實驗花了我一下午才把這個搞出來,後來才發現運行時改變開關狀態的這個功能有錯誤,直接把CL的值賦給了AL,又把新開關狀態的值給覆蓋了。可惜,下課了,沒來得及改…
還有,是否有一款類比8255或其它單片機的軟體,以後直接在寢室裡做實驗得了,實驗室可以不去了
------------------------------------------
有時候在想,彙編這麼複雜,指令多(難記,不像進階語言的int、string類型好記)、寄存器限制(8b、16、32b)、IP指標常變(POP、PUSH)、現場保護…真多,這些問題不得不關注
大家知道JIT編譯器是把中繼語言編譯成相應處理器指令,而中繼語言(*.dll---.NET、*.class---Java)一般有10幾K上百K,寫個組譯工具一般不到5K,從大小層面上看JIT編譯器應該複雜多了。而且用進階語言編寫的程式在運行時都不只調用一個*.dll檔案,數量上又增加了一個複雜度。況且進階語言對代碼安全、堆棧保護、防止緩衝區溢位都有相當高的要求!
能寫出像.NET平台這樣的JIT確實是個牛人!
附:做該彙編實驗時的代碼,有興趣的可以瞧瞧,在這不做技術討論
DATA SEGMENT
CTRL DB 82H ;定義控制字
DATA ENDS
CODE SEGMENT
MAIN PROC FAR
ASSUME CS:CODE,DS:DATA
START;
PUSH DS
MOV AX,0
PUSH AX
MOV AX,DATA
MOV DS,AX
MOV DX,20BH ;8255的控制口地址
MOV AL,CTRL
OUT DX,AL
MOV DX,209H ;8255-B口地址,接收開關輸入訊號
IN AL,DX
MOV DX,20AH ;8255-C口地址,輸出AL值
OUT DX,AL
MOV BL,AL ;儲存開關輸入訊號,BL為左AL左移後的值
MOV CL,AL ;CL為執行L1前AL的值
L1:
MOV DX,209H
IN AL,DX
CMP AL,01H ;逐個與01H、03H…比較
JZ L2
CMP AL,03H
JZ L2
CMP AL,07H
JZ L2
CMP AL,0FH
JZ L2
CMP AL,1FH
JZ L2
CMP AL,3FH
JZ L2
CMP AL,7FH
JZ L2
CMP AL,0FFH
END1:RET ;當輸入為0FFH(1111 1111B)或其它值時退出
L2: ;控制二極體迴圈點亮
MOV AL,BL ;把上次左移後的AL值(存放在BL)送到AL
ROL AL,1 ;左移AL 1位
MOV DX,20AH
OUT DX,AL ;輸出移位後的值,效果就是二極體向左點亮了
MOV BL,AL
MOV AL,CL
PUSH BX ;把BX、CX值壓棧,儲存BL、CL的值
PUSH CX
MOV BX,0FFFFH ;外迴圈次數
LO: ;外迴圈
MOV CX,0FFFFH
LI: ;內迴圈
NOP
NOP
NOP
LOOP LI
SUB BX,1
JNZ LO
POP CX ;彈出CX值
POP BX ;彈出BX值
JMP L1
RET
MAIN ENDP
CODE ENDS
END START