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.