assembly 如何正确计算文件中特定位置数字总和?(YASM 8086)

kknvjkwl  于 2022-11-24  发布在  其他
关注(0)|答案(1)|浏览(110)

我的输入文件中有一行文本,分为列。列之间用分号分隔。
以下是输入文件示例:
A1;example;10;0;55;2.44
我只看第三列的数字,这里是10,所以它的位数之和是1,根据任务要求,总和必须是7
我读了这一行,把它存到缓冲区里,然后逐字节移到第三个comumn开始的地方。

; 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
laximzn5

laximzn51#

; Skip one column
mov di, inputBuffer
.whileNotSemicolon:
    cmp di, byte ';'
    je .semicolon
    inc di
    jmp .whileNotSemicolon
    .semicolon:
        inc di

这段代码不可能 * 跳过一列 *!cmp di, byte ';'没有任何意义。它比较的是指针而不是指针所指向的字节。您需要:

.whileNotSemicolon:
    cmp  [di], byte ';'
    je   .semicolon
    inc  di
    jmp  .whileNotSemicolon
    .semicolon:
        inc di

但更好的解决方案是尽量减少分支,如下面的代码所示:

.whileNotSemicolon:
    mov  al, [di]
    inc  di
    cmp  al, ';'
    jne  .whileNotSemicolon
.semicolon:

在这种情况下,它将是数字10,所以它的数字总和是1。根据 * 任务要求 *,总和必须是7
我看不出这7应该从哪里来!
你的帖子没有提到这一点,但是你没有解决与this extremely similar question相关的任务,其中第3、4和5列包含[-100,100]范围内的数字的可能性有多大。
已知第3列只能包含{-0123456789;},对数字求和的任务包括:

  • 从第3列加载一个字节
  • 将字符转换为相应的数字减去48
  • 如果它是-1(ASCII=45),则结果将是-3,这将在sub al, '0'上产生进位
  • 如果是分号(ASCII=59),则结果将是大于9的11
; IN (di) OUT (di)
procDigitsSum
    push ax
    push cx
    xor  cx, cx
    xor  ax, ax
.loop:
    add  cx, ax
.minus:
    mov  al, [di]
    inc  di
    sub  al, '0'
    jb   .minus          ; It's a minus
    cmp  al, 9
    jbe  .loop           ; It's a digit
.above:                  ; It's a semicolon
    mov  [digitsSum], cx
    pop  cx
    pop  ax
    ret                  ; DI points at next column

1如果允许空格,它将遵循与减号相同的路径。

相关问题