8086汇编程序数字转单词写入文件时缓冲区覆盖问题求助
8086汇编输出缓冲区覆盖问题修复
问题描述
我编写的8086汇编程序,功能是将输入文件中的数字转换为对应单词,其余字符原样写入输出文件,但出现了输出缓冲区字符互相覆盖的问题。例如输入文件内容为0a,预期输出nulisa,实际输出为aulis。
原代码
.model small .stack 100h .data msgHelp DB "Usage: program.exe <input_file> <output_file>$" msgFileError DB "Error: File not found or cannot be opened.$" input db 200 dup (0) output db 200 dup (0) skBuf db 20 dup (?) raBuf db 200 dup (?) words db "nulis", 0, "vienas", 0, "du", 0, "trys", 0, "keturi", 0, "penki", 0, "sesi", 0, "septyni", 0, "astuoni", 0, "devyni", 0 wordOffsets dw 0, 6, 13, 16, 21, 28, 34, 39, 47, 55 dFail dw ? rFail dw ? raBufPos dw 0 .code start: MOV ax, @data MOV ds, ax MOV di, offset raBuf MOV bx, 82h MOV si, offset input cmp byte ptr es:[80h], 0 je help cmp es:[82h], '?/' jne check_param cmp byte ptr es:[84h], 13 je help jmp check_param help: mov ah, 9 mov dx, offset msgHelp int 21h jmp programEnd check_param: cmp byte ptr es:[bx], 13 je next_filename cmp byte ptr es:[bx], 32 je next_filename mov dl, byte ptr es:[bx] mov [si], dl inc bx inc si jmp check_param next_filename: inc bx mov si, offset output output_filename_loop: cmp byte ptr es:[bx], 13 je found mov dl, byte ptr es:[bx] mov [si], dl inc bx inc si jmp output_filename_loop found: MOV ah, 3Dh MOV al, 00 MOV dx, offset input INT 21h JC file_error MOV dFail, ax MOV ah, 3Ch MOV cx, 0 MOV dx, offset output INT 21h JC file_error MOV rFail, ax read: MOV bx, dFail CALL ReadBuf CMP ax, 0 JE closeInput MOV cx, ax MOV si, offset skBuf processLoop: MOV dl, [si] CMP dl, '0' JB notDigit CMP dl, '9' JA notDigit PUSH cx PUSH si PUSH di CALL ConvertDigitToWord POP di POP si POP cx JMP skip notDigit: MOV [di], dl INC di INC raBufPos skip: INC si DEC cx JNZ processLoop writeOutput: MOV cx, raBufPos MOV bx, rFail MOV dx, offset raBuf CALL WriteBuf MOV di, offset raBuf MOV raBufPos, 0 JMP read file_error: MOV ah, 09h MOV dx, offset msgFileError INT 21h jmp programEnd closeOutput: MOV ah, 3Eh MOV bx, rFail INT 21h JC file_error closeInput: MOV ah, 3Eh MOV bx, dFail INT 21h programEnd: MOV ah, 4Ch MOV al, 0 INT 21h ConvertDigitToWord PROC SUB dl, '0' MOV cl, dl MOV si, offset wordOffsets MOV bx, cx SHL bx, 1 ADD si, bx MOV ax, [si] ADD ax, offset words MOV si, ax copyWord: MOV al, [si] CMP al, 0 JE doneCopy MOV [di], al INC di INC si INC raBufPos JMP copyWord doneCopy: RET ConvertDigitToWord ENDP ReadBuf PROC MOV ah, 3Fh MOV bx, dFail MOV cx, 20 MOV dx, offset skBuf INT 21h RET ReadBuf ENDP WriteBuf PROC MOV ah, 40h MOV bx, rFail MOV cx, raBufPos MOV dx, offset raBuf INT 21h RET WriteBuf ENDP END start
问题根源
核心错误在于调用ConvertDigitToWord前后错误地保存和恢复了di寄存器:
ConvertDigitToWord函数会将数字对应的单词写入raBuf,并通过INC di更新di的位置,使其指向单词末尾的下一个字节,方便后续字符继续写入。- 但原代码中调用该函数前
PUSH di,调用后POP di,强行将di恢复到调用前的位置,导致后续字符会覆盖之前写入的单词开头部分。
比如输入0a时:
- 处理数字
0,ConvertDigitToWord将nulis写入raBuf[0-4],di指向raBuf[5]。 - 但
POP di后,di回到raBuf[0],处理字符a时直接将a写入raBuf[0],覆盖了原来的n。 - 最终
raBuf中的内容变为aulis+a,输出时就出现了错误的aulis。
修复方案
移除processLoop中调用ConvertDigitToWord前后的PUSH di和POP di指令,保留di的更新结果:
processLoop: MOV dl, [si] CMP dl, '0' JB notDigit CMP dl, '9' JA notDigit PUSH cx PUSH si ; 移除 PUSH di CALL ConvertDigitToWord ; 移除 POP di POP si POP cx JMP skip
验证效果
修复后,输入0a时:
- 处理
0,di从raBuf[0]更新到raBuf[5],raBufPos变为5。 - 处理
a,写入raBuf[5],di更新到raBuf[6],raBufPos变为6。 - 写入输出文件的内容为
nulisa,符合预期。
内容的提问来源于stack exchange,提问作者Denver
相关产品推荐
相关产品推荐

