如何在YASM 8086中正确计算文件指定列的数字之和?
汇编问题:第三列数字数位和计算错误修正
问题背景
输入文件每行被分号划分为6列,示例行:A1;example;10;0;55;2.44。我们需要计算第三列数字的数位和(如示例中10的数位和为1),但现有代码无法正确实现该逻辑,推测错误出在procDigitsSum函数的.secondLoop部分。
现有代码片段
主程序核心逻辑
; Save line into buffer call procGetLine ; Skip one column mov di, inputBuffer .whileNotSemicolon: cmp di, byte ';' ; 此处存在逻辑错误 je .semicolon inc di jmp .whileNotSemicolon .semicolon: inc di ; Do some calculations with second column and move to the start of third column ; ............ ; Call function that calculates sum of number digits in third column call procDigitsSum cmp [digitsSum], word 7 je .isSeven
procDigitsSum函数(问题核心)
procDigitsSum push si push ax push dx push cx push bx mov [digitsSum], word 0 mov si, 0 .loop: mov cl, [di] inc di cmp cl, byte ';' je .columnEnd ; ASCIIZ for using it in function later mov byte [thirdColumnNumber+si], cl mov byte [thirdColumnNumber+si+1], 0 inc si jmp .loop .columnEnd mov dx, thirdColumnNumber mov di, dx .secondLoop: ; Guessing mistake lies somewhere here mov dl, [di] inc di cmp dl, byte 0 je .endLoop add [digitsSum], dl add [digitsSum], byte 30h jmp .secondLoop .endLoop pop bx pop cx pop dx pop ax pop si ret
procGetLine函数(确认正常工作)
procGetLine: push ax push bx push cx push si mov bx, [inputFileDescriptor] mov si, 0 .loop call procFGetChar cmp ax, 0 je .endOfFile jc .endOfFile mov [inputBuffer+si], cl inc si cmp cl, 0Ah je .endOfLine jmp .loop .endOfFile: mov [lastLine], byte 1 .endOfLine: mov [inputBuffer+si], byte '$' mov [bytesRead], si pop si pop cx pop bx pop ax ret
错误分析
主程序列跳转逻辑错误:
原代码中cmp di, byte ';'是拿寄存器di的地址值和分号的ASCII值(3Bh)比较,完全不符合需求,正确写法应为比较di指向的内存内容:cmp byte ptr [di], ';'。
另外,如果注释中"处理第二列并跳转到第三列开头"的逻辑未实现,还需要补充跳过第二列的循环,确保di最终指向第三列第一个字符。procDigitsSum数位转换逻辑错误:- 原代码先把ASCII字符值直接加到总和,再额外加30h,完全搞反了ASCII转数字的逻辑:正确转换应为ASCII字符减去30h(如'1'的ASCII是31h,减30h得到数值1)。
- 保存ASCIIZ字符串时,每次循环都给
thirdColumnNumber+si+1设0是冗余操作,只需在列读取完成后在末尾加一次终止符即可。
修正后的代码
修正主程序列跳转逻辑
; Save line into buffer call procGetLine ; Skip first column mov di, inputBuffer .whileNotSemicolon1: cmp byte ptr [di], ';' ; 修正:比较内存内容而非寄存器地址 je .semicolon1 inc di jmp .whileNotSemicolon1 .semicolon1: inc di ; Skip second column to reach third column start .whileNotSemicolon2: cmp byte ptr [di], ';' je .semicolon2 inc di jmp .whileNotSemicolon2 .semicolon2: inc di ; Call function that calculates sum of number digits in third column call procDigitsSum cmp [digitsSum], word 7 je .isSeven
修正后的procDigitsSum函数
procDigitsSum push si push ax push dx push cx push bx mov [digitsSum], word 0 mov si, 0 .loop: mov cl, [di] inc di cmp cl, ';' je .columnEnd ; 保存当前数字字符到缓冲区 mov byte [thirdColumnNumber+si], cl inc si jmp .loop .columnEnd: ; 仅在末尾添加一次ASCII终止符 mov byte [thirdColumnNumber+si], 0 mov di, thirdColumnNumber .secondLoop: mov dl, [di] inc di cmp dl, 0 je .endLoop ; ASCII转数字:减去30h sub dl, 30h ; 扩展为16位避免溢出,再累加到总和 mov al, dl cbw add [digitsSum], ax jmp .secondLoop .endLoop: pop bx pop cx pop dx pop ax pop si ret
内容的提问来源于stack exchange,提问作者user10203585
相关产品推荐
相关产品推荐

