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 ?
问题分析与修正
核心问题点
- 输入内容未复制到
line缓冲区:int 21h ah=0Ah读取的输入字符存在read+2位置,但原代码直接操作空的line,导致截取内容完全错误。 - 输入结束判断错误:
int 21h ah=0Ah不会通过ZF标志位指示输入结束,正确方式是检查read+1(输入长度字节)是否为0(用户按Ctrl+Z时返回长度0)。 - 变量类型不匹配:
line_ln定义为字节型db,但后续用16位寄存器bx读取,会错误读取相邻变量内容,应改为字型dw。 - 未实现“只打印前半部分行”逻辑:原代码将所有行的截取内容存入
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
相关产品推荐
相关产品推荐

