📄 136_zhj.asm
字号:
;//////////////////////////////////////////////////////////////////
;日期: 2008-03-19
;代码名称:138_ZHJ
;编程者:张宏基
;程序功能: 完成两个压缩的8位多字节无符号BCD数相加的程序段。
; 两个操作数可以由键盘输入或者在数据段定义(常数)。
; 输出要求:在屏幕上显示出参与运算的两个加数和结果和。
;//////////////////////////////////////////////////////////////////
;------------------------------------------------------------------------------------------
.MODEL SMALL
.STACK 64
.DATA
;定义第一个加数存储结构
FirstPRAM LABEL BYTE
FirstMaxL DB 9
FisrtActL DB ?
FirstADD DB 9 DUP(0)
;定义第二个加数存储结构
SecondPRAM LABEL BYTE
SesondMaxL DB 9
SecondActL DB ?
SecondADD DB 9 DUP(0)
ONE DB 4 DUP(0)
TWO DB 4 DUP(0)
SUM DB 6 DUP(' ')
Result DB 11 DUP(0)
LEFTSPACE EQU 10
ROWSPACE EQU 03
COL DB 00
ROW DB 00
;定义程序运行过程中会出现的字符串
MESSEG1 DB 'FIRST NUMBER: '
MESSEG2 DB 'SECOND NUMBER: '
MSSSEG3 DB 'RESULT: '
.386
;-------------------------------------------------------------------------------------------
.CODE ;数据区
main PROC FAR
MOV AX, @DATA ;进行初始化
MOV DS, AX
MOV ES, AX
MOV AX, 0003H
INT 10H
CALL BPUT ;调用BPUT要求用户输入两个BCD数
MOV AL, FisrtActL ;如果输入的第一个加数的值不满8位
LEA SI, FirstADD ;则礒xpandTO8扩展为8位
LEA DI, FirstADD+08 ;其中进行高位补'0'并存到FirstADD
MOV AL, SecondActL ;如果输入的第二个加数的值不满8位
LEA SI, SecondADD ;则礒xpandTO8扩展为8位
LEA DI, SecondADD+08 ;其中进行高位补'0'并存到SecondADD
CALL BCDADD ;调用BCDADD进行BCD数的相SUM结果存到BCDRES中
LEA SI, SUM+4 ;将计算得到的BCD数结果
LEA DI, Result+10 ;转换成ASCII字符
CALL AConvert ;并存入Result中
CALL DISPLAY ;调DISPLAY将计算的结果显示
MOV AH, 01H
INT 21H
MOV AX, 4C00H ;设置中断结束程序
INT 21H
main ENDP
;
;从键盘接受两个量并把他们存储到定义好的FirstADD和SecondADD中
;--------------------------------------------------------------------------------------------
BPUT PROC NEAR ;使用到AX BP CX SI
MOV ROW, ROWSPACE+1 ;设置行
MOV COL, LEFTSPACE+3 ;设置列
LEA BP, MESSEG1 ;提示输入第一个数
MOV CX, 17d ;字符数
CALL KDISPLAY
MOV AH, 0AH ;从键盘接受并存放到
LEA DX, FirstPRAM ;FirstADD中
INT 21H
MOV COL, LEFTSPACE+3
INC ROW ;下一行
LEA BP, MESSEG2 ;提示输入第二个数
MOV CX, 17d ;字符数
CALL KDISPLAY
MOV AH, 0AH ;从键盘接受并存放到
LEA DX, SecondPRAM ;SecondADD中
INT 21H
INC ROW
RET
BPUT ENDP
;显示字符,其中BP中存放要显示的字符的地址,CX中存放要显示的字符个数
;-----------------------------------------------------------------------------------------------
KDISPLAY PROC NEAR ;BP,CX在入口处设置
MOV AX, 1301H ;请求显示行
MOV BX, 000FH ;页和属性
MOV DH, ROW ;屏幕行
MOV DL, COL ;屏幕列
INT 10H
RET
KDISPLAY ENDP
;用来显示计算得到的结果
;-----------------------------------------------------------------------------------------------
DISPLAY PROC NEAR
INC ROW
LEA BP, MSSSEG3 ;将"The Result is : "的地址装入BP
MOV CX, 10d ;设置显示的字符数
CALL KDISPLAY ;调KDISPLAY显示"The Result is :"
MOV AH, 02H ;调用02中断
MOV CX, 9 ;字符数初始化为9
LEA DI, Result+2 ;装入存着计算结果的地址
LLL: MOV DL, [DI] ;
SUB DL, 30H ;LLL部分用来判断存放的计算
JNZ XXX ;结果首位是不是为了
INC DI ;如果是就跳过不显示
DEC CX ;因为计算结果首位不可能为0
JMP LLL
XXX:
MOV DL, [DI] ;利用02中断显示计算结果
INT 21H
INC DI
LOOP XXX
RET
DISPLAY ENDP
;将存储在FirstADD和SecondADD里的两个数取出来相加
;------------------------------------------------------------------------------------------------
BCDADD PROC NEAR
LEA SI, FirstADD+8 ;将FirstADD里的ASCII数据取出
LEA DI, ONE+4 ;进行BCD转换后
CALL BConvert ;存入ONE里
LEA SI, SecondADD+8 ;将SecondADD里的ASCII数据取出
LEA DI, TWO+4 ;进行BCD转换后
CALL BConvert ;存入TWO里
XOR AH, AH
LEA SI, ONE+3 ;取第一个加数地址
LEA DI, TWO+3 ;取第二个加数地址
LEA BX, SUM+4 ;取存放BCD结果数地址
MOV CX, 04
NEXT:
MOV AL, [SI] ;将被加数移入
ADC AL, [DI] ;将加数移入
DAA ;BCD加法调整
MOV [BX], AL ;存入结果
DEC SI ;第一个加数地址减1
DEC DI ;第一个加数地址减1
DEC BX ;结果地址减1
LOOP NEXT
MOV AL, 0
ADC AL, 0
DAA ;这一步是为了防止最高位有进位
MOV [BX], AL
RET
BCDADD ENDP
;将ASCII码字符转换成压缩BCD码
;--------------------------------------------------------------------------------------------------
BConvert PROC NEAR
MOV CX, 05 ;设置循环次数
B: MOV AX, [SI] ;取一个字
XCHG AH, AL ;高低字节互换
SHL AL, 04 ;AL左移4位
SHL AX, 04 ;AX左移4位
MOV [DI], AH ;存入DI指向的存储器中
DEC SI ;源地址减1
DEC SI ;目标地址减1
DEC DI
LOOP B
RET
BConvert ENDP
;将存SUMDRES里的BCD结果数转换为ASCII字符
;-----------------------------------------------------------------------------------------------------
AConvert PROC NEAR
MOV CX, 05H
PPP:
MOV AL, [SI] ;取源操作数,一个字节
MOV BL, AL
AND AL, 0FH ;将高4位清0
ADD AL, 30H ;加30h变成ASCII字符
MOV [DI], AL ;存入目的操作数
DEC DI ;下一个目的操作数地址
SHR BL, 04H ;取高四位11
ADD BL, 30H ;加30h变成ASCII字符
MOV [DI], BL ;存入目的操作数
DEC DI ;下一个目的操作数地址
DEC SI
LOOP PPP
RET
AConvert ENDP
;如果输入的数不满8位,将其扩展为8位并存到FirstADD和SecondADD中
;-----------------------------------------------------------------------------------------------------
Expand PROC NEAR
MOVZX BX, AL ;暂存AL
MOVZX CX, AL
INC CX
CMP AL, 08 ;如果输入是8位,则直接结束返回
JE F
ADD SI, BX ;如果不是,则取得存放的数的最后一位以备用来扩展成8位
D:
MOV AL, [SI] ;这个循环是用来将存放的数扩展的,例如输入为12345
MOV [DI], AL ;经过这个循环后变为12312345
DEC SI ;下面还要做一个将前面的8-AL位清0的工作
DEC DI ;
LOOP D
MOV AX, 08
SUB AX, BX
MOV CX, AX ;计算得到8-AL,即要清0的位数
MOV AL, ' ' ;将0装入AL
E:
MOV [DI], AL ;清0
DEC DI
LOOP E
F:
RET
Expand ENDP
END main
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -