實驗九:根據材料程式設計
實驗任務一
要求:補全程式 t1.asm,完成在螢幕上輸出記憶體單元中的十進位制兩位數。
1 ;t1.asm 2 ; 在螢幕上輸出記憶體單元中的十進位制兩位數 3 assume cs:code, ds:data 4 data segment 5 db 12 6 db ?,? ; 前一個位元組用於儲存商,後一個位元組用於儲存餘數 7 data ends 8 code segment 9 start: 10 ×××× 11 ×××× ; 補全指令,使得ds <-- data段地址12 13 mov ah,0 14 mov al,ds:[0] ; ax <-- data段位元組單元的被除數12 15 mov bl,10 16 div bl 17 mov ××,al ; 補全程式碼,讓商儲存到data段註釋中指定的單元 18 mov ××,ah ; 補全程式碼,讓餘數儲存到data段註釋中指定的單元 19 20 mov ah,2 21 mov dl,×× ; 補全程式碼,使得dl <-- data段中儲存的商的位元組單元數值22 ×××× ; 補全程式碼,使得dl中的數值轉換為數字字元 23 int 21h 24 25 mov ah,2 26 mov dl,×× ; 補全程式碼,使得dl <-- data段中儲存餘數的位元組單元數值 27 ×××× ; 補全程式碼,使得dl中的數值轉換為數字字元 28 int 21h 29 30 mov ax,4c00h 31 int 21h 32 code ends 33 end start
補充好的程式碼為:
執行結果:
小結:
此題要求輸出一個十進位制兩位數,以目前所學知識還不能一次性列印2個甚至多個字元,只能一個一個的分別獲取該數字的個位和十位,然後依據ASCLL碼轉換為對應的字元進行輸出。而關鍵就在於如何獲取個位和十位數字,這裡我們採用了除法(div)指令來達到這個目的。
讓10除兩位數,得到的商即是該兩位數的十位數字,得到的餘數即是該兩位數的個位數字。
實驗任務二
要求:補全程式 t2.asm,完成在螢幕上輸出 data 段定義的 5 個十進位制兩位數,資料和資料之間以空格間隔。
1 ;t2.asm 2 assume cs:code, ds:data 3 data segment 4 db 12,35,96,55,67 5 data ends 6 code segment 7 start: 8 ; 補全程式,參考t1.asm,綜合應用以下知識完成: 9 ; (1) loop指令、記憶體單元地址的靈活表示 10 ; (2) div指令, 數字→數字字元的轉換 11 ; (3) int 21h的2號子功能,完成單個字元輸出的方法,即: 12 ; mov ah,2 13 ; mov dl,待輸出字元或其ASCⅡ碼 14 ; int 21h 15 ; (4) 資料和資料之間以空格間隔的實現: 使用(3)輸出空格字元 16 17 mov ax,4c00h 18 int 21h 19 code ends 20 end start
補充好的程式碼為:
執行結果:
小結:
此題可認為是任務一的進階,需要輸出的數字更多了,並且增加了輸出空格的要求。不過也不困難,設計一個單層迴圈即可解決。
實驗任務三
要求:根據材料程式設計,在螢幕中間分別顯示綠色、綠底紅色、白底藍色的字串“welcome to masm!”。
材料(摘要):
編寫好的程式碼為:
執行結果:
小結:
此題做出來也許並不難,難的是追求以一種更簡潔的方式來完成任務。這是我目前想到的比較簡潔的方法,採用了兩層巢狀迴圈。
大體思路:
外層迴圈是bx在不同行之間切換,內層迴圈是si在指定行的某一位置開始依次移動並輸出相應字元。
遇到的困難:
為了把data段的字元傳送到視訊記憶體中,還需要一個指標在這些字元間移動來傳遞字元,初期想讓si身兼兩職,讓si也來充當這個角色,但是發現,視訊記憶體中是用2個位元組來表示一個字元的,即視訊記憶體中的指標是遞增2的,而data段中的指標只需要遞增1,兩者不相容,所以。。。si還是專心當好它視訊記憶體指標的職能吧,我另找了di來作為data段的指標。可是問題又來了,雖然字元傳送的問題是解決了,但是每行字元的屬性都不一樣,我似乎還需要一個指標在這些屬性值間遊走來傳遞屬性值,可是已經沒有額外的指標暫存器可用了。為了最大化利用已有的指標暫存器,只能從尋找規律入手了。發現控制外層迴圈次數的cx是遞減1的,而我們需要的屬性值指標是遞增1的,二者的和應當不變。於是便有了上面的解法。我還是採用di暫存器,因為一行字元的屬性是一樣的,可以在內層迴圈開始之前就將這一行的屬性值設定好,這樣在進入內迴圈的時候di也就被空了出來。