設計子程式 子程式一:在指定的位置,用指定的顏色,顯示一個用0結束的字元串 舉例:在屏幕的8行3列,用綠色顯示data段中的字元串 assume cs:code data segment db 'Welcome to masm!',0 data ends code segment start: mo ...
設計子程式
子程式一:在指定的位置,用指定的顏色,顯示一個用0結束的字元串
舉例:在屏幕的8行3列,用綠色顯示data段中的字元串
assume cs:code data segment db 'Welcome to masm!',0 data ends code segment start: mov dh,8 ;行 mov dl,3 ;列 mov cl,2 ;顏色屬性 mov ax,data mov ds,ax mov si,0 call show_str ;子程式 mov ax,4c00h int 21h show_str: push dx ;避免寄存器衝突(雖然這個子程式沒有衝突,但為了更好的使用,還是加上了) push cx push si mov ax,0b800h mov es,ax ;顯示緩衝區段地址 mov al,dh mov bl,0a0h ;用於計算第八行的首地址 dec al mul bl ;首地址在ax中 mov bx,ax ;存在bx寄存器內 mov dh,0 mov di,dx ;用於計算列地址 dec di add di,di ;列地址就在di寄存器中 mov al,cl s: mov cl,ds:[si] ;取出字元,要判斷cx是否為0 mov ch,0 jcxz ok ;終止指令跳轉的條件 mov dl,ds:[si] ;取出字元 mov es:[bx+di],dl ;將字元送入顯示緩衝區中 mov es:[bx+di+1],al ;設置字元屬性 inc si ;data段的地址偏移+1 add di,2 ;顯是緩衝區段地址+2 jmp short s ;指令跳轉 ok: pop dx ;恢復主程式中寄存器的值 pop cx pop si ret ;子程式返回 code ends end start
運行結果:(不知明原因,第一行會被吃掉,因此實際顯示是在第七行)
子程式二:
功能:解決除法溢出問題
應用舉例:計算1000000/10(F4240/0AH)
返回: (dx) = 結果的高16位,(ax)=結果的低16位,(cx)=餘數
結果:(dx) =0001H, (ax)=86A0H,(cx)=0
公式:
H:X的高16位
L:X的低16位
N:除數
X/N = int(H/N)*65535 + [rem(H/N*65535)+L]/N
(對公式的理解很重要!!!我看了半天,才看懂了)
assume cs:code code segment start: mov ax,4240h ;存放被除數(dword類)的低16位地址 mov dx,000fh ;存放被除數(dword類)的高16位地址 mov cx,0ah ;存放除數 call divdw divdw: push ax ;把ax(即低16位地址先存入棧中,之後要用到) mov ax,dx ;對高16位地址進行16位除法 mov dx,0 div cx mov bx,ax ;bx的值為int(H/N),將除法所得商移入bx中 pop ax ;取出低16位地址
div cx ;對低16位地址進行16位除法,結果的低16位商位於ax寄存器中 mov cx,dx ;將餘數移入cx中 mov dx,bx ;將結果的高16位商移入dx中 ret code ends end start
運行結果:
子程式設計三:
功能:將word型數據轉變為表示十進位數據的字元串,字元串以0結尾
應用舉例:將12666以十進位的形式在屏幕的8行3列,用綠色顯示出來(顯示時調用子程式一)
assume cs:code data segment db 10 dup(0) ;保存字元串的記憶體地址段 data ends code segment start: mov ax,12666 mov bx,data mov ds,bx mov si,0 call dtoc ;調用子程式 mov ax,4c00h int 21h dtoc: mov bx,10 ;bx為除數 mov dx,0 div bx ;對ax進行16位除法 mov cx,ax ;商保存在cx中,用於結束除法的繼續,當商為0時,代表所有餘數已求出 add dx,30h ;利用十進位對應的ascii碼=十進位數值碼+30H,得出字元並存在寄存器dx中 push dx ;將字元結果保存在棧中,因為餘數結果相對於本身字元的順序是逆序,因此我們要利用棧來逆序 add si,1 ;記錄除的次數,也就是字元的個數 jcxz s1 ;若cx即商為0,則調到s1處 jmp short dtoc ;迴圈除法 s1: mov bl,0 mov ds:[si],bl ;在data段的即將放入字元的末尾,將0存入 mov cx,si ;將字元的個數存取cx中 mov si,0 ;si寄存器表示data段的偏移地址 s2: pop ds:[si] ;取出放在棧中的數據 add si,1 ;偏移地址+1 loop s2 ;迴圈 mov dh,8 ;顯示字元串 mov dl,3 mov cl,2 mov si,0 call show_str ret show_str: push dx push cx push si mov ax,0b800h mov es,ax mov al,dh mov bl,0a0h dec al mul bl mov bx,ax mov dh,0 mov di,dx dec di add di,di mov al,cl s: mov cl,ds:[si] mov ch,0 jcxz ok mov dl,ds:[si] mov es:[bx+di],dl mov es:[bx+di+1],al inc si add di,2 jmp short s ok: pop dx pop cx pop si ret code ends end start
運行結果:(還是一樣,第一行顯示的會被吃掉,所以實際在第七行)