子程序1:
;功能:在指定的位置,用指定的颜色,显示一个用0结束的字符串。
;参数:(dh)=行号(取值范围0 ~ 24),(dl)=列号(取值范围0 ~ 79),(cl)=颜色,
;ds:si指向字符串的首地址
;返回: 无
show_str: PUSH AX
PUSH CX
PUSH SI
PUSH BX
PUSH ES
PUSH DI
MOV BL,CL ;记录下颜色参数
MOV AX,0b800h
MOV ES,AX
MOV AX,0A0h ;行号间隔
MUL DH
MOV DI,AX ;用参数乘以行号间隔,得到目的行偏移地址,结果存在DI中
MOV AX,2 ;列号间隔
MUL DL
ADD DI,AX ;用参数乘以列号间隔,得到目的列偏移地址
;结果加在行号偏移地址中
show_str1: MOV CL,[SI]
MOV CH,0
JCXZ show_str_ok
MOV ES:[DI],CL ;向目标地址写入字符
MOV ES:[DI+1],BL ;向目标地址写入颜色
INC SI ;转向下个字符
ADD DI,2
JMP SHORT show_str1 ;继续下个字符判断
show_str_ok:pop DI
pop ES
pop BX
Pop SI
Pop CX
Pop AX
RET
子程序2:
;名称:divdw
;功能:进行不会产生溢出的除法运算,被除数为dword型,除数为word型,结果为dword型.
;参数:(ax)=dword型数据的低16位
; (dx)=dword型数据的高16位
; (cx)=除数
;返回:(dx)=结果的高16位,
; (ax)=结果的低16位,
; (cx)=余数
;使用公式如下:
;X/N=INT(H/N)*65536+[REM(H/N)*65536+L]/N
;X:被除数,范围:0,FFFFFFFF
;N:除数,范围: 0,FFFF
;H:X高16位,范围:0,FFFF
;L:X低16位,范围:0,FFFF
;int():描述性运算符,取商,比如:int(38/10)=3
;rem():描述性运算符,取余数,比如:rem(38/10)=8
divdw: ;子程序开始
push bx
push ax
mov ax,dx ;被除数为X的高16位
sub dx,dx ;因为H取值最大FFFF,而除数取值最大FFFF,所以先设H为32位,高16位为0000
div cx ;H/N,商在AX中,余数在DX中
mov bx,ax ;保存H/N的商
pop ax ;REM(H/N)取余数在DX中*65536意思是*10000H,那么DX就是被除数中的高16位,
;+L X的低16位,自然存在AX中
div cx ;[REM(H/N)*65536+L]/N 商在AX中,余数在DX中 (ax)=结果的低16位
mov cx,dx ;(cx)=余数
mov dx,bx ;(dx)=结果的高16位 (H/N的商)
pop bx ;还原调用的bx
ret ;子程序结束
子程序3:
;名称:dtoc
;功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符.
;参数:(ax)=word型数据,ds:si指向字符串的首地址
;返回:无
;方法:用10 除以(ax),每次余数为一位的值,每次的商是下一次的被除数,直到商为0.
; 每次的商加上30H,为十进制数的ASCII码
dtoc: ;子程序开始
push dx
push bx
push si
push ax
push cx
mov bx,0 ;计数,一共有多少个字符
dtoc_1: mov cx,10 ;除数
sub dx,dx ;进行16位的除法,DX存余数
div cx ;AX存商,DX存余数
mov cx,ax
jcxz dtoc_2 ;如果商为0,除法结束
add dx,30H ;得到十进制数的ASCII码
push dx ;将十进制数的ASCII码入栈,否则直接写入的是逆序字符串
inc bx
jmp short dtoc_1
dtoc_2: add dx,30H
push dx
inc bx ;将最后一个结果数入栈,商为0,余数未知
mov cx,bx ;用于确定LOOP循环次数
dtoc_w: pop ax
mov ds:[si],al ;字符操作
inc si ;最后一次循环SI+1
loop dtoc_w ;字符循环写入ds:si地址
dtoc_ok:mov byte ptr ds:[si],0 ;字符串以0为结尾符
pop cx
pop ax
pop si
pop bx
pop dx
ret ;子程序结束