I've been working on the project. The main goal is to calculate how many words do not contain letters from 'a' to 'k'. Given file has [0;1000] lines. Every line contains 6 columns.
The first two columns contain string with [1; 20] characters. Characters could be letters, numbers, and whitespaces.
3-5 columns contain integers in the range [-100; 100]. 6th column contains real numbers in the range [-9.99; 9.99] with only two digits after the decimal point.
Each section I separated by a semicolon ';'.
helloA;lB;lC;lD;lE;lF
A11;bas morning;0;0;5;1.15
My problem is, that if there is a newLine at the end of the file, skip them, and sum up them in the final count.
TASK: calculate how many words (the word is one or more symbols without ' '(space)) in the first two columns do not contain letters 'B' or 'C'. And print that integer number.
I have tried to compare al with 0x20 and jump to the next section if it is smaller, but that didn't help me.
What I have done so far
; Main
.whileNotTheEndOfFile:
mov si, 2
call procSkaitytiEilute
; Check the first two columns
;mov al, ';'
mov di, line
.skipSpaces:
mov al, [di]
inc di
cmp al, ' '
je .skipSpaces
cmp al, ';'
je .q3
dec di
.checkWord:
mov bx, 1
.q1:
mov al, [di]
inc di
cmp al, ' '
je .q2
cmp al, ';'
je .q2
jmp .q8
.q8:
cmp al, 20h
jl .skipLine
jmp .q7
.q7:
cmp al, 'A'
jl .q5
jmp .q4
.q4:
cmp al, 'K'
jae .q5
mov bx, 0 ; One or more invalid chars in current word
jmp .q1
.q5:
cmp al, 'a'
jae .q6
jmp .q1
.q6:
cmp al, 'k'
jae .q1
mov bx, 0
jmp .q1
.q2:
add [lineCount], bx ; BX=[0,1] Counting the 'good' words
cmp al, ';'
jne .skipSpaces
.q3:
dec si ; Next column?
jnz .skipSpaces
.skipLine:
cmp [readLastLine], byte 0
je .whileNotTheEndOfFile
; Jeigu ne failo pabaiga, kartojame cikla
.skipLine:
sub [lineCount], 2
cmp [readLastLine], byte 0
je .whileNotTheEndOfFile
; Hexadecimal convertion to decimal
mov dx, lineCount
mov ax, [lineCount]
call procUInt16ToStr
call procPutStr
macNewLine
mov si, dx
.writeToFile:
lodsb
cmp al, 0
jne .writeToFile
sub si, dx
lea cx, [si-1]
mov bx, [writingDescriptor]
mov ah, 40h
int 21h
; Closing Files
.end:
mov bx, [writingDescriptor]
call procFClose
.rasymoKlaida:
mov bx, [readingDescriptor]
call procFClose
exit
%include 'yasmlib.asm'
; void procSkaitytiEilute()
; Read line to buffer ‘eilute’
procReadLine:
push ax
push bx
push cx
push si
mov bx, [readingDescriptor]
mov si, 0
.loop:
call procFGetChar
; End if the end of file or error
cmp ax, 0
je .endOfFile
jc .endOfFile
; Putting symbol to buffer
mov [line si], cl
inc si
; Check if there is \n?
cmp cl, 0x0A
je .endOfLine
jmp .loop
.endOfFile:
mov [readLastLine], byte 1
.endOfLine:
mov [line si], byte '$'
mov [lineLength], si
pop si
pop cx
pop bx
pop ax
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .data
readingFile:
db 'input.dat', 00
readingDescriptor:
dw 0000
writingFile:
times 128 db 00
writingDescriptor:
dw 0000
readLastLine:
db 00
line:
db 64
times 66 db '$'
lineLength:
dw 0000
lineCount:
times 128 db 00
My file:
XYZ;PPP;1;1;1;1.00
A11;bas aaa;0;0;5;1.15
My output: 4
Needed output: 2 (because there are only 2 "good" words "XYZ" and "PPP"), my program counts 2 more words because of a new line at the end.
CodePudding user response:
It would appear that in contrast with the original task description your file can contain one or more empty lines as well. Or even lines with spaces followed by the newline codes.
To deal with these empty lines (only containing the bytes 13 and 10), your idea to skip on codes below 32 is good, but it's in the wrong place.
Below is the quick fix. Please notice that the ASCII codes are to be treated as unsigned numbers. Don't use the signed jl
instruction on them.
mov di, line
.skipSpaces:
mov al, [di]
inc di
cmp al, ' '
je .skipSpaces
cmp al, ';'
je .q3
dec di
cmp al, 32 ; NEW
jb .skipLine ; NEW
.checkWord:
mov bx, 1
.q1:
mov al, [di]
inc di
cmp al, ' '
je .q2
cmp al, ';'
je .q2
! cmp al, 'A'
! jb .q1
! cmp al, 'K'
! jbe .badChar ; [A,K] is bad
! cmp al, 'a'
! jb .q1
! cmp al, 'k'
! ja .q1
! .badChar: ; [a,k] is bad
! mov bx, 0 ; One or more invalid chars in current word
jmp .q1
.q2:
add [lineCount], bx ; BX=[0,1] Counting the 'good' words
cmp al, ';'
jne .skipSpaces
.q3:
dec si ; Next column?
jnz .skipSpaces
.skipLine:
cmp [readLastLine], byte 0
je .whileNotTheEndOfFile
The lines that I marked with an exclamation mark really should be:
or al, 32 ; Make lowercase
cmp al, 'a'
jb .q1
cmp al, 'k'
ja .q1
mov bx, 0 ; [A,K] and [a,k] are badChars
Why does your program contain next redundant lines?
; Jeigu ne failo pabaiga, kartojame cikla .skipLine: sub [lineCount], 2 cmp [readLastLine], byte 0 je .whileNotTheEndOfFile