assembly 使用文件YASM中的字符串(8086)

yruzcnhs  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(127)

我有一个任务要做。我会尽量解释清楚。
当你运行程序时,它要求输入(阅读文件和写文件)。
正在阅读文件具有范围[1; 999]。每行有六列。每列用分号(;).

  • 第一列和第二列 * 包含文本符号,范围为[1;[第20段]。
  • 第三-第五 * 列包含整数[-100; 100页]。
  • 最后一列 * 包含浮点数[-9.99; 9.99].点后带两个符号。
    文件示例:
firstA;lB;lC;lD;lE;lF
A11;bas hello;0;0;5;1.15
B12; good day;-100;11;78;1.33

**任务:**输出:仅 * 第一列和第二列 *,不包含数字和符号'B','C'
输出:

firstA,因为只有此列没有'B'、'C'和数字。
到目前为止,我写的程序,只是扔掉了数字和符号。我不能想出解决整个任务

我的程序

%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
6jjcrrmo

6jjcrrmo1#

网上没有太多关于“yasmmac.inc“的信息,但我相信我对这些 procFGetCharprocFPutChar 宏的解释不会太离谱...
如果你不使用模块化的方法,这个任务看起来会太复杂。你需要把比较简单的子任务委托给独立的子程序。此外,从数据的来源进行抽象也是有意义的。不要从文件中读取一个字符,然后立即将其分类。不,从文件中提取一个完整的行,并从内存副本中处理所请求的字段。2这样会容易得多,也不容易出现与文件访问相关的错误。

.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

文本文件中的每一行都以回车符和换行符对(13,10)结束。因此,找到10表示EOL。
从DOS接收到AX=0意味着文件结束。如果这发生在我们的缓冲区中还没有字符的时候,它就发出一个正常的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
; ----------------------
  • field* 子例程完成了这个程序的神奇功能,但即使 it 也会将字符的分类委托给下一个子例程。这将增强可读性。作为一条经验法则,我尽量将每个子例程保持在一个屏幕(25行)的范围内。因为这段代码将以SI指向当前字段后结束,所以继续第二个字段将真实的容易。
; ----------------------
; 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
; ----------------------

.fgets* 和 .fputc 中存在错误,需要平衡堆栈!* 它们需要“忘记”在jmp to .close 可以安全传递 * 之前生成的call

相关问题