You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用8086汇编求第n个斐波那契数时陷入无限循环问题排查

斐波那契数求解的8086汇编问题

需求与伪代码

需求是求解第n个斐波那契数(示例:n=3时输出1),设计的伪代码如下:

a = 0
b = 1
input n
si = 0

if n>2:
    loop:
        temp = b
        b = a+b
        a = temp
    loop while si != cx

print b

8086汇编实现代码

在EMU 4.08中编写的汇编代码:

.MODEL SMALL
.STACK 100h
.DATA
 STRING0 DB 'Enter INDEX $'           
.CODE
    MAIN PROC
        MOV AX,@DATA
        MOV DS,AX  
        
        LEA DX, STRING0  
        MOV AH,9
        INT 21H  
        
        
        MOV AH, 2  
        MOV DL,0AH    ; NEW LINE
        INT 21H
        MOV DL,0DH 
        INT 21H   
        
  
        MOV AH,1
        INT 21H 
        SUB CX,CX
        MOV CL,AL
        MOV SI,0
        MOV AX,0
        MOV BX,1
        

        LOOP1:
        
        PUSH BX
        ADD BX,AX
        POP AX
        INC SI
        
        LOOP LOOP1
             
        MOV DX,BX
        MOV AH,9
        INT 21H
         

     MAIN ENDP
END MAIN

遇到的问题

  • 运行代码时陷入无限循环,无法定位原因
  • 使用SUB CX,CX清空CX后将AL的值移入CL作为计数器,避免8位数据传入16位寄存器的错误,该操作是否合理?

问题分析与修复

1. 无限循环的核心原因

  • 输入值未转换为数值:INT 21H AH=1读取的是字符的ASCII码(比如输入数字3,AL为0x33即十进制51),而非真实数值。直接将该值赋值给CL,会导致循环执行次数远大于预期;若输入字符导致CX初始为0,LOOP指令会将CX减为0xFFFF,触发无限循环。
  • 循环控制逻辑混乱:伪代码中想用SI与CX比较控制循环,但8086的LOOP指令本身通过CX自减并判断是否为0来控制循环,额外的INC SI完全多余且未参与任何判断,逻辑冲突。
  • 输出功能错误:AH=9是DOS输出字符串的功能,要求DS:DX指向以$结尾的字符串。直接将斐波那契数值存入DX,会导致程序访问非法内存,引发异常,表现为看似无限循环的错误。

2. 关键修复点

  • ASCII转数值:读取输入后执行SUB CL, 30H,将字符ASCII码转换为对应十进制数值。
  • 修正循环次数:根据需求(n=3输出1),数列定义为第1项0、第2项1,第n项需循环n-2次计算。先判断n是否≤2,是则直接输出对应值;否则设置CX为n-2,用LOOP控制循环。
  • 优化计算逻辑:用临时寄存器替代栈操作保存中间值,逻辑更清晰:MOV DX, AX → MOV AX, BX → ADD BX, DX。
  • 数值转字符串输出:将二进制斐波那契数转换为ASCII字符串后,再用AH=9输出。

修复后的完整代码

.MODEL SMALL
.STACK 100h
.DATA
    STRING0 DB 'Enter INDEX $'
    RESULT_STR DB 10 DUP('$') ; 存储转换后的ASCII结果
.CODE
MAIN PROC
    MOV AX,@DATA
    MOV DS,AX  

    ; 打印输入提示
    LEA DX, STRING0  
    MOV AH,9
    INT 21H  

    ; 换行
    MOV AH, 2  
    MOV DL,0AH
    INT 21H
    MOV DL,0DH 
    INT 21H   

    ; 读取输入字符
    MOV AH,1
    INT 21H 
    SUB CX,CX
    MOV CL,AL
    SUB CL,30H ; ASCII码转十进制数值
    MOV AX,0 ; 第1项斐波那契数
    MOV BX,1 ; 第2项斐波那契数

    ; n≤2时直接输出对应值
    CMP CL,2
    JBE PRINT_RESULT

    ; 设置循环次数为n-2
    SUB CL,2
    MOV CX,CX

LOOP1:
    ; 计算下一项:temp=AX, AX=BX, BX=BX+temp
    MOV DX,AX
    MOV AX,BX
    ADD BX,DX
    LOOP LOOP1

PRINT_RESULT:
    ; 将BX中的二进制数转为ASCII字符串
    LEA SI, RESULT_STR+9 ; 从字符串末尾开始填充
    MOV CX,10
CONVERT:
    XOR DX,DX
    DIV CX
    ADD DL,30H
    MOV [SI],DL
    DEC SI
    CMP AX,0
    JNE CONVERT

    ; 输出结果
    LEA DX, RESULT_STR
    MOV AH,9
    INT 21H

    ; 程序正常退出
    MOV AH,4CH
    INT 21H

MAIN ENDP
END MAIN

关于SUB CX,CX的说明

该操作完全合理:CX是16位寄存器,直接给CL赋值时CH的值未初始化(为随机垃圾值),SUB CX,CX等价于MOV CX,0,可将CX整体清零,再给CL赋值后,能保证CX的高8位为0,低8位为输入的有效数值,避免16位寄存器高字节的垃圾值影响循环次数。


内容的提问来源于stack exchange,提问作者EmployedSlaveStudent

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 11:55:20