I have one task to do. I will try to explain it as clearly as possible.
When you run the program, it asks to input (reading file and writing file).
Reading file has lines in range [1; 999]. Every line has six columns. Every column is separated by semicolon (;).
First and second columns contains text symbols in range [1; 20].
Third - fifth columns contains integers [-100; 100].
Last column contains floating number [-9.99; 9.99]. With two symbols after point.
FILE EXAMPLE:
firstA;lB;lC;lD;lE;lF
A11;bas hello;0;0;5;1.15
B12; good day;-100;11;78;1.33
TASK: Output: Only first and second columns, that doesn't contain numbers and symbols 'B', 'C'.
OUTPUT:
firstA, because only this column doesn't have 'B', 'C' and numbers.
Up to now I have written program, that just throws away numbers and symbols. I can't figure out the solution for the full TASK.
My program
%include 'yasmmac.inc'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
org 100h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .text
startas:
macPutString 'Reading file name:', crlf, '$' ;Input for reading file
mov al, 128
mov dx, readingFile
call procGetStr
macNewLine
macPutString 'Writing file name: ', crlf, '$' ;Input for writing file
mov al, 128
mov dx, writingFile
call procGetStr
macNewLine
push readingFile
push writingFile
call function
exit
;Main Function
function:
push bp
mov bp, sp
sub sp, 4
push dx
push bx
push ax
mov dx, [bp 6]
call procFOpenForReading
jnc .secondFOpen
macPutString 'Error while opening file', crlf, '$'
jmp .end
.secondFOpen:
mov [bp-2], bx
mov dx, [bp 4]
call procFCreateOrTruncate
jnc .filter
macPutString 'Error while opening writing file', crlf, '$'
jmp .close
.filter:
mov [bp-4], bx
.whileNotTheEnd:
mov bx, [bp-2]
call procFGetChar
jnc .c1
macPutString 'Error while reading file', crlf, '$'
jmp .close
.c1:
cmp ax, 0 ; Checks if it is not the end of the file
jne .check
jmp .close ; If the end - close the file
.check:
mov al, cl
cmp al, ';' ; Checks if ';'
jne .c2
.c2:
cmp al, 30h ; Number checking
jge .c3
jmp .c4
.c3:
cmp al, 39h ; Number checking
jle .checkEnd
jmp .c4
.c4:
cmp al, 'B'
jne .c5
jmp .checkEnd
.c5:
cmp al, 'C'
jne .writing
jmp .checkEnd
.writing:
mov bx, [bp-4]
call procFPutChar
jnc .checkEnd
macPutString 'Error while writing file', crlf, '$'
jmp .close
.acheckEnd:
cmp ax, 0
jne .nextIteration
jmp .close
.nextIteration:
jmp .whileNotTheEnd
.close:
mov bx, [bp-4]
call procFClose
.closeReadingFile:
mov bx, [bp-2]
call procFClose
.end:
ret4
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%include 'yasmlib.asm'
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .data
writingFile:
times 255 db 00
readingFile:
times 255 db 00
duomenys:
times 255 db 00
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
section .bss
CodePudding user response:
There's not much about "yasmmac.inc" to be found online, but I believe that my interpretation of what these procFGetChar and procFPutChar macros do will not be too far off...
The task will seem too complicated if you don't use a modular approach. You need to delegate the simpler subtasks to separate subroutines. Further it would make sense to abstract from where the data is coming from. Don't read a single character from the file and immediately have it classified. No, fetch a complete line from the file and process the requested fields from the memory copy. It will be so much easier and less prone to errors related to file access.
.whileNotTheEnd:
; Fetch one line from the file
call .fgets ; -> DI (AX BX CL)
test di, di
jz .close ; Normal EOF
; Process fields 1 and 2 from the memory copy
mov si, Buffer
call .field ; -> SI (AX BX)
call .field ; -> SI (AX BX)
jmp .whileNotTheEnd
.close:
mov bx, [bp-4]
call procFClose
mov bx, [bp-2]
call procFClose
The lines in the text file each end with a carriage return and linefeed pair (13,10). Finding the 10 therefore denotes the EOL.
Receiving AX=0 from DOS means the end of the file. If this happens when we have not yet characters in our buffer, it signals a normal EOF.
; ----------------------
; IN (bp) OUT (di) MOD (ax,bx,cl)
.fgets:
mov bx, [bp-2] ; Handle
xor di, di ; Counts characters
.more:
call procFGetChar ; -> AX CL CF
jc .err1
test ax, ax ; EOF ?
jz .eof
mov [Buffer di], cl
inc di
cmp cl, 10
jne .more
.ret:
ret
.eof:
test di, di ; If DI==0 then Normal EOF
jz .ret
.err1:
macPutString 'Error while reading file', crlf, '$'
pop ax ; (*) Forget about `call fgets`
jmp .close
; ----------------------
The field subroutine does the magic of this program but even it will delegate to a further subroutine the classification of the character. This will enhance readability. As a rule of thumb, I try to keep each subroutine within the bounds of one screen (25 rows). Because this code will end with SI pointing after the current field, it will be real easy to continue with the 2nd field.
; ----------------------
; IN (si) OUT (si) MOD (ax,bx)
.field:
mov bx, si ; Remember the start of this field
.check:
lodsb
cmp al, ";"
je .write
call .test ; -> CF
jnc .check
.skip:
lodsb ; Skip remainder of this (bad) field
cmp al, ";"
jne .skip
ret
.write:
push si ; (1)
mov si, bx ; Send this field to file
lodsb
.w1:
call .fputc ; -> (AX BX)
lodsb
cmp al, ";"
jne .w1
pop si ; (1) SI points after the ";"
ret
; ----------------------
; IN (al) OUT (CF)
.test:
cmp al, "0"
jb .OK
cmp al, "9"
jbe .NOK
cmp al, "B"
je .NOK
cmp al, "C"
je .NOK
.OK:
clc
ret
.NOK:
stc
ret
; ----------------------
; IN (al,bp) OUT () MOD (ax,bx)
.fputc:
mov bx, [bp-4] ; Handle
call procFPutChar ; -> AX CF
jc .err2
test ax, ax
jz .err2
ret
.err2:
macPutString 'Error while writing file', crlf, '$'
pop ax ; (*) Forget about `call .fputc`
pop ax ; (*) Forget about `call .field`
jmp .close
; ----------------------
(*) The error exits in .fgets and .fputc need to balance the stack! They need "to forget" about the call
s that were made before the jmp
to .close can pass in all safety.