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
参考视频资料: http://pan.baidu.com/s/1nvpQiLz 密码: et5r