彙編語言:簡單的子程序設計
本文內容來源於王爽《彙編語言(第三版)》實驗10 編寫子程序
這次要求編寫三個子程序,所有思路提示在書中給出了,需要了解的同學可以到書中尋找相關提示(儘管網上有電子書,但我強烈建議同學們花錢買實體書,而且還不貴)
這些子程序的設計很簡單,寫關鍵代碼之前,要記得用堆棧保護寄存器即可。
下面給出具體實現的代碼,不要笑話我的中式英語,我只是受中華文化影響比較深……(其實就是懶得打中國字,而且英文還蹩腳)
第一個子程序——顯示字符串
設計思路:向80X25彩色字符模式顯示緩衝區(內存地址從B800:0000到B800:7FFF)直接寫入要顯示的內容即可,具體內容見王爽的《彙編語言(第三版)》中的實驗9補充材料。
;proc_name: show_str
;function: output a string with one color in a certain postion
;interface: (dh) = row(0~24),(dl) = column(0~79)
; (cl) = color, ds:si points to the first address of the string
;return: void
show_str: push ax
push bx
push cx
push dx
push es
push si
mov ax,0b800h
mov es,ax
;set row
mov al,160
mul dh
mov bx,ax
;set column
mov dh,0
add dx,dx
mov di,dx
;output the string
mov ah,cl
show_str_s: mov al,[si]
mov ch,0
mov cl,al
jcxz show_str_ok
mov es:[bx+di],ax
inc si
add di,2
jmp short show_str_s
show_str_ok: pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret
第二個子程序——解決除法溢出問題
由於除法指令div在某些情況下會出現溢出的狀況(比如:(ax) = 0ffffh, (bx) = 1,
DIV BL得到的商0ffffh,無法在寄存器al中存放)
因此,有必要自己寫一個子程序解決這一問題。書中給出瞭解決問題的公式,以及公式的證明,想知道的同學自己去翻書吧(我懶得打字了)
;proc_name: divdw
;function: Division operation(avoid overflow)
; the dividend is dword type and the divisor is word type
; the result is dword type, the remainder is word type.
;interface: (ax) = the low 16 bit of the dividend
; (dx) = the high 16 bit of the dividend
; (cx) = divisor(word type)
;return: (dx) = the high 16 bit of the result
; (ax) = the low 16 bit of the result
; (cx) = the remainder
divdw: push dx
push ax
mov bp,sp
mov dx,0
mov ax,[bp+2]
div cx
push ax
mov ax,[bp]
div cx
mov cx,dx
pop dx
add sp,4
ret
第三個子程序——數值顯示
思路:二進制轉成十進制,在轉換成數字字符,注意字符排列的順序。用除法指令div要用32位除以16位,得到的餘數序列要反轉過來,纔是真正要輸出的順序。爲此,我用堆棧實現反轉。最後,記得保護寄存器。
配合第二個子程序,即可以在屏幕上顯示數字了。
;proc_name: dtoc
;function: translate word type data into a decimal digit string which
; ends with 0
;interface: (ax) = data in word type
; ds:si points to the first address to the string
;return: void
dtoc: push ax
push bx
push cx
push dx
push si
mov bp,sp
mov bx,10
mov dx,0
dtoc_s: div bx
mov cx,dx
add cx,'0'
push cx
mov cx,ax
jcxz dtoc_ok
mov dx,0
jmp dtoc_s
dtoc_ok:
pop ax
mov [si],al
mov cx,bp
sub cx,sp
jcxz dtoc_out
inc si
loop dtoc_ok
dtoc_out:
mov al,0
mov [si+1],al
pop si
pop dx
pop cx
pop bx
pop ax
ret
完整程序舉例
程序一
功能:將12666以十進制形式打印在屏幕上
assume cs:code,ss:stack,ds:data
stack segment
db 256 dup(?)
stack ends
data segment
db 256 dup(?)
data ends
code segment
main: mov ax,12666
mov bx,data
mov ds,bx
mov si,0
call dtoc
mov dh,8
mov dl,3
mov cl,2
call show_str
mov ax,4c00h
int 21h
;---------------------------------
;proc_name: dtoc
;function: translate word type data into a decimal digit string which
; ends with 0
;interface: (ax) = data in word type
; ds:si points to the first address to the string
;return: void
dtoc: push ax
push bx
push cx
push dx
push si
mov bp,sp
mov bx,10
mov dx,0
dtoc_s: div bx
mov cx,dx
add cx,'0'
push cx
mov cx,ax
jcxz dtoc_ok
mov dx,0
jmp dtoc_s
dtoc_ok:
pop ax
mov [si],al
mov cx,bp
sub cx,sp
jcxz dtoc_out
inc si
loop dtoc_ok
dtoc_out:
mov al,0
mov [si+1],al
pop si
pop dx
pop cx
pop bx
pop ax
ret
;---------------------------------------------------
;proc_name: show_str
;function: output a string with one color in a certain postion
;interface: (dh) = row(0~24),(dl) = column(0~79)
; (cl) = color, ds:si points to the first address of the string
;return: void
show_str: push ax
push bx
push cx
push dx
push es
push si
mov ax,0b800h
mov es,ax
;set row
mov al,160
mul dh
mov bx,ax
;set column
mov dh,0
add dx,dx
mov di,dx
;output the string
mov ah,cl
show_str_s: mov al,[si]
mov ch,0
mov cl,al
jcxz show_str_ok
mov es:[bx+di],ax
inc si
add di,2
jmp short show_str_s
show_str_ok: pop si
pop es
pop dx
pop cx
pop bx
pop ax
ret
code ends
end main
程序二
見下篇博文(笑)
總結
這篇博文其實是對王爽的《彙編語言(第三版)》的一篇推廣文,這本書的確是一部初學者必讀的好書,完全可以自學,比我們學校老師講的好多了。
彙編語言程序設計這門課雖然結束了,但我的彙編之旅纔剛剛開始。說實話,在課上所學的東西連彙編的皮毛都沒有,什麼子程序傳參,堆棧傳參,中斷向量表,我都沒學會。現在我肚子裏的墨水全是靠自學王爽的這本書的。
現在還只是在8086實模式下編程,這是其他院校學過彙編這門課的大學生應該都掌握的,用中斷的方式寫點小程序,輸出寫彩色字符,做點動畫,弄點音樂,這些都只是皮毛。而目前的我,連這些皮毛的做不到。
總而言之,我會繼續深入學習彙編語言,和彙編語言談一場長久的戀愛。