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

8086汇编程序调试:输入行前半部分的字节截取与打印问题

8086汇编:多行输入处理问题排查与修正

需求

程序接收多行输入,输出前半部分行中每行的前半长度内容(行长度按整数除法取半)。

测试情况

  • 输入:
    first line
    second line
    third line
    fourth line
    
  • 实际输出:
    d
    firs
    
  • 预期输出:
    first (10 // 2)
    secon   (11 // 2)
    

原思路

逐行读取所有输入,截取每行的前半部分,保存截取后的内容及其长度,最后使用cnt_lns计数器只打印前半部分的行。

原代码

cpu 8086
segment extra
buffer resb 60000

segment code
..start mov bx, data
        mov ds, bx
        mov bx, stack
        mov ss, bx
        mov sp, dno
        mov bx, extra
        mov es, bx


read_lines:
        mov ah, 0x0a
        mov dx, read
        int 21h
        jz print_lines

        mov cx, [cnt_lns]
        inc cx
        mov [cnt_lns], cx

    

shorten_lines:
        mov bx, 0
        mov bl, byte [read + 1]
        mov bh, 0
        shr bx, 1
    
        mov [line + bx], byte 13
        mov [line + bx + 1], byte 10
        inc bx

        mov [line_ln], bx
        mov cx, bx
    
        mov bx, buffer
        add bx, [total_len]
        mov si, line
        mov di, bx
        rep movsb
    
        mov bx, [line_ln]
        add [total_len], bx
    
print_lines:
    mov cx, [total_len]
    mov bx, 0
cycle:
    mov ah, 2
    mov dl, [buffer + bx]
    int 21h
    inc bx
    dec cx
    jnz cycle
    
done: hlt

segment data
read        db  100, ?
line        resb 100

line_ln     db    0

cnt_lns     dw    0
total_len   dw    0


segment stack
        resb 16
dno:    db ?

问题分析与修正

核心问题点

  1. 输入内容未复制到line缓冲区:int 21h ah=0Ah读取的输入字符存在read+2位置,但原代码直接操作空的line,导致截取内容完全错误。
  2. 输入结束判断错误:int 21h ah=0Ah不会通过ZF标志位指示输入结束,正确方式是检查read+1(输入长度字节)是否为0(用户按Ctrl+Z时返回长度0)。
  3. 变量类型不匹配:line_ln定义为字节型db,但后续用16位寄存器bx读取,会错误读取相邻变量内容,应改为字型dw。
  4. 未实现“只打印前半部分行”逻辑:原代码将所有行的截取内容存入buffer并全部打印,没有按需求只输出总行数的前一半。

修正后的代码

cpu 8086
segment extra
buffer resb 60000
line_lens resw 100  ; 存储每行截取后的长度,最多支持100行

segment code
..start mov bx, data
        mov ds, bx
        mov bx, stack
        mov ss, bx
        mov sp, dno
        mov bx, extra
        mov es, bx

read_lines:
        ; 读取一行输入
        mov ah, 0x0a
        mov dx, read
        int 21h
        
        ; 判断输入结束:输入长度为0(Ctrl+Z)
        mov al, [read + 1]
        or al, al
        jz process_print
        
        ; 总行数+1
        inc word [cnt_lns]
        
        ; 计算行长度的一半(整数除法)
        mov bx, 0
        mov bl, [read + 1]
        shr bx, 1  ; bx = 行长度 // 2
        
        ; 将输入的前半部分复制到line缓冲区
        mov cx, bx
        mov si, read + 2
        mov di, line
        rep movsb
        
        ; 添加回车换行
        mov [line + bx], byte 13
        mov [line + bx + 1], byte 10
        add bx, 2  ; 加上回车换行的长度
        
        ; 保存当前行的截取长度到line_lens
        mov si, [cnt_lns]
        dec si  ; 数组索引从0开始
        shl si, 1  ; 每个元素是字,偏移量*2
        mov [line_lens + si], bx
        
        ; 将截取后的行内容复制到buffer
        mov cx, bx
        mov si, line
        mov di, buffer
        add di, [total_len]
        rep movsb
        
        ; 更新总长度
        add [total_len], bx
        
        ; 继续读取下一行
        jmp read_lines

process_print:
        ; 计算需要打印的行数:总行数 // 2
        mov ax, [cnt_lns]
        shr ax, 1
        mov [print_cnt], ax
        
        ; 如果总行数为0,直接退出
        or ax, ax
        jz done
        
        ; 打印前半部分行
        mov bx, 0  ; buffer偏移量
        mov cx, 0  ; 当前打印行数
print_loop:
        ; 获取当前行的长度
        mov si, cx
        shl si, 1
        mov ax, [line_lens + si]
        
        ; 打印当前行的每个字符
        mov dx, ax
print_char:
        mov ah, 0x02
        mov dl, [buffer + bx]
        int 21h
        inc bx
        dec dx
        jnz print_char
        
        ; 行数+1,判断是否完成
        inc cx
        cmp cx, [print_cnt]
        jl print_loop

done: hlt

segment data
read        db  100, ?, 100 dup(?)  ; 完整的输入缓冲区:最大长度、实际长度、字符存储
line        resb 100                ; 单处理后的行缓冲区

cnt_lns     dw 0                    ; 总行数
total_len   dw 0                    ; buffer总长度
print_cnt   dw 0                    ; 需要打印的行数


segment stack
        resb 16
dno:    db ?

修正说明

  • 新增line_lens数组存储每行截取后的长度,实现按行打印的逻辑。
  • 修复输入读取流程:将read+2的输入内容复制到line后再处理截取和换行。
  • 修正输入结束判断逻辑:通过检查输入长度是否为0退出读取循环。
  • 实现“前半部分行”打印:计算总行数的一半,逐行读取line_lens中的长度并打印对应内容。
  • 解决变量类型不匹配问题,避免非法内存读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 23:15:29