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

如何在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

错误分析

  1. 主程序列跳转逻辑错误:
    原代码中cmp di, byte ';'是拿寄存器di的地址值和分号的ASCII值(3Bh)比较,完全不符合需求,正确写法应为比较di指向的内存内容:cmp byte ptr [di], ';'。
    另外,如果注释中"处理第二列并跳转到第三列开头"的逻辑未实现,还需要补充跳过第二列的循环,确保di最终指向第三列第一个字符。

  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:35:18