汇编作业(2006.5.17)

DATA SEGMENT
 X DB 21, ?, 21 DUP(0)
 LENX DB 0   ; X的长度  
 Y DB 21, ?, 21 DUP(0)   
 LENY DB 0   ; Y的长度
 Z DB 21 DUP (0)   ; 保存结果
 N DB 0H    ; 监视加法的进位
 M DB 0H    ; 监视减法的借位  
 STR1 DB 'INPUT X (AT MOST 20 DIGITS): $'
 STR2 DB 0AH, 0DH, 'INPUT Y (AT MOST 20 DIGITS): $'
 STR3 DB 0AH, 0DH, ' X + Y = $'
 STR4 DB 0AH, 0DH, ' X - Y = $'
 STR5 DB 0AH, 0DH, 'ERROR! PROGRAMME CANCELED...', 0AH, 0DH, '$'
DATA ENDS

STACK SEGMENT PARA STACK
 DW 20H DUP(0)
STACK ENDS

CODE SEGMENT
 ASSUME CS:CODE, DS:DATA, SS:STACK
BEGIN: MOV AX, DATA
 MOV DS, AX
 MOV DX, OFFSET STR1
 MOV AH, 09H
 INT 21H
 MOV DX, OFFSET X
 MOV AH, 0AH   ; 获取多字节数据
 INT 21H
 MOV CX, 0   ; CX清零
 MOV SI, OFFSET X
 INC SI    ; SI指向X中存储其长度的位置
 MOV CL, [SI]   ; 将X中的数据个数存入CX
 MOV LENX, CL   
 CALL TESTTONUM   ; 调用测试初始化子程序

 MOV DX, OFFSET STR2
 MOV AH, 09H
 INT 21H
 MOV DX, OFFSET Y  ; 获取数据,同上
 MOV AH, 0AH
 INT 21H
 MOV CX, 0
 MOV SI, OFFSET Y
 INC SI    
 MOV CL, [SI]
 MOV LENY, CL
 CALL TESTTONUM
 
 MOV BL, LENX   ; 判断X长度是否大于等于Y的长度
 CMP BL, LENY
 JAE GOOD
 JMP QUIT   ; 否则退出
 
GOOD: MOV CL, LENX
 PUSH CX    ; 暂存CX
 MOV SI, OFFSET X  ; 令SI指向X首地址

 CALL COPY   ; 调用复制子程序
 POP CX    ; CX恢复
 PUSH CX    ; 再次储存
 CALL PRO1   ; 调用计算X+Y子程序
     
 MOV DX, OFFSET STR3    
 MOV AH, 09H
 INT 21H
 POP CX    ; CX恢复
 PUSH CX    ; 再次存储
 CALL TOASCIISHOW  ; 调用输出子程序
 
 POP CX
 PUSH CX
 MOV SI, OFFSET X  
 CALL COPY
 POP CX
 PUSH CX
 CALL PRO2   ; 调用计算X-Y子程序
 
 MOV DX, OFFSET STR4
 MOV AH, 09H
 INT 21H
 POP CX
 PUSH CX
 MOV N, 0H   ; 避免减法结果打印出最高位的1(详细参考输出子程序)
 CALL TOASCIISHOW  
 
OVER: MOV AH, 4CH
 INT 21H 

TESTTONUM PROC    ; 测试,初始化子程序
 INC SI    
 PUSH SI    ; 存储当前SI指向的位置(X或Y中的第一个实际数据)
LOP1: MOV AX, 0
 MOV AL, [SI]   ; 判断输入的不同情况
 CMP AL, '0'
 JB QUIT
 CMP AL, 'f'
 JA QUIT
 CMP AL, '9'
 JBE PART1
 CMP AL, 'A'
 JB QUIT
 CMP AL, 'F'
 JBE PART2
 CMP AL, 'a'
 JB QUIT    
 CMP AL, 'f'
 JBE PART2

PART1: AND AL, 0FH   ; 开始转化为数值
 MOV [SI], AL   ; 替换原始ASCII码
 JMP CONTINUE1
PART2: SUB AL, 07H
 JMP PART1

CONTINUE1: INC SI
  LOOP LOP1
 POP SI    ; 恢复SI指向
 DEC SI    ; SI指向实际输入的位数
 MOV BL, [SI]
 CMP BL, 1   ; 如果只有一位,则不需要交换(由于输入时最高位存储在低地址处,所以需要交换)
 JE NO
 MOV CX, 0   ; 开始交换
 MOV BX, 0
 MOV CL, [SI]
 SHR CL, 1   ; 交换循环次数是实际输入位数的一半
 MOV BL, [SI]   ; 开始确定最后一个数据的位置
 DEC BL    
 MOV DI, SI
 INC DI
 ADD DI, BX   ; 此时,DI指向最后一个数据
 INC SI    ; SI指向第一个数据

LOP: MOV AX, 0   ; 开始交换
 MOV AL, [DI]
 XCHG [SI], AL
 MOV [DI], AL
 INC SI
 DEC DI
 LOOP LOP 
 RET

