實驗10 編寫子程序
這次實驗需要編寫三個子程序,通過它們來認識幾個常見的問題和掌握解決這些問題的方法。
1.顯示字符串
問題
子程序描述
提示
Solution
跟之前的文章的風格相似,都是用王爽老師原書中的描述,在完成第一個程序之前,需要稍微了解一下顯存相關的內容:匯編語言:實驗九 根據材料編程
了解了顯存相關的知識,可以動手操作操作了,題目需要將字符串顯示在特定的行列,如果學習過數據結構或者對二維數組較為了解,求解二維數組中R行C列的元素前面一共有多少個元素?一定知道這么一個計算方法:(R * nums + C),nums表示每一行元素的個數。
顯存內存的分布也可以類比成二維數組,每一行一共有 80 個元素,每個元素占用 2 個字節,那么每一行占用了80 * 2 = 160字節,求解R行C列前面占用的空間就可以得到表達式:(R * 160 + C * 2 ) 字節。
實現代碼
assume cs:code, ds:data
data segment
db 'Welcome to masm!',0
data ends
code segment
start:
mov dh, 10 ;行號 范圍 0 ~ 24
mov dl, 3 ;列號 范圍 0 ~ 79
mov cl, 2 ;顏色(取值范圍0 ~ 79)
mov ax, data
mov ds, ax
mov si, 0;ds偏移
mov di, 0;es偏移
mov bl, cl ;bl保存需要改變的顏色
mov ax, 0B800H
mov es, ax;顯存位置
mov al, dh
mov ah, 160
mul ah
add di, ax ;行空間
mov al, cl
mov ah, 2
mul ah
add di, ax ;列空間
call compare
mov ax, 4c00h
int 21h
compare:;調用子程序前的保存工作
push cx
push di
push si
show_str:
mov cl, ds:[si]
mov ch, 0H
jcxz ok ;循環結束
mov es:[di], cl
mov es:[di + 1], bl
add di, 2
inc si
jmp short show_str
ok:;調用完子程序之后的恢復工作
pop si
pop di
pop cx
ret
code ends
end start
運行
2.解決除法溢出的問題
問題
子問題描述
提示
Solution
問題主要用於解決除法溢出的問題。
程序不難,只是用於熟悉子程序結構、構建。
assume cs:code, ss:stack
stack segment
db 8 dup (0)
stack ends
code segment
start:
mov ax, stack
mov ss, ax
mov ax, 4240H ;被除數低位
mov dx, 000FH ;被除數高位
mov cx, 0AH ;除數
call divdw
mov ax, 4c00h
int 21H
divdw:
push ax ;將被除數低位壓棧
mov ax, dx ;將被除數高位傳入ax
mov dx, 0 ;進行高位除法
div cx ;ax / cx,公式中 H / N
mov bx, ax ;bx保存 int(H / N)
pop ax ;低數位出棧,此時dx中為rem(H / N),正好滿足 [ rem(H / N) * 65536 + L]
div cx ;(dx * 16 + ax) / cx
mov cx, dx
mov dx, bx
ret
code ends
end start
3.數值顯示
問題
子程序描述
提示
讀者對本題應該非常熟悉,在《C語言程序設計》課程中應該完成過“打印一個數字的每位數字”,這道題其實也是那個經典的while循環,按照王爽老師的解析還是可以很輕松地完成的哦。
assume cs:code, ss:stack
stack segment
db 10 dup (0)
stack ends
data segment
db 10 dup (0)
data ends
code segment
start:
mov ax, 12666
mov bx, data
mov ds, bx
mov bx, stack
mov ss, bx
mov dx, 0
mov si, 0;計數器,表示共有多少位
mov di, 10 ;充當除數
call dtoc
mov dh, 8
mov dl, 3
mov cl, 2
call show
dtoc:
mov cx, ax
jcxz change ;如果ax已經是零,循環結束,將數據轉移到ds:[x]
mov dx, 0
div di ;除10
push dx ;將余數壓棧
inc si ;計數器加一
jmp short dtoc
change:
mov cx, si
mov di, 0 ;充當ds偏移
getAns: ;從棧中彈出數據,並加上30H
jcxz ok ;數據彈出完畢
pop ax
add ax, 30H
mov [di], ax
inc di
dec cx
jmp getAns
ok:
ret
show:
mov si, 0;ds偏移
mov di, 0;es偏移
mov bl, cl ;bl保存需要改變的顏色
mov ax, 0B800H
mov es, ax;顯存位置
mov al, dh
mov ah, 160
mul ah
add di, ax ;行空間
mov al, cl
mov ah, 2
mul ah
add di, ax ;列空間
call compa
mov ax, 4c00h
int 21h
compa:;調用子程序前的保存工作
push cx
push di
push si
show_str:
mov cl, ds:[si]
mov ch, 0H
jcxz okk ;循環結束
mov es:[di], cl
mov es:[di + 1], bl
add di, 2
inc si
jmp short show_str
okk:;調用完子程序之后的恢復工作
pop si
pop di
pop cx
ret
code ends
end start