求问汇编语言里AAA调整的问题

影魔烧成灰 2016-04-07 01:06:54
楼主编了一个软件,目标是输出斐波那契数列的第N项,N要大于100,。
楼主输出前面17项都没有问题,但是当楼主输出第18项时,输出的却成了18428,本来应该是2584.
后来楼主进行调试发现,当进行987和1587的加法时,个位加法结果确实是4,并且产生了进位;
但是十位加法AL的结果是12H(也就是整数18),当进行AAA调整时,发现确实产生了进位,但是调整后AL的结果却是02,也就是没有进行+06H运算,后面也是一样的,我想问一下是怎么回事。
这是那个加法的方法,把这个加法单独进行测试,实现987和1587相加是正确的
数据存在缓冲区里
N1_NLEN DW 0 ;数组1的非数字长度
N1_LEN DW 0 ;数组1的长度
NUM1 DB 100 DUP(0) ;数组1
N2_NLEN DW 0 ;数组2的非数字长度
N2_LEN DW 0 ;数组2的长度
NUM2 DB 100 DUP(0) ;数组2
下面是加法的代码

ADDER1 PROC NEAR
PUSH SI
PUSH DS
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV SI,99
MOV CX,[N1_LEN]
MOV DI,[N2_LEN];
XOR DL,DL ;DL清零
CMP CX,DI
MOV [N1_LEN],CX
MOV DI,99
JAE CONTINUE ;CX存放两个数组中较大一个的长度
MOV CX,[N2_LEN]
MOV [N1_LEN],CX ;修改结果的长度
MOV BX,[N2_NLEN]
MOV [N1_NLEN],BX
CONTINUE:
XOR AL,AL
MOV AL,DL
XOR AH,AH
XOR DL,DL
MOV BX,[N1_NLEN]
DEC BX
CMP SI,BX
JE LA
ADD AL,BYTE PTR [NUM1+SI]
AAA
MOV DL,AH
DEC SI
JMP LB
LA:
ADD AL,0
LB:
MOV BX,[N2_NLEN]
DEC BX
CMP DI,BX
JE LC
ADD AL,BYTE PTR [NUM2+DI]
DEC DI
AAA
MOV DL,AH
JMP LD
LC:
ADD AL,0
AAA
MOV DL,AH
LD:
MOV [NUM1+SI+1],AL
LOOP CONTINUE
CMP DL,0
JE LF
MOV [NUM1+SI],DL
MOV [N1_NLEN],SI
MOV BX,[N1_LEN]
INC BX
MOV [N1_LEN],BX
LF:
POP DX
POP CX
POP BX
POP AX
POP DS
POP SI
RET
ADDER1 ENDP

为什么前面17项结果正确,但是第18项结果就出错了呢
...全文
525 9 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
影魔烧成灰 2016-04-07
  • 打赏
  • 举报
回复
引用 5 楼 zara 的回复:
ADDER1 里 LB: 和 LC: 之间的 DEC DI 挪到 AAA 指令的后面,别在 ADD 和 AAA 间加入其它指令,尽管可能手册上都说 DEC 指令不影响到 CF
谢谢大神,确实是那里的问题。100分都给你了,
影魔烧成灰 2016-04-07
  • 打赏
  • 举报
回复
引用 7 楼 fornetuse123 的回复:
本来还想学习下,结果发现上窜下跳,注释太精简,还是放弃了。
抱歉了。刚学汇编三周,第一次编,走了很多弯路,也没来的及改,还有很多代码是迭代前的。
fornetuse123 2016-04-07
  • 打赏
  • 举报
回复
本来还想学习下,结果发现上窜下跳,注释太精简,还是放弃了。
zara 2016-04-07
  • 打赏
  • 举报
回复
DEC 影响到了 AF 而 AAA 也会使用到 AF,所以 DEC 夹在 ADD 和 AAA 之间就可能出错了。
zara 2016-04-07
  • 打赏
  • 举报
