;==========================================================================
;子程序DTOC功能;将word型数据转变为表示十进制数的字符串,字符串以0为结尾符。
;==========================================================================
; 问题:将data段中的数据以十进制的形式显示出来。
; DATA SEGMENT
; DW 123,12666,1,8,3,38
; DATA ENDS
;==========================================================================
ASSUME CS:CODE,DS:DATA
DATA SEGMENT
DW 123,12666,1,8,3,38
DATA ENDS
CODE SEGMENT
START:
MOV AX,DATA
MOV DS,AX
MOV SI,12 ;SI用来寻址,12=存储的第一个字符串的首地址
MOV CX,6 ;循环次数6,总共要转换6个word型数据
MOV BX,0 ;寻址用,现在[BX]指向第一个word型数据123
TRANSFER_ALL:
MOV AX,DS:[BX] ;(AX)=word型数据
CALL DTOC ;把(AX)中的word型数据转化成数字的ASCII码,传送到DS:SI开始的内存单元
ADD BX,2 ;准备读取下一个word型数据
CALL NEXT_WORD ;将SI指向下一个字符串开始的内存单元的偏移地址
LOOP TRANSFER_ALL ;继续转换下一个word型数据
MOV SI,12 ;再次将SI指向存储的第一个字符串的首地址
MOV DH,8 ;行号:0
MOV DL,3 ;列号:0
MOV CX,6 ;循环次数为6,总共要输出6个字符串
SHOW_ALL:
PUSH CX ;保存循环次数
MOV CL,2 ;绿色
CALL SHOW_STR ;显示字符串,(DH)=行号(0~24),(DL)=列号(0~79),(CL)=颜色
;DS:SI指向字符串的首地址。
CALL NEXT_WORD ;将SI指向下一个字符串开始的内存单元的偏移地址
INC DH ;行号+1,在下一行输出下一个字符串
POP CX ;恢复循环次数
LOOP SHOW_ALL ;继续转换下一个word型数据
MOV AX,4C00H
INT 21H
;----------------------------------------------------------------------------
;名称:DTOC(DIGITAL TOCHARACTER)
;功能:将word型数据转变为表示十进制数的字符串,字符串以0为结尾符。
;参数:(AX)=WORD型数据,(SI),DS:SI指向字符串的首地址
;返回:无
DTOC PROC NEAR
PUSH BX ;保护现场
PUSH DX
PUSH CX
PUSH AX
PUSH SI
MOV BX,0 ;BX用来计数,转化了多少位数字
DECIMAL_PLACE:
MOV DX,0 ;高16位置零
MOV CX,10 ;除数=10
DIV CX ;(AX)=商,(DX)=余数
ADD DX,30H ;数字转化为ASCII码
PUSH DX ;压入(DL)=每一位数字的ASCII码
INC BX ;转化的位数+1
CMP AX,0 ;商是不是0,代表是否已经取得10进制数的每一位数字
JNE DECIMAL_PLACE ;如果不是0,则还没有转化完,继续取得下一位数字
MOV CX,BX ;(CX)=循环次数
TRANSFER: ;依次把十进制数每一位数的ASCII码送到DS:SI开始的内存单元
POP DX ;弹出一位数字的ASCII码
MOV [SI],DL ;传送到DS:[SI]处
INC SI ;SI+1,准备传送下一个字符的ASCII码
LOOP TRANSFER ;继续传送
MOV AX,0
MOV [SI],AL ;改写数字字符串的最后一个byte的数据为0作为结尾符
POP SI ;恢复现场
POP AX
POP CX
POP DX
POP BX
RET ;返回
DTOC ENDP
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;功能:在制定的位置,用制定的颜色,显示一个用0结尾的字符串。
;参数:(DH)=行号(0~24),(DL)=列号(0~79),(CL)=颜色,DS:SI指向字符串的首地址。
;返回:无
SHOW_STR PROC NEAR
PUSH AX ;保护现场
PUSH ES
PUSH DX
PUSH DI
PUSH SI
MOV AX,0B800H ;显示缓冲区段地址
MOV ES,AX ;(ES)=显示缓冲区段地址
MOV AL,0A0H ;以下计算初始字符的偏移地址
MUL DH ;行数×0A0H(160个字节)
MOV DI,AX ;转移到DI中
MOV AL,2 ;显示缓冲区中一个字符占两个字节空间
MUL DL ;2×列号
ADD DI,AX ;获得初始字符的偏移地址
S:
MOV AX,DS:[SI] ;输出字符到显示缓冲区
MOV ES:[DI],AX
INC DI ;准备写入颜色信息
MOV ES:[DI],CL ;写入颜色信息
INC SI ;准备输出下一个字符
PUSH CX ;保存颜色=(CL)
MOV CX,DS:[SI] ;(CX)=下一个字符
MOV CH,0 ;!!!若DS:[SI]的低位字节为零,但其高位字节不为零,
;!!!则程序不能如期望的那样跳转到END_SHOW
JCXZ END_SHOW ;不为零则继续输出,为零则结束子程序
POP CX ;恢复颜色=(CL)
INC DI ;准备写入下一个字符
JMP S ;输出下一个字符
END_SHOW:
POP CX ;!!!如果(CX)≠0,就会跳转到这里,此时(CX)在栈中还没有弹出
;!!!如果不弹出就会引发错误
POP SI ;恢复现场
POP DI
POP DX
POP ES
POP AX
RET ;返回
SHOW_STR ENDP
;-----------------------------------------------------------------------------
;-----------------------------------------------------------------------------
;功能:将SI从本字符串开始的内存单元的偏移地址指向下一个字符串开始的内存单元的
; 偏移地址,字符串以0为结尾符。
;参数:(SI)=本字符串开始的内存单元的偏移地址
;返回:(SI)=下一个字符串开始的内存单元的偏移地址
NEXT_WORD PROC NEAR
PUSH AX ;保护现场
ZERO_OR_NOT:
MOV AX,[SI]
MOV AH,0 ;!!!如果AX的低8位(要比较的字符)为0而高8位不为0
;!!!则程序不能如期望的那样跳转到END_OF_NUM_STRING
CMP AX,0 ;是不是结尾符0?
JE END_OF_NUM_STRING ;是,则跳转到END_OF_NUM_STRING
INC SI ;否,SI+1
JMP ZERO_OR_NOT ;检测下一个byte
END_OF_NUM_STRING: ;是结尾符0
INC SI ;SI+1,指向下一个字符串开始的内存单元的偏移地址
POP AX ;恢复现场
RET ;返回
NEXT_WORD ENDP
;------------------------------------------------------------------------------
CODE ENDS
END START