一、实验题目
将两个多位十进制数相减,要求被减数,减数均以 ASCII码形式按顺序存放在以DATA1和DATA2为首的5个内存单元中(低位在前),结果送回DATA1处。
二、基本代码
DATA SEGMENT
DATA1 DB 33H,39H,31H,37H,38H ;第一个数据(作为被减数)
DATA2 DB 36H,35H,30H,38H,32H ;第二个数据(作为减数)
MES1 DB '-','$'
MES2 DB '=','$'
DATA ENDS
STACK SEGMENT ;堆栈段
STA DB 20 DUP(?)
TOP EQU LENGTH STA
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA,SS:STACK,ES:DATA
START: MOV AX,DATA
MOV DS,AX
MOV ES,AX
MOV AX,STACK
MOV SS,AX
MOV AX,TOP
MOV SP,AX
MOV SI,OFFSET DATA1
MOV BX,05
CALL DISPL ;显示被减数
MOV AH,09H
LEA DX,MES1
INT 21H
MOV SI,OFFSET DATA2
MOV BX,05 ;显示减数
CALL DISPL
MOV AH,09H
LEA DX,MES2
INT 21H
MOV SI,OFFSET DATA1
MOV DI,OFFSET DATA2
CALL SUBA ;减法运算
MOV SI,OFFSET DATA1
MOV BX,05 ;显示结果
CALL DISPL
MOV DL,0DH
MOV AH,02H
INT 21H
MOV DL,0AH
MOV AH,02H
INT 21H
INT 21H
MOV AX,4C00H
INT 21H
DISPL PROC NEAR ;显示子功能
DSI: MOV AH,02
MOV DL,[SI+BX-1] ;显示字符串中一字符
INT 21H
DEC BX ;修改偏移量
JNZ DSI
RET
DISPL ENDP
SUBA PROC NEAR
MOV DX,SI
MOV BP,DI
MOV BX,05
SU1: SUB BYTE PTR[SI+BX-1],30H
SUB BYTE PTR[DI+BX-1],30H
DEC BX ;将ASCII 码表示的数字串
JNZ SU1 ;转化为十六进制的数字串
MOV SI,DX
MOV DI,BP
MOV CX,05 ;包括进位,共5位
CLC ;清进单位
SU2: MOV AL,[SI]
MOV BL,[DI]
SBB AL,BL ;带进位相减
AAS ;非组合BCD码的减法调整
MOV [SI],AL ;结果送被减数区
INC SI
INC DI ;指向下一位
LOOP SU2 ;循环
MOV SI,DX
MOV DI,BP
MOV BX,05
SU3: ADD BYTE PTR [SI+BX-1],30H
ADD BYTE PTR [DI+BX-1],30H
DEC BX ;十六进制的数字串转化ASCII码表示的数字串
JNZ SU3
RET
SUBA ENDP
CODE ENDS
END START
三、可显示负号结果
DATAS SEGMENT
DATA1 DB 38H,39H,31H,37H,33H;五位被减数,低位在前,这是存的字符ASCII值
DATA2 DB 38H,39H,31H,37H,39H;减数
DATA3 DB 38H,39H,31H,37H,33H;被减数备用数据,用作负数情况
MES1 DB '-','$'
MES2 DB '=','$'
;此处输入数据段代码
DATAS ENDS
STACKS SEGMENT
STA DB 20 DUP(?)
TOP EQU LENGTH STA;预定义TOP为STA的长度
;此处输入堆栈段代码
STACKS ENDS
CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS,ES:DATAS
START:
MOV AX,DATAS
MOV DS,AX
MOV ES,AX
MOV AX,STACKS;将名称为stacks的段(也就是ss段)的段地址送入ax
MOV SS,AX;将stacks段基址送入SS栈段
MOV AX,TOP;将STA的长度送入AX
MOV SP,AX;将stacks偏移地址送入ss:sp
;显示被减数
MOV SI,OFFSET DATA1;数据段DATA1地址送入SI
MOV BX,05
CALL DISPL
;显示-符号,MOV AH,09H表示在屏幕上显示移偏地址存在DX中为MES1的字符串。
MOV AH,09H
LEA DX,MES1;装载MES1的有效地址到dx,该语句可以用mov dx,MES1代换
INT 21H
MOV SI,OFFSET DATA2
MOV BX,05;显示减数
CALL DISPL
;显示=符号,MOV AH,09H表示在屏幕上显示移偏地址存在DX中为MES2的字符串
MOV AH,09H
LEA DX,MES2
INT 21H
MOV SI,OFFSET DATA1;相当于定义下标
MOV DI,OFFSET DATA2;相当于定义下标
CALL SUBA;减法运算
;负数情况
JNC S;当进位标记CF为0时跳转,为1时执行后面的指令,加负号
MOV AH,09H
LEA DX,MES1;装载MES1的有效地址到dx,该语句可以用mov dx,MES1代换
INT 21H
MOV SI,OFFSET DATA2;相当于定义下标
MOV DI,OFFSET DATA3;相当于定义下标
CALL SUBA;减法运算
;负数运行
MOV SI,OFFSET DATA2
JNC P
;非负数运行
s:MOV SI,OFFSET DATA1
p:MOV BX,05;显示结果
CALL DISPL
MOV DL,0DH;0DH是回车符确认的ASCII码
MOV AH,02H
INT 21H
MOV DL,0AH;这里的0AH是换行符的ASCII码,
MOV AH,02H
INT 21H
INT 21H
MOV AX,4C00H
INT 21H
;显示子功能
DISPL PROC NEAR
DSI:MOV AH,02
MOV DL,[SI+BX-1];显示字符串中一字符
INT 21H
DEC BX;修改偏移量
JNZ DSI
RET
DISPL ENDP
;减法运算子功能
SUBA PROC NEAR;
MOV DX,SI
MOV BP,DI
MOV BX,05
;;SU1将数据转化为十六进制的数字
SU1:SUB BYTE PTR[SI+BX-1],30H;BYTE PTR指明访问内存单元是一个字节
SUB BYTE PTR[DI+BX-1],30H
DEC BX;将ASCII码表示的数字串
JNZ SU1
MOV SI,DX
MOV DI,BP
MOV CX,05;包括进位,共5位
CLC;清除CF位
;;带进位相减
SU2:MOV AL,[SI]
MOV BL,[DI]
SBB AL,BL;sbb是带借位减法指令,它利用了CF位上记录的借位值,sbb al,bl: (al)=(al)-(bl)-CF
AAS;AAS 减法的ASCII调整指令,调整的最后结果是bcd码,可以用来明确直接地显示十进制数数字
;若AL寄存器的低4位>9或AF=1,则:
;AL=AL-6,AF置1;
;将AL寄存器高4位清零;
;AH=AH-1,CF置1。
;否则,不需要调整。
MOV [SI],AL;结果送被减数区
INC SI
INC DI;指向下一位
LOOP SU2;循环
;SU3十六进制的数字串转化ASCII码表示的数字串
MOV SI,DX
MOV DI,BP
MOV BX,05
;这里CF都是1
JC SU4;CF=1时候跳转
;CF为0运行SU3
SU3:
ADD BYTE PTR [SI+BX-1],30H;ADD同样影响CF标志位!
ADD BYTE PTR [DI+BX-1],30H
DEC BX
JNZ SU3;JNZ 结果不为零则转移ZF=0
JZ abc
;CF=1运行SU4
SU4:
ADD BYTE PTR [SI+BX-1],30H;ADD同样影响CF标志位!
ADD BYTE PTR [DI+BX-1],30H
DEC BX
JNZ SU4;JNZ 结果不为零则转移ZF=0
STC;CF=1,CLC=0
abc:
RET
SUBA ENDP
;此处输入代码段代码
MOV AH,4CH
INT 21H
CODES ENDS
END START