回复
ADDER1 里 LB: 和 LC: 之间的 DEC DI 挪到 AAA 指令的后面,别在 ADD 和 AAA 间加入其它指令,尽管可能手册上都说 DEC 指令不影响到 CF
影魔烧成灰 2016-04-07
  • 打赏
  • 举报
回复
引用 1 楼 zara 的回复:
既然单独测试这个方法对那两个数相加是正确的,你放这个函数上来有什么意义。 照你的说法,十位数相加的话要么是 16 (8+8) 要么是 17 (8+8+个位的进位),怎么会是 18 呢;可能还是这里本来数据就有问题了吧,在这个地方停下来,仔细看看两待加数如何,各步运行结果如果。 可以的话,整个可运行调试的代码放上来吧。
好吧,我放全部代码。目前代码有两个问题,一个是只输入一个参数的第18项以后不正常,二是输入若干个参数,第二项结果还不正确。 [code=text] DATAS SEGMENT MESG DB 'Please input the number(Separated by spaces):','$' BUFF DB 50,?,50 DUP('$') ;系统请求用户输入的字符串 CRLF DB 10, 13, '$' ;回车换行 N1_NLEN DW 0 ;数组1的非数字长度 N1_LEN DW 0 ;数组1的长度 NUM1 DB 100 DUP(0) ;数组1 N2_NLEN DW 0 ;数组2的非数字长度 N2_LEN DW 0 ;数组2的长度 NUM2 DB 100 DUP(0) ;数组2 DATAS ENDS STACKS SEGMENT DW 100 DUP(0) STACKS ENDS CODES SEGMENT ASSUME CS:CODES,DS:DATAS,SS:STACKS ; ------------------------------------- ; 功能:显示指定地址(Str_Addr)的字符串 Output MACRO Str_Addr PUSH DX PUSH AX MOV DX,OFFSET Str_Addr MOV AH,09H INT 21H POP AX POP DX ENDM ; ------------------------------------- ;计算对应的项,存放在DX中 BB PROC NEAR PUSH BX MOV BX,DX SHL BX,1 ;移动三次乘以8 SHL BX,1 SHL BX,1 SHL DX,1 ;乘以2 ADD DX,BX ;相加 MOV AH,0 ;升位以后再相加 AND AL,0FH ADD DX,AX POP BX RET BB ENDP ; ------------------------------------- ;实现任意大的两个数相加,NUM1,NUM2分别是数组的首地址,结果放到NUM1数组中,进位CF ADDER1 PROC NEAR PUSH SI PUSH DS PUSH AX PUSH BX PUSH CX PUSH DX MOV SI,99 MOV CX,[N1_LEN] MOV DI,[N2_LEN];DI存放BP的长度 XOR DL,DL ;DL清零 CMP CX,DI MOV [N1_LEN],CX MOV DI,99 JAE CONTINUE ;CX存放两个数组中较大一个的长度 MOV CX,[N2_LEN] MOV [N1_LEN],CX ;修改结果的长度 MOV BX,[N2_NLEN] MOV [N1_NLEN],BX CONTINUE: XOR AL,AL MOV AL,DL XOR AH,AH XOR DL,DL MOV BX,[N1_NLEN] DEC BX CMP SI,BX JE LA ADD AL,BYTE PTR [NUM1+SI] AAA MOV DL,AH DEC SI JMP LB LA: ADD AL,0 LB: MOV BX,[N2_NLEN] DEC BX CMP DI,BX JE LC ADD AL,BYTE PTR [NUM2+DI] DEC DI AAA MOV DL,AH JMP LD LC: ADD AL,0 AAA MOV DL,AH LD: MOV [NUM1+SI+1],AL LOOP CONTINUE CMP DL,0 JE LF MOV [NUM1+SI],DL MOV [N1_NLEN],SI MOV BX,[N1_LEN] INC BX MOV [N1_LEN],BX LF: POP DX POP CX POP BX POP AX POP DS POP SI RET ADDER1 ENDP ; ------------------------------------- ;实现任意大的两个数相加,NUM1,NUM2分别是数组的首地址,结果放到NUM2数组中,进位CF ADDER2 PROC NEAR PUSH SI PUSH DS PUSH AX PUSH BX PUSH CX PUSH DX MOV SI,99 MOV CX,[N2_LEN] MOV DI,[N1_LEN] ;DI指针指向末尾 XOR DL,DL ;DL清零 CMP CX,DI MOV [N2_LEN],CX MOV DI,99 JAE CONTINUEZ ;CX存放两个数组中较大一个的长度 MOV CX,[N1_LEN] MOV [N2_LEN],CX ;修改结果的长度 MOV BX,[N1_NLEN] MOV [N2_NLEN],BX CONTINUEZ: XOR AL,AL MOV AL,DL XOR AH,AH XOR DL,DL MOV BX,[N2_NLEN] DEC BX CMP SI,BX JE LAZ ADD AL,BYTE PTR [NUM2+SI] AAA MOV DL,AH DEC SI JMP LBZ LAZ: ADD AL,0 LBZ: MOV BX,[N1_NLEN] DEC BX CMP DI,BX JE LCZ ADD AL,BYTE PTR [NUM1+DI] AAA MOV DL,AH DEC DI JMP LDZ LCZ: ADD AL,0 AAA MOV DL,AH LDZ: MOV [NUM2+SI+1],AL LOOP CONTINUEZ CMP DL,0 JE LFZ MOV [NUM2+SI],DL MOV [N2_NLEN],SI MOV BX,[N2_LEN] INC BX MOV [N2_LEN],BX LFZ: POP DX POP CX POP BX POP AX POP DS POP SI RET ADDER2 ENDP ; ------------------------------------- ;显示NUM1对应的项 SHOW1 PROC NEAR PUSH DS PUSH AX PUSH CX PUSH DX MOV CX,[N1_LEN] ;数组长度,BX:数组首地址 MOV SI,[N1_NLEN] NEXTSHOW: MOV AH,02 MOV DL,[BX+SI] ADD DL,30H ;转换为ASCII码 INT 21H INC SI LOOP NEXTSHOW Output CRLF;回车换行 POP DX POP CX POP AX POP DS RET SHOW1 ENDP ; ------------------------------------- ;显示NUM2对应的项 SHOW2 PROC NEAR PUSH DS PUSH AX PUSH CX PUSH DX MOV CX,[N2_LEN] ;数组长度,BX:数组首地址 MOV SI,[N2_NLEN] NEXTSHOW: MOV AH,02 MOV DL,[BX+SI] ADD DL,30H ;转换为ASCII码 INT 21H INC SI LOOP NEXTSHOW Output CRLF;回车换行 POP DX POP CX POP AX POP DS RET SHOW2 ENDP ; ------------------------------------- ;主程序入口 START: MOV AX,DATAS MOV DS,AX MOV [N1_NLEN],99 MOV [N1_LEN],1;初始化斐波那契数列的第一和第二项 MOV [NUM1+99],1 MOV [N2_NLEN],99 MOV [N2_LEN],1 MOV [NUM2+99],1 Output MESG ;提示信息 MOV DX, OFFSET BUFF ;输入数字字符串 MOV AH,0AH INT 21H Output CRLF ;回车换行. ; ------------------------------------- ;开始处理数字字符串 MOV AH,0 MOV CH,0 XOR DX,DX XOR BX,BX MOV CL,BUFF[1] LEA SI,BUFF[2] NEXT: MOV AL,[SI] CMP AL,20H JE CALCULATE CALL BB I: INC SI LOOP NEXT PUSH CX CMP DX,1 ;判断输入的项数是否是第1,2项 JE SHOWNUM1 CMP DX,2 JE SHOWNUM1 PUSH DX CMP BX,0 ;如果不是第二项,判断是否是字符串的第一项,若是则跳转TT JZ TTZ SUB DX,BX MOV CX,DX POP BX MOV AX,1 JMP TZ TTZ: MOV CX,DX DEC CX DEC CX POP BX MOV AX,1 TZ: TEST AX,1 ;与测试 JZ TAZ;奇转 JNZ TBZ;偶转 TAZ: CALL ADDER1 JMP TCZ TBZ: CALL ADDER2 TCZ: INC AX LOOP TZ JMP SHOWNUM1 POP CX ; ------------------------------------- ;判断是偶数项还是奇数项,奇数项输入NUM1里的数,偶数项输出NUM2里的数 SHOWNUM1: PUSH BX TEST DX,1 ;与测试 JZ SAZ;奇转 JNZ SBZ;偶转 SAZ: LEA BX,NUM1 CALL SHOW1 JMP SCZ SBZ: LEA BX,NUM2 CALL SHOW2 SCZ: POP BX ; ------------------------------------- ;结束程序 EXIT: MOV AH,4CH INT 21H ; ------------------------------------- ; CALCULATE: PUSH SI PUSH CX CMP DX,1 ;判断输入的项数是否是第1,2项 JE SHOWNUM CMP DX,2 JE SHOWNUM PUSH DX PUSH DX CMP BX,0 ;如果不是第二项,判断是否是字符串的第一项,若是则跳转TT JZ TT SUB DX,BX MOV CX,DX POP BX MOV AX,1 JMP T TT: MOV CX,DX DEC CX DEC CX POP BX MOV AX,1 T: TEST AX,1 ;与测试 JZ TA;奇转 JNZ TB;偶转 TA: CALL ADDER1 JMP TC TB: CALL ADDER2 TC: INC AX LOOP T POP DX JMP SHOWNUM TD: POP CX POP SI XOR DX,DX JMP I ; ------------------------------------- ;判断是偶数项还是奇数项,奇数项输入NUM1里的数,偶数项输出NUM2里的数 SHOWNUM: PUSH BX TEST DX,1 ;与测试 JZ SA;奇转 JNZ SB;偶转 SA: LEA BX,NUM1 CALL SHOW1 JMP SC SB: LEA BX,NUM2 CALL SHOW2 SC: POP BX JMP TD ; ------------------------------------- CODES ENDS END START [code]
影魔烧成灰 2016-04-07
  • 打赏
  • 举报