QUIT: MOV DX, OFFSET STR5  ; 错误信息
 MOV AH, 09H
 INT 21H
 JMP OVER
 
NO: RET
TESTTONUM ENDP

COPY PROC    ; 复制子程序   
 INC SI    
 INC SI    ; SI指向要复制的第一个数据
 MOV DI, OFFSET Z
LOP2: MOV AX, 0   ; 开始复制到Z中
 MOV AL, [SI]
 MOV [DI], AL
 INC SI
 INC DI
 LOOP LOP2
 RET
COPY ENDP

PRO1 PROC    ; 计算X+Y子程序
 MOV SI, OFFSET Z  
 MOV DI, OFFSET Y
 INC DI
 INC DI    ; DI指向Y中的第一个数据
 MOV CX, 0
 MOV CL, LENY   ; 先循环LENY次(位数相同的部分)
LOP3: MOV BX, 0
 MOV BL, [DI]
 ADD BL, N   ; N为低位向本位的进位(第一次值为0)
 ADD [SI], BL   
 
 MOV BL, [SI]    
 CMP BL, 0FH   ; 如果本位大于F,则设置进位N为1
 JBE NOUP1   ; 否则跳转
 MOV N, 1H
 JMP UP1
 
NOUP1: MOV N, 0H   ; 无进位,设置N为0
UP1: INC SI
 INC DI
 LOOP LOP3
 MOV AL, LENX
 SUB AL, LENY   ; 再循环LENX-LENY次(循环X比Y多出来的那部分位数)
 MOV CL, AL
 JCXZ OUT1
LOP4: ADD BYTE PTR [SI], 0
 MOV BL, N   ; 同样加上当前进位N
 ADD [SI], BL
 MOV BL, [SI]
 CMP BL, 0FH   ; 有进位时,N置1
 JBE NOUP2
 MOV N, 1H
 JMP UP2

NOUP2: MOV N, 0H   ; 无进位时,N置0
UP2: INC SI
 LOOP LOP4
OUT1: RET
PRO1 ENDP

PRO2 PROC    ; 计算X-Y子程序
 MOV SI, OFFSET Z
 MOV DI, OFFSET Y
 INC DI
 INC DI
 MOV CX, 0H
 MOV CL, LENY   ; 先循环LENY次(位数相同的部分)
LOP5: MOV BX, 0H
 MOV BL, [DI]
 ADD BL, M   ; 将减数加上低位向本位的借位M(第一次为0)
 CMP BL, [SI]   ; 如果减数小于等于被减数,则无借位(M置0)
 JBE NODOWN1
 MOV AL, [SI]
 OR AL, 10H   ; 否则,从高位借1,被减数加上10H(同ADD 10H)
 MOV [SI], AL
 MOV M, 1H   ; 有借位,M置1
 JMP DOWN1
 
NODOWN1:MOV M, 0H
DOWN1: SUB [SI], BL
 INC SI
 INC DI
 LOOP LOP5
 MOV AL, LENX
 SUB AL, LENY
 MOV CL, AL   ; 再循环LENX-LENY次(循环X比Y多出来的那部分位数)
 JCXZ OUT2
LOP6: SUB BYTE PTR [SI], 0H
 MOV BL, M
 CMP BYTE PTR [SI], BL  ; 如果此位比借位还小,则继续借位(即此位为0时)
 JAE NODOWN2   
 MOV AL, [SI]   
 OR AL, 10H
 MOV [SI], AL
 MOV M, 1H
 JMP DOWN2

NODOWN2:MOV M, 0H   ; 无借位,M置0
DOWN2: SUB [SI], BL
 INC SI
 LOOP LOP6
OUT2: RET
PRO2 ENDP

TOASCIISHOW PROC   ; 输出函数
 MOV BL, N   
 CMP BL, 0H   ; 如果N为1,则在结果最前面打印一个'1'(即结果的最高位也存在进位) 
 JE OVERF   ; 检测减法的最高位溢出
 MOV DL, '1'
 MOV AH, 02H
 INT 21H
 

OVERF: MOV BL, M   ; 如果M为1,则在结果最前面打印一个'_'(即结果的最高位也存在借位)
 CMP BL, 0H
 JE NORMAL
 MOV DL, '_'
 MOV AH, 02H
 INT 21H
 
NORMAL: MOV SI, OFFSET Z
 MOV BX, 0
 MOV BL, LENX   ; 此处为从Z的高地址向低地址打印(结果从高位到低位显示)
 ADD SI, BX
 DEC SI
LOP7: MOV AX, 0
 MOV AL, [SI]
 AND AL, 0FH   ; 保留一位有效数值(每位只有一个数字)
 CMP AL, 0AH   ; 开始转化为ASCII码
 JB CONTINUE2
 ADD AL, 07H
CONTINUE2: ADD AL, 30H
  MOV DX, 0
  MOV DL, AL
  MOV AH, 02H
  INT 21H
  DEC SI
  LOOP LOP7
  MOV DL, 'H'
  MOV AH, 02H
  INT 21H
  RET
TOASCIISHOW ENDP

CODE ENDS
END BEGIN 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值