
;计算data段中第一组数据的3次方, 结果保存在后面一组dword单元中
assume cs:code
data segment
dw 1,2,3,4,5,6,7,8
dd 0,0,0,0,0,0,0,0
data ends
code segment
start:mov ax,data
mov ds,ax
mov si,0 ;ds:si指向第一组word单元
mov di,16 ;ds:di指向第二组dword单元
mov cx,8
s:mov bx,[si]
call cube ;调用子程序
mov [di],ax
mov [di].2,dx
add si,2 ;ds:si指向下一个word单元
add di,4 ;ds:di指向下一个dword单元
loop s
mov ax,4c00h
int 21h
cube:mov ax,bx ;子程序
mul bx
mul bx
ret
code ends
end start
子程序-显示字符
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0~24),(dl)=列号(取值范围0~79),(cl)=颜色,
;ds:si指向字符串的首地址
;返回:无
;应用举例:在屏幕的8行3列, 用绿色显示data段中的字符串。
assume cs:code
data segment
db 'Welcome to masm!',0
data ends
code segment
start:mov ax,data
mov ds,ax
mov si,0 ;字符串的首地址
mov dh,8 ;行号
mov dl,3 ;列号
mov cl,2 ;绿色
call show_str
mov ax,4c00h
int 21h
show_str: ;子程序用到的寄存器一定要先保存
push ax
push es
push bx
push bp
mov ax,0B800h ;显存段地址
mov es,ax
mov bl,cl ;bl保存颜色
;计算偏移量
mov al,160
mul dh
mov bp,ax
mov al,2
mul dl
add bp,ax ;计算出偏移量;bp显存偏移量
s:mov ch,0
mov cl,[si] ; 提取字符
jcxz s1 ;0字符返回
mov es:[bp],cl
mov es:[bp+1],bl
inc si
add bp,2
jmp s
s1:pop bp
pop bx
pop es
pop ax
ret
code ends
end start
防止溢出的除法运算

;名称:divdw
;功能:进行不会产生溢出的除法运算, 被除数为dword型, 除数为word型, 结果为dword型。
;参数:(ax)=dword型数据的低16位,(dx) =dword型数据的高16位,(cx)=除数
;返回:(dx)=结果的高16位,(ax)=结果的低16位,(cx)=余数
;应用举例:计算1000000/10(F4240H/0AH)=商186A0=100000
assume cs:code
data segment
data ends
code segment
start:
mov ax,4240h ;被除数低位
mov dx,000Fh ;被除数高位
mov cx,0Ah ;除数
call divdw
mov ax,4c00h
int 21h
divdw:
push bx
push ax ;保存低16位
;求int(H/N)
mov ax,dx ;高16位值给ax
mov dx,0
div cx ;(H/N)的商保存到ax中,(H/N)余数保存到dx中
mov bx,ax ;bx保存(H/N)的商
pop ax ;提取低16位
;求[rem(H/N) *65536+L] /N
;*65536就是把数据左移16位,放到高位的意思
;(H/N)余数在dx中(高位),就是rem(H/N) *65536
;(H/N)余数在dx中,低位在ax中,就是rem(H/N) *65536+L
div cx ;ax中保存[rem(H/N) *65536+L] /N的商
mov cx,dx ;返回余数
mov dx,bx ;(H/N)的商放到高位就是int(H/N) * 65536
;X/N=int(H/N) *65536+[rem(H/N) *65536+L] /N=dx+ax
pop bx
ret
code ends
end start
word型数据转变为十进制数的字符串
;名称:dtoc
;功能:将word型数据转变为表示十进制数的字符串, 字符串以0为结尾符
;参数:(a x) =word型数据
;ds:si指向字符串的首地址
;返回值:无
;应用举例:编程,将数据12666以十进制的形式在屏幕的8行3列,用绿色显示出来。
;在显示时我们调用本次实验中的第一个子程序show_str。
assume cs:code
data segment
db 10 dup(0)
data ends
code segment
start:
mov ax,12666 ;317A
mov bx,data
mov ds,bx
mov si,0
call dtoc
mov dh,8
mov dl,3
mov cl,2
mov si,0 ;字符串的首地址
call show_str
mov ax,4c00h
int 21h
dtoc: ;将word型数据转变为表示十进制数的字符串, 字符串以0为结尾符
push dx
push cx
push ax
push si
push bx
mov bx,0 ;bx保存字符总数
dt1:mov cx,10d ;d表示十进制,余数
mov dx,0
div cx ;ax保存商,dx保存余数
mov cx,ax ;把商给cx
jcxz dt2 ;如果商等于0跳到dt2
add dx,30h ;把余数加上30h得到ASCII吗
push dx
inc bx
jmp dt1
dt2:add dx,30h
push dx
inc bx
mov cx,bx ;循环次数
mov si,0
dt3:pop ax
mov [si],al
inc si
loop dt3
mov al,0
mov [si],al ;保证0结尾
pop bx
pop si
pop ax
pop cx
pop dx
ret
show_str: ;子程序用到的寄存器一定要先保存
push ax
push es
push bx
push bp
mov ax,0B800h ;显存段地址
mov es,ax
mov bl,cl ;bl保存颜色
;计算偏移量
mov al,160
mul dh
mov bp,ax
mov al,2
mul dl
add bp,ax ;计算出偏移量;bp显存偏移量
s:mov ch,0
mov cl,[si] ; 提取字符
jcxz s1 ;0字符返回
mov es:[bp],cl
mov es:[bp+1],bl
inc si
add bp,2
jmp s
s1:pop bp
pop bx
pop es
pop ax
ret ;返回
code ends
end start
清屏
assume cs:code
data segment
data ends
code segment
start:
call cls
mov ax,4c00h
int 21h
cls: ;清屏
push bx
push es
push dx
push cx
mov bx,0b800h ;显存地址 0xb800
mov es,bx
mov bx,0
mov cx,4000 ;文本模式显示25行,80字 即80*25*2 = 4000字节
s: mov dl,0 ;将NULL字符,即ASCII 0 放入低位
mov dh,0 ;将颜色 0 即 黑色 放入高位
mov es:[bx],dx
add bx,2
loop s
pop cx
pop dx
pop es
pop bx
ret
code ends
end start
延时子程序
delay:push ax ;延时子程序
push dx
mov dx,3h ;循环次数,读者可以根据自己机器的速度调整循环次数
mov ax,0
sl:sub ax,1
sbb dx,0
cmp ax,0
jne sl
cmp dx,0
jne sl
pop dx
pop ax
ret
