【问题标题】:Working with strings from file YASM (8086)使用文件 YASM (8086) 中的字符串
【发布时间】:2022-11-12 00:54:29
【问题描述】:

我有一项任务要做。我会尽量解释清楚。

当您运行程序时,它会要求输入(读取文件和写入文件)。

读取文件的行范围为 [1; 999]。每行有六列。每列用分号 (;) 分隔。

第一和第二columns 包含范围 [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”。

输出:

fiestA,因为只有这一列没有'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

【问题讨论】:

  • 如果你用 C 写它,你会怎么做?你能把它翻译成asm吗?目前尚不清楚您应该打印什么输出,例如如果字段 2 不包含任何 A 或 B 字符但字段 1 在该行上包含,则是否应该单独打印字段 2。此外,如果你只是扔掉';,你将不知道字段从哪里开始/结束。在我看来,您只需遍历每行的前 2 个字段,每次到达 ; 时,如果该字段不包含您拒绝的任何字符,则打印该字段。

标签: file assembly dos x86-16 yasm


【解决方案1】:

在网上找不到太多关于“yasmmac.inc”的内容,但我相信我对这些内容的解释procFGetCharprocFPutChar宏不会太远......

如果您不使用模块化方法,任务将显得过于复杂。您需要将更简单的子任务委派给单独的子例程。此外,从数据的来源中抽象出来是有意义的。不要从文件中读取单个字符并立即对其进行分类。不,从文件中获取完整的行并从内存副本中处理请求的字段。这将变得更容易,更不容易出现与文件访问相关的错误。

.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
; ----------------------

场地子程序完成了这个程序的魔力,但即使将把字符的分类委托给另一个子程序。这将增强可读性。根据经验,我尝试将每个子程序保持在一个屏幕(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 之前制作的calls。关可以安全通过.

【讨论】:

    猜你喜欢
    • 2022-11-12
    • 2022-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多