Home > Mobile >  how to properly calculate sum of digits from specific place in file? (YASM 8086)
how to properly calculate sum of digits from specific place in file? (YASM 8086)

Time:11-25

I have one line of text in my input file, which is divided into six columns. Columns are separated from each other by a semicolon.

Here is input file example:

A1;example;10;0;55;2.44

I am looking only into third column number. In this case it would be number 10, so the sum of its digits is 1. According to the task requirements, the sum has to be 7

I read the line, save it into buffer. Then byte by byte I move to the place where third comumn starts.

    ; 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 function:

    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 function just in case, however it seems to work fine:

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

CodePudding user response:

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

This code can't possibly skip one column! The cmp di, byte ';' makes no sense. It compares the pointer instead of the byte that the pointer points at. You need:

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

But an even better solution tries to minimize the branching like in next code:

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

In this case it would be number 10, so the sum of it's digits is 1. According to the task requirements, the sum has to be 7

I don't see where this 7 should come from!


Your post doesn't mention this, but what are the chances that you are not solving a task related to this extremely similar question where the 3rd, 4th, and 5th columns contain numbers in the range [-100,100].
Knowing that the 3rd column can only contain {-0123456789;}, the task to sum the digits comprises:

  • loading a byte from the 3rd column
  • converting the character into the corresponding digit subtracting 48
  • if it was the minus1 (ASCII=45), the result will be -3 which will have produced a carry on sub al, '0'
  • if it was the semicolon (ASCII=59), the result will be 11 which is above 9
; 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 If whitespace were allowed, it would follow the same path as the minus did.

  • Related