1、顯示字符串
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 ; 保護子程序寄存器中用到的寄存器
; 由於主程序的限定
; 這里由CPU自動為我們分配棧空間
mov di,0 ;顯示緩存區中的偏移量
mov bl,dh
dec bl ; bl-1才是真正的行,因為行號從0開始計數
mov al,160
mul bl ; 每行160字節 用 行數*每行偏移量 得到目標行的偏移量
mov bx,ax ; mul bl之后,乘積存儲在ax中,這里要轉存入bx中
mov al,2 ; 列的偏移量為2,兩個字節代表一列!!!
mul dl ; 與行偏移量同理
add bl,al ;將列偏移量與行偏移量相加,得到指定位置的偏移量。
mov ax,0b800h
mov es,ax ;指定顯示緩存區的內存位置
mov al,cl ; 由於后面jcxz語句的判斷要用到cx,所以我們要將
; cl(顏色)先存下來。
s: mov ch,0
mov cl,ds:[si] ;首先將當前指向字符串的某個字符存入cx中
jcxz ok ; 如果cx為0,則轉移到ok標號執行相應代碼
mov es:[bx+di],cl ;將字符傳入低地址
mov es:[bx+di+1],al ; 將顏色傳入高地址
add di,2 ; 列偏移量為2
inc si ; 字符串的偏移量為1
loop s ; 不為0,繼續復制
ok: pop dx
pop cx
pop si ; 還原寄存器變量
ret ; 結束子程序調用
code ends
end start
2、解決除法溢出的問題
這里要注意,把一個數放在了dx,高位寄存器中,那么就相當於 65536。
例如:int(H/N)65536 就相當於把int(H/N)放在了dx中。
divdw:
;先計算高位,再計算低位。低位先入棧
push ax ; 先將低位數據入棧,因為后面的div需要占用ax寄存器
mov ax,dx ; 將被除數(X的高16位)放入被除數的低16位ax中
mov dx,0 ; 將被除數的高十六位dx清零
div cx ; int(H/N), 存入ax(商)中,rem(H/N)存入dx(余數)中
mov bx,ax ; 臨時保存ax
pop ax ; 取出先前入棧的X的低位
div cx ; L\N
mov cx,dx ; 余數保存在cx里
mov dx,bx ; dx保存的是最終結果的高位
3、數值顯示
投機取巧之法,不過相對簡單。
assume cs:code
data segment
db 10 dup (0)
data ends
stack segment
dw 8 dup(0)
stack ends
code segment
start: mov ax,12666
mov bx,data
mov ds,bx
mov bx,stack
mov ss,bx
mov sp,10h
mov si,0
call dtoc
mov dh,8
mov dl,3
mov cl,2
call show_str
mov ax,4c00h
int 21h
dtoc: push ax
push bx
push si
mov bx,10
mov si,0
s0:
mov dx,0
div bx ; ax/bx
add dx,30h ; 余數加30
push dx ; 入棧
mov cx,ax ; 商-->cx
inc si ; 記錄循環次數
inc cx ; 當商為0時,也要加 1 ,方便loop判斷
loop s0 ; 首先 cx = cx -1,再判斷 cx 是否為0
mov cx,si ; cx 為循環次數
mov si,0 ; si 指向 ds:[0]
s1:
pop ds:[si] ; 將棧中轉化好了的數據放到內存中
inc si
loop s1
pop si
pop bx
pop ax
ret
show_str: push dx
push cx
push si ; 保護子程序寄存器中用到的寄存器
; 由於主程序的限定
; 這里由CPU自動為我們分配棧空間
mov di,0 ;顯示緩存區中的偏移量
mov bl,dh
dec bl ; bl-1才是真正的行,因為行號從0開始計數
mov al,160
mul bl ; 每行160字節 用 行數*每行偏移量 得到目標行的偏移量
mov bx,ax ; mul bl之后,乘積存儲在ax中,這里要轉存入bx中
mov al,2 ; 列的偏移量為2,兩個字節代表一列!!!
mul dl ; 與行偏移量同理
add bl,al ;將列偏移量與行偏移量相加,得到指定位置的偏移量。
mov ax,0b800h
mov es,ax ;指定顯示緩存區的內存位置
mov al,cl ; 由於后面jcxz語句的判斷要用到cx,所以我們要將
; cl(顏色)先存下來。
s: mov ch,0
mov cl,ds:[si] ;首先將當前指向字符串的某個字符存入cx中
jcxz ok ; 如果cx為0,則轉移到ok標號執行相應代碼
mov es:[bx+di],cl ;將字符傳入低地址
mov es:[bx+di+1],al ; 將顏色傳入高地址
add di,2 ; 列偏移量為2
inc si ; 字符串的偏移量為1
loop s ; 不為0,繼續復制
ok: pop dx
pop cx
pop si ; 還原寄存器變量
ret ; 結束子程序調用
code ends
end start