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

8086汇编二进制转十进制程序打印BX时循环异常问题排查

问题排查与修复方案

核心问题分析

1. 内存越界破坏数据

在反转二进制字符串的代码段中,循环结束后错误地修改了si指向的内存(此时si已超出bnum缓冲区的起始地址,指向未知内存区域),导致后续变量(如存储转换结果的bx)被意外篡改,进而引发循环异常终止。

原错误代码片段:

reverse:
    mov al ,[si] 
    mov [di] ,al
    inc di
    dec si
    loop reverse
    
; add the string terminator
inc di
MOV BYTE PTR [SI], '$' ; 错误:si此时指向bnum缓冲区外,破坏其他内存

2. 循环终止条件的指令选择

使用JG ST(有符号数大于判断)虽然对正数商有效,但逻辑上更适合用JNZ ST(非零判断),直接判断商是否为0,避免有符号数判断的潜在歧义。

3. 打印循环的冗余操作

printt循环结束后额外打印[di]的操作冗余,且逻辑不够严谨,容易导致重复打印或遗漏。


修复后的完整代码

.model small
.STACK 300h
.data
    welcome DB 'Welcome, please enter binary number max(10 digits)',0Ah,0Dh,'Press e to end',0Ah,0Dh,'$'
    msg1 DB 0Ah,0Dh,'You entered: ',0Ah,0Dh,'$'
    error DB ' Not an option, sorry. Enter again: ',0Ah,0Dh,'$'
    obtions DB 0Ah,0Dh,0Ah,0Dh,'convert it to ',0Ah,0Dh,'1-decimal',0Ah,0Dh,'2-octal',0Ah,0Dh,'3-hexa',0Ah,0Dh, '9-End',0Ah,0Dh,'$'
    bnum DB 11 DUP(?) ; buffer to store the binary number
    rbnum DB 11 DUP(?) ; buffer to store the reversed binary number
    fdnum DB 11 DUP(?) ; buffer to store the final decimal answer number
    length_msg db 0Ah,0Dh,'Length is: ','$'
    lenght_bnum db 0 ; length of the binary number
    fans db 0 ; final answer
    hex_num db 5 DUP ('$') ; buffer to store the hexadecimal number
    endl DB 0Ah,0Dh
    
    dec_result db 6 dup (?) ; decimal result will be stored here 
    oct_result db 5 dup (?) ; octal result will be stored here 
    dec_result_len db 0
.code
MAIN PROC  
    .startup

    ; print welcome
    MOV ah ,09h
    LEA dx , welcome
    int 21h
    xor ax, ax ; clear ax register

    
    ; Read string
    LEA SI, bnum ; load the address of the buffer into SI
    MOV CX, 10 ; set the counter to 10
    mov bx, 0 ; counter for the length of the binary number
READ:
    MOV AH, 01h 
    INT 21H ; read a character
    MOV [SI], AL ; store the character in the buffer
    CMP AL, 0Dh ; if equal to carriage return "Enter", jump string_end
    JE string_end ; if equal, jump string_end
    INC SI ; increment the pointer
    XOR AX, AX
    inc bx 
    LOOP READ ; repeat until CX = 0
string_end:
    MOV BYTE PTR [SI], '$' ; add the string terminator
    ;;;reverse bnum
    dec si
    LEA di, rbnum ; load the address of the reversed buffer into DI
    MOV CX, bx ; set the counter to the length of binary number
reverse:
    mov al ,[si] 
    mov [di] ,al
    inc di
    dec si
    loop reverse
    
    ; add the string terminator to rbnum (修复:在rbnum末尾添加$)
    MOV BYTE PTR [DI], '$' ; 正确:DI此时指向rbnum最后一个字符的下一个位置
    ;;;
    LEA DX, msg1 
    MOV AH, 09h 
    INT 21h ; print msg1 "You entered:"

    LEA DX, bnum 
    MOV AH, 09h 
    INT 21h ; print the binary number

    xor si, si
    lea dx, length_msg
    mov ah, 09h
    int 21h ; print "Length is:"

    mov lenght_bnum, bl ; store the length of the binary number in lenght_bnum
    mov dl, lenght_bnum
    add dl, 30h
    MOV AH, 02h
    INT 21h ; print the length of the binary number


    ; print options
obtion:
    mov ah, 09h
    LEA dx, obtions
    int 21h

    ; read option and store it in al
    mov ah, 01h ; 
    int 21h ; 
    
    
    ;switch
    cmp al,'1'
    je decimal
    cmp al,'2'
    je octal
    cmp al,'3'
    je hexadecimal
    cmp al,'9'
    je endd
    
    ; print error if not 1 or 2 or 3 or 9, and jump to option
    mov ah ,09h 
    LEA dx , error
    int 21h
    jmp obtion
    
decimal:
    mov cx ,bx 
    xor bx ,bx ;reset to zero to store answer
    mov dx ,1  ; initialize weight to 2^0
    LEA di, rbnum
cbd: ; convert binary to decimal loop
    cmp [di],'0'
    je novalue ;if current digit is 0, skip adding weight
    add bx ,dx
novalue:
    inc di
    shl dx, 1 ; multiply weight by 2 (next bit's weight)
    loop cbd
    
    ;;;;;;;;;;;;;;;;store decimal in string 
    LEA di, fdnum
    mov cx,0ah ; divisor is 10
    xor ax,ax 
    mov ax,bx ; load decimal result into AX
    xor dx,dx ; clear DX for division
ST : 
    div cx ; AX = quotient, DX = remainder
    mov bx ,ax ; save quotient to BX
    add dl ,30h ; convert remainder to ASCII
    ; MOV AH, 02h ; 测试打印,可注释掉
    ; INT 21h ; 测试打印余数,可注释掉
    mov [di],dl ; store ASCII digit in buffer
    inc di ; move to next buffer position
    mov ax,bx ; load quotient back into AX
    xor dx,dx ; clear DX for next division
    CMP AX, 0
    JNZ ST ; 修复:用非零判断替代有符号大于,逻辑更直接
     dec di ; move to last valid digit in buffer
     ;;;;;;;;;;;;;;;;;;;;
         mov ah ,2 ; set DOS print character function
         LEA si, fdnum ; load start address of result buffer
 printt :
     mov dl , [di] ; load digit to print
     int 21h ; print digit
     dec di ; move to previous digit
     cmp di,si ; check if we've reached the start of the buffer
     JGE printt ; 修复:大于等于时继续循环,避免冗余操作
    jmp endd
    
   
    
octal:
    jmp endd

hexadecimal:

    jmp endd
    
endd:
    .EXIT 
MAIN ENDP
END MAIN

关键修复点说明

  1. 修复内存越界:将MOV BYTE PTR [SI], '$'改为MOV BYTE PTR [DI], '$',在反转后的二进制字符串缓冲区rbnum的末尾添加终止符,避免破坏其他内存数据。
  2. 优化循环终止条件:将JG ST改为JNZ ST,直接判断商是否为0,逻辑更清晰,适配无符号数的商值判断。
  3. 简化打印循环:将jne printt改为JGE printt,并移除末尾冗余的打印操作,确保从最后一个数字到第一个数字完整打印,逻辑更严谨。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 08:20:53