qq_56696679
千里不留行984
采纳率0%
2021-04-02 22:06

汇编两个变量求和,为什么将DI寄存器换成数据段就出错了?

汇编老师布置了作业,要求写两个变量的加法,在这个程序之前我们学习了闰年的程序,于是我将闰年的一段代码当做子程序直接拿过来用了,但是却出现了错误,这段子程序中用来累加数据的数据段[w]里的数据根本不是输入的数据。

经过DEBUG发现,在数据存入[w]之前的过程没有问题,唯独最后显示的[w]里的数据出现了错误。但当我把[w]换成DI寄存器就运行成功了,求问大佬是什么原因。

调用的子程序是闰年里的datacate,在我写的代码里叫mult。

我写的二变量加法的程序

DATAS SEGMENT
    NUM1 DB 0DH,0AH,'Please enter the first number:',13,10,'$'
    NUM2 DB 0DH,0AH,'Please enter the other number:',13,10,'$'
    SUM DB 0DH,0AH,'The answer is:',13,10,'$' 
    buf db 8
 	BI DB 0
DATAS ENDS

stack segment stack
	db 200 dup(0)
stack ends

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS
START:
    MOV AX,DATAS
    MOV DS,AX
OUTPUT1:    
    LEA DX,NUM1
    MOV AH,9
    INT 21H;界面输出“请输入第一个数字”  
    MOV DI,0;初始化寄存器DI的值,使其为零
    LEA DX,BUF
    mov ah,10
	int 21h;键盘输入到缓冲区
	MOV CH,0
  	MOV CL,[BUF+1];初始化CX的值,这决定了LOOP循环的次数
	CALL MULT;调用MULT子程序
    MOV AX,DI
OUTPUT2:
	LEA DX,NUM2
    MOV AH,9
    INT 21H;界面输出“请输入第二个数字” 
    LEA DX,BUF
    mov ah,10
	int 21h;键盘输入到缓冲区
	MOV CH,0
  	MOV CL,[BUF+1];初始化CX的值,这决定了LOOP循环的次数
	CALL  MULT
	MOV AX,DI
OUTPUT3:
	LEA DX,SUM
    MOV AH,9
    INT 21H;界面输出“结果是” 
	MOV AX,DI
	CALL JINZHI;调用“16进制转换10进制”子程序并输出
	MOV AH,4CH
    INT 21H
	
MULT PROC NEAR  
    ;将上面输入到缓冲区中的数据取出来进行进位计算,最终得到一个有意义的数字,比如“12”,并将12加入到W数据段中。
    push cx;将cx的值压入堆栈段中(为了保留CX原始的值)
		  dec cx;cx-1
		  lea si,buf+2;获取BUF+2=004E这个偏移地址,并将该地址赋给SI
	tt1:inc si;SI+1
		loop tt1;返回上一条进行循环,进行一次循环,CX里的值减一,直到CX里的值为零执行下一条
		pop cx;将CX的值从堆栈段里取出来
		
		mov dh,30h
		mov bl,10
		mov ax,1
	l1:push ax
	   push bx
	   push dx;将AX,BX,DX里的值全部存放到堆栈段中
	
	sub byte ptr [si],dh;si作为偏移地址指向的内存中的数减去寄存器中DH的数
	mov bl,byte ptr [si];将做完减法之后的内存中的数赋值给BL
	mov bh,0;初始化BH的值
	mul bx;执行BX和AX的乘法,乘积存放在AX中
	add DI,ax
	   pop dx
	   pop bx
	   pop ax;将DX,BX,AX的值从堆栈段里取出来
	mul bl;执行BL和AL的乘法,乘积存放在AL中
	dec si;SI减一
	loop l1;返回到L1进行循环
	ret
MULT ENDP

JINZHI PROC NEAR;进行16进制转换10进制,使存在DI寄存器中的16进制数转成10进制并输出	
	MOV BX,10
	MOV SI,4   
remainder:
    mov DX,0
    DIV BX;被除数除以10
    MOV [BI+SI],DL;得到的余数放在DL中,将DL中的数放在数据段里
    DEC SI;SI作为计数器,每得到一个余数,SI减一
    CMP AX,0
    JE NEXT
    JMP remainder;只有当商等于0的时候,才进行下面的程序,否则循环执行
NEXT:  
    INC SI;当将余数取出来时,需要SI加一,指向刚才存入的数据
    MOV DL,[BI+SI];将余数赋值给DL
    ADD DL,30H
    MOV AH,02
    INT 21H;DL加30H,得到需要显示数据的ASCII码 
    CMP SI,4
    JB NEXT;SI小于4时,进行循环 
    RET
JINZHI ENDP
    
CODES ENDS
    END START

闰年的程序:

DATA SEGMENT
    infon DB 0DH,0AH,'Please input a years:$'
    Y DB 0DH,0AH,'This is a leap year!$'
    N DB 0DH,0AH,'This is not a leap year!$'
    w dw 0
    buf db 8
    	db ?
    	db 8 dup(?)  	
data ends

stack segment stack
	db 200 dup(0)
stack ends

code segment
		  assume ds:data,ss:stack,cs:code
	start:mov ax,data
		  mov ds,ax
		  
		  lea dx,infon
		  mov ah,9
		  int 21h
		  
		  lea dx,buf;将BUF中的地址送到DX中去
		  mov ah,10
		  int 21h;键盘输入到缓冲区
		  
		  mov cl,[buf+1];buf+1=004D,将该地址的值赋给CL,CL=04
		  mov ch,0;初始化CH的值为零,此时CX=0004
		  
		  lea di,buf+2;
		  call datacate;跳转到datacate所在的段地址,并将当前的IP压入栈中
		  call ifyears;跳转到ifyears所在的段地址,并将当前的IP压入栈中
		  jc a1
		  
		  lea dx,n
		  mov ah,9
		  int 21h
		  jmp exit
a1:       lea dx,y
		  mov ah,9
		  int 21h
exit:		mov ah,4ch
			int 21h		  
datacate proc near
		  push cx;将cx的值压入堆栈段中(为了保留CX原始的值)
		  dec cx;cx-1
		  lea si,buf+2;获取BUF+2这个偏移地址,并将该地址赋给SI
	tt1:inc si;SI+1
		loop tt1;返回上一条进行循环,进行一次循环,CX里的值减一,直到CX里的值为零执行下一条
		pop cx;将CX的值从堆栈段里取出来
		
		mov dh,30h
		mov bl,10
		mov ax,1
	l1:push ax
	   push bx
	   push dx;将AX,BX,DX里的值全部存放到堆栈段中
	
	sub byte ptr [si],dh;si作为偏移地址指向的内存中的数减去寄存器中DH的数
	mov bl,byte ptr [si];将做完减法之后的内存中的数赋值给BL
	mov bh,0;初始化BH的值
	mul bx;执行BX和AX的乘法,乘积存放在AX中
	add [w],ax
	   pop dx
	   pop bx
	   pop ax;将DX,BX,AX的值从堆栈段里取出来
	mul bl;执行BL和AL的乘法,乘积存放在AL中
	dec si;SI减一
	loop l1;返回到L1进行循环
	ret
datacate endp

	ifyears proc near
		push bx
		push cx
		push dx;将BX,CX,DX里的值全部存放到堆栈段中
		mov ax,[w]
		mov cx,ax
		mov dx,0
		mov bx,100;进行赋值
		div bx;100作为除数
		cmp dx,0
		jnz lab1;余数不等于零的时候跳转到LAB1
		mov ax,cx
		mov bx,400
		
		div bx;400作为被除数
		cmp dx,0
		jz lab2;等于零的时候跳转到LAB2
		clc
		jmp lab3
	lab1:mov ax,cx
	mov dx,0
	mov bx,4
	div bx
	cmp dx,0
	jz lab2
	clc
	jmp lab3
	lab2:stc
	lab3:pop dx
		 pop cx
		 pop bx
		 ret
	ifyears endp
code ends
	end start
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • QA_Assistant 有问必答小助手 1月前

    你好,我是有问必答小助手,非常抱歉,本次您提出的有问必答问题,技术专家团超时未为您做出解答

    本次提问扣除的有问必答次数,将会以问答VIP体验卡(1次有问必答机会、商城购买实体图书享受95折优惠)的形式为您补发到账户。

    ​​​​因为有问必答VIP体验卡有效期仅有1天,您在需要使用的时候【私信】联系我,我会为您补发。

    点赞 评论 复制链接分享

相关推荐