YASM(8086)文件字符串处理:筛选合规首/次列的程序实现求助
问题分析
现有程序的核心缺陷是缺乏列上下文管理:它仅做了单个字符的过滤,但没有跟踪当前处于第几列、当前列是否符合输出条件,也没有跳过不需要处理的3-6列,更没有在列结束时(遇到分号/换行)判断是否输出整列内容,完全没实现“仅输出首、次列中无数字及B、C的列”的核心需求。
要完成任务,必须引入状态变量跟踪列状态,重构字符处理逻辑。
解决方案步骤
1. 新增状态变量(在.bss段)
需要记录当前列号、列合法性、临时存储列内容:
section .bss current_col resb 1 ; 当前列号(1-6) is_col_valid resb 1 ; 当前列是否合法:1=合法,0=违规 col_buf resb 21 ; 存储当前列内容(最多20字符+结束符) col_buf_ptr resb 2 ; 缓冲区指针(偏移量)
2. 重构核心处理逻辑
修改function内的过滤逻辑,加入状态初始化和列处理流程:
- 初始化状态:处理前设置
current_col=1,is_col_valid=1,清空缓冲区指针 - 逐字符处理时,分情况处理换行、分号、普通字符:
- 换行:重置列号到1,准备下一行
- 分号:处理当前列(仅1/2列合法则输出),然后重置状态进入下一列
- 普通字符:1/2列检查字符是否违规,违规则标记列无效;3-6列直接跳过
- 文件结束时,处理最后一行的最后一列
修改后的完整代码
%include 'yasmmac.inc' org 100h section .text startas: macPutString 'Reading file name:', crlf, '$' mov al, 128 mov dx, readingFile call procGetStr macNewLine macPutString 'Writing file name: ', crlf, '$' mov al, 128 mov dx, writingFile call procGetStr macNewLine push readingFile push writingFile call function exit ; Main Function function: push bp mov bp, sp sub sp, 4 push dx push bx push ax push cx push si ; 打开读文件 mov dx, [bp+6] call procFOpenForReading jnc .secondFOpen macPutString 'Error while opening file', crlf, '$' jmp .end .secondFOpen: mov [bp-2], bx ; 打开写文件 mov dx, [bp+4] call procFCreateOrTruncate jnc .init_state macPutString 'Error while opening writing file', crlf, '$' jmp .close ; 初始化状态变量 .init_state: mov [bp-4], bx mov byte [current_col], 1 mov byte [is_col_valid], 1 mov word [col_buf_ptr], 0 jmp .whileNotTheEnd .whileNotTheEnd: mov bx, [bp-2] call procFGetChar jnc .process_char macPutString 'Error while reading file', crlf, '$' jmp .close .process_char: cmp ax, 0 ; 文件结束? je .handle_eof mov al, cl ; 处理换行符:重置列状态,准备下一行 cmp al, 0Ah je .handle_newline ; 处理分号:结束当前列,判断是否输出 cmp al, ';' je .handle_semicolon ; 处理普通字符 cmp byte [current_col], 2 jg .skip_col_3_to_6 ; 3-6列直接跳过 ; 当前是1/2列,检查字符是否违规 call .check_char_valid ; 不管是否违规,先把字符存入缓冲区(如果合法后续输出) mov si, [col_buf_ptr] mov [col_buf + si], al inc si mov [col_buf_ptr], si jmp .nextIteration .skip_col_3_to_6: ; 3-6列直接跳过,不处理 jmp .nextIteration ; 检查字符是否是数字/B/C,违规则标记列无效 .check_char_valid: ; 检查数字0-9 cmp al, '0' jl .check_b cmp al, '9' jle .mark_invalid .check_b: cmp al, 'B' je .mark_invalid cmp al, 'b' ; 可选支持小写判断,需求未明确可移除 je .mark_invalid .check_c: cmp al, 'C' je .mark_invalid cmp al, 'c' je .mark_invalid ret .mark_invalid: mov byte [is_col_valid], 0 ret ; 处理分号:结束当前列 .handle_semicolon: call .process_current_col ; 重置状态进入下一列 mov byte [is_col_valid], 1 mov word [col_buf_ptr], 0 inc byte [current_col] jmp .nextIteration ; 处理换行:结束当前列,重置列号到1 .handle_newline: call .process_current_col mov byte [current_col], 1 mov byte [is_col_valid], 1 mov word [col_buf_ptr], 0 ; 换行符不输出,直接进入下一行 jmp .nextIteration ; 处理文件结束:处理最后一列 .handle_eof: call .process_current_col jmp .close ; 处理当前列:如果是1/2列且合法,输出缓冲区内容 .process_current_col: cmp byte [current_col], 2 jg .proc_col_end ; 3-6列不输出 cmp byte [is_col_valid], 1 jne .proc_col_end ; 违规列不输出 ; 输出缓冲区内容 mov bx, [bp-4] mov si, 0 .print_loop: cmp si, [col_buf_ptr] je .proc_col_end mov al, [col_buf + si] call procFPutChar jnc .print_next macPutString 'Error while writing file', crlf, '$' jmp .close .print_next: inc si jmp .print_loop .proc_col_end: ret .nextIteration: jmp .whileNotTheEnd .close: mov bx, [bp-4] call procFClose .closeReadingFile: mov bx, [bp-2] call procFClose .end: pop si pop cx pop ax pop bx pop dx mov sp, bp pop bp ret4 %include 'yasmlib.asm' section .data writingFile: times 255 db 00 readingFile: times 255 db 00 section .bss current_col resb 1 is_col_valid resb 1 col_buf resb 21 col_buf_ptr resb 2
关键修改说明
- 状态跟踪:通过
current_col记录当前列位置,is_col_valid标记列合法性,col_buf临时存储列内容,确保能判断整列是否符合要求 - 列处理逻辑:
- 仅对1/2列做违规字符检查,3-6列直接跳过,符合需求
- 遇到分号或换行时触发列判断,只有全程无违规字符的1/2列才会被输出
- 字符检查:抽离
.check_char_valid逻辑,清晰判断字符是否为数字/B/C,违规则标记列无效 - 缓冲区管理:用
col_buf_ptr跟踪写入位置,输出后重置,避免内容混乱
测试验证
用你提供的示例文件测试:
firstA;lB;lC;lD;lE;lF A11;bas hello;0;0;5;1.15 B12; good day;-100;11;78;1.33
程序会输出:
firstA
完全符合预期。
内容的提问来源于stack exchange,提问作者Kurbamit
相关产品推荐
相关产品推荐