回复
引用 1 楼 zara 的回复:
既然单独测试这个方法对那两个数相加是正确的,你放这个函数上来有什么意义。 照你的说法,十位数相加的话要么是 16 (8+8) 要么是 17 (8+8+个位的进位),怎么会是 18 呢;可能还是这里本来数据就有问题了吧,在这个地方停下来,仔细看看两待加数如何,各步运行结果如果。 可以的话,整个可运行调试的代码放上来吧。
抱歉上面应该是1597和987相加,把1597输成了1587,很抱歉
影魔烧成灰 2016-04-07
  • 打赏
  • 举报
回复
楼主的加法算法是从借鉴的别人的(http://blog.sina.com.cn/s/blog_9c5d29f701016azb.html) 但是这个算法有两个问题,一个问题是5,5输出的是0,不是10,第二个问题和我有一点像,就是输入789和789相加,结果是402,各位也不是8,各位大牛能不能帮我解决一下第二个问题,不胜感激。
zara 2016-04-07
  • 打赏
  • 举报
回复
既然单独测试这个方法对那两个数相加是正确的,你放这个函数上来有什么意义。
照你的说法,十位数相加的话要么是 16 (8+8) 要么是 17 (8+8+个位的进位),怎么会是 18 呢;可能还是这里本来数据就有问题了吧,在这个地方停下来,仔细看看两待加数如何,各步运行结果如果。
可以的话,整个可运行调试的代码放上来吧。

21,497

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