Home > Blockchain >  Working with strings from file YASM (8086)
Working with strings from file YASM (8086)

Time:11-11

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 calls that were made before the jmp to .close can pass in all safety.

  • Related