組合語言(第三版)實驗10-1,2
1.顯示字串 子程式描述: 名稱:show_str 功能:在指定的位置,用指定的顏色,顯示一個用0結束的字串。 引數:(dh)=行號(取值範圍0~24),(dl)=列號(取值範圍0~79), (cl)=顏色,ds:si指向字串的首地址 返回:無 應用舉例:在螢幕的8行3列,用綠色顯示data段中的字串。
程式碼:
assume cs:codesg
datasg segment
db 'welcome to masm!',0
datasg ends
codesg 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 ds
push si ;棧儲存原資料
mov ax,0b800h
mov es,ax ;視訊記憶體段地址
mov ax,0a0h
mul dh
mov bx,ax ;bx 行號(從0開始)
mov ax,2
mul dl
mov di,ax ;di 列號(從0開始)
mov al,cl ;al 顏色
mov ch,0
set:
mov cl,[si];cl 字串中的位元組
jcxz ok ;cx 為0 轉結束子程式
mov es:[bx+di],cl ;列中低位代表字元
mov es:[bx+di+1],al ;列中高位代表顏色
inc si
add di,2
jmp short set
ok:
pop si
pop ds
pop cx
pop dx
ret
codesg ends
end start
2.解決除法溢位的問題 子程式描述 名稱:divdw 功能:進行不會產生溢位的除法運算,被除數為dword型,除數為word型,結果為dword型。 引數:(ax)=dword型資料的低16位 (dx)=dword型資料的高16位 (cx)=除數 返回:(dx)=結果的高16位,(ax)=結果的低16位 (cx)=餘數 應用舉例:計算1000000/10(F4240H/0AH) mov ax,4240h mov v dx,000fh mov cx,0ah call divdw
提示 給出一個公式: X:被除數,範圍:[0,FFFF FFFF] N:除數,範圍:[0,FFFF] H:X高16位,範圍:[0,FFFF] L:X低16位,範圍:[0,FFFF] int():描述性運算子,取商,比如:rem(38/10)=8 rem():描述性運算子,取餘數,比如:rem(38/10)=8 公式:X/N=int(H/N)*65536+[rem(H/N)*65536+L]/N 這個公式將可能產生溢位的除法運算:X/N,轉變為多個不會產生溢位的除法運算。 公式中,等號右邊的所有除法運算都可以用div指令來做,肯定不會導致除法溢位。
解析: 根據公式: 1.int(H/N)*10000h即是將(高位/除數)所得商左移16位變為高位 2.rem(H/N)*10000H+L即是求第一步剩下的餘數
舉個例子(雖然例子中的數不會溢位): 在十進位制中328/2,被除數328的高位H為3,低位L為28,則根據 1.求得int(H/N)=int(3/2)=商1,餘1即rem(H/N),此時328/2的餘數為128 2.第一步得出的餘數為128,即128=1*100+28(rem(H/N)*100+L) 3.最後結果為328/2=164=1*100+128/2=int(H/N)*100+(rem(H/N)*100+L)/N
程式碼:
assume cs:codesg
datasg segment
db 8 dup(0)
datasg ends
codesg segment
start:
mov ax,4240h
mov dx,000fh
mov cx,0ah
call divdw
mov ax,4c00h
int 21h
divdw:
push ax ;將ax存放至棧中,以便後面程式使用
mov ax,dx ;將ax設為H
mov dx,0 ;將dx置零
div cx ;求得ax=int(H/N),dx=rem(H/N)
mov bx,ax ;bx即為最終輸出中高位儲存的數
pop ax ;ax=L,dx=rem(H/N)
div cx ;相當於[dx*10000h+ax]/N
;ax即為最終輸出中低位儲存的數
;dx即為最終輸出中儲存的餘數
mov cx,dx
mov dx,bx ;返回結果
ret
codesg ends
end start