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

如何修复实模式汇编中的整数打印例程?

修复print_int例程的问题

问题根源分析

你的print_int存在多处栈操作和逻辑错误,导致输出乱码:

  • 负数处理逻辑漏洞:非负数时未跳过.negative代码块,错误修改栈数据
  • 栈平衡破坏:push si后未用pop si恢复,而是错误使用add sp,2,导致栈偏移和寄存器值丢失
  • 缓冲区索引错误:打印时的地址计算错误,读取了栈中无关数据
  • 循环计数错误:.finish处的dec cx直接抵消有效位数,导致少打印或不打印

修复后的完整代码

; Displays a single character to the screen
; void putc(char %al)
putc:
    mov ah, 0Eh
    int 10h
    ret

; Prints an integer to the screen
; void print_int(num %si, base %di)
print_int:
    ; Initialize stack frame
    push bp
    mov bp, sp

    ; 校验基数范围
    cmp di, 2
    jl .return
    cmp di, 36
    jg .return

    ; 保存寄存器
    push bx
    push si
    push cx
    push dx

    ; 预留缓冲区和负数标记(1字节标记+64字节缓冲区)
    sub sp, BUFFER_SIZE + 1
    mov byte [sp], 0  ; 负数标记初始为0

    ; 处理负数(仅十进制)
    cmp si, 0
    jge .loop
    cmp di, 10
    jnz .loop
    ; 转为正数并标记负数
    neg si
    mov byte [sp], 1

.loop:
    ; 计算余数和商
    xor dx, dx
    mov ax, si
    div di

    ; 余数转字符并存入缓冲区(从缓冲区起始位置往后存)
    mov bx, sp
    add bx, 1  ; 跳过负数标记,指向缓冲区起始
    add bx, cx ; cx是当前已存储的位数,从0开始
    mov si, digits
    add si, dx
    mov al, [si]
    mov [bx], al

    ; 更新商和计数
    mov si, ax
    inc cx

    ; 商不为0继续循环
    cmp si, 0
    jne .loop

    ; 打印负数符号(如果需要)
    cmp byte [sp], 1
    jne .print_number
    mov al, '-'
    call putc

.print_number:
    ; 从缓冲区末尾往前打印(因为余数是逆序存储的)
    mov bx, sp
    add bx, 1
    add bx, cx
    dec bx  ; 指向最后一个有效字符

.print_loop:
    cmp cx, 0
    jle .end_print
    mov al, [bx]
    call putc
    dec bx
    dec cx
    jmp .print_loop

.end_print:
    ; 清理栈并恢复寄存器
    add sp, BUFFER_SIZE + 1
    pop dx
    pop cx
    pop si
    pop bx

.return:
    mov sp, bp
    pop bp
    ret

digits: db "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
BUFFER_SIZE: equ 64

关键修复点说明

  1. 负数处理:新增jge .loop跳过非负数的负数处理逻辑,仅在十进制且数字为负时才标记并取反
  2. 栈管理:明确预留缓冲区和标记的空间,操作栈时严格平衡,所有push的寄存器都对应pop
  3. 缓冲区存储:余数按逆序存入缓冲区(个位→十位→百位...),打印时从缓冲区末尾往前读取,保证输出顺序正确
  4. 循环计数:移除错误的dec cx,直接用cx作为有效位数计数,确保所有数字位都被打印

测试验证

执行mov si, 5、mov di, 10、call print_int会输出5;mov si,17输出17;mov si,728输出728,符合预期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 00:24:53