【问题标题】:How to write decimal number by one char to file 8086 YASM如何将一个字符的十进制数写入文件 8086 YASM
【发布时间】:2022-11-12 07:32:35
【问题描述】:

我有一个任务,我会尽量解释清楚。有一个文件 [0; 1000] 行。每行包含 6 列。

前两列包含细绳与 [1; 20] 个字符。字符可能是字母、数字和空格.

3-5 列包含范围内的整数[-100; 100]. 第 6 列包含范围内的实数[-9.99; 9.99]小数点后只有两位数。

每个部分我用分号';'分隔。

文件示例:

helloA;lB;lC;lD;lE;lF
A11;bas morning;0;0;5;1.15
B12; Hello WoRlD;-100;11;78;1.33
B11;table;10;0;55;-2.44
C1;OakWood;0;8;17;3.77

任务:计算前两部分中有多少行包含字母“B”和“C”。并在另一个文件中打印该整数。

我几乎完成了所有任务,除了一件事。我不知道如何在文件中打印十进制数。我将此数字存储在内存中十六进制.我需要将该数字转换为十进制并将其打印到另一个文件中。

我很挣扎,因为可能有 1 条好线,但也可能有 1000 条好线。所以我需要打印 1 个字符(如果好行数在 [0; 9] 之间),但它可能是 900 行好行,所以程序必须打印 3 个字符。

我的代码

org 100h

%include 'yasmmac.inc'

section .text

    startas:
        macPutString 'Output file:', crlf, '$'
        
            ; Save the writing file's name
        mov al, 128         
        mov dx, writingFile
        call procGetStr     
        macNewLine
        
        ; Open reading file
        mov dx, readingFile
        call procFOpenForReading
        jnc .writingFileOpen
        macPutString 'Error while opening the writing file!', '$'
        exit
        
        ; Open the writing file
        .writingFileOpen:
            mov [readingDescriptor], bx
            mov dx, writingFile
            call procFCreateOrTruncate
            jnc .writingFileSuccessfullyOpened
            macPutString 'Error while opening file for writing!', '$'
            jmp .writingError
        
        ; Sacing writing descriptor
        .writingFileSuccessfullyOpened:
            mov [writingDescriptor], bx
            
            
        ; Read first line
        call procReadLine
        
        ; Main loop
        .untilEndOfFile:
            call procReadLine
            
            ; checking the first two columns
            ;mov al, ';'
            
            ; checking first column
            .firstColumn:
                mov al, [di]
                inc di
                
                cmp al, byte 'B'
                je .skipALine
                cmp al, byte 'b'
                je .skipALine
                cmp al, byte 'C'
                je .skipALine
                cmp al, byte 'c'
                je .skipALine
                
                cmp al, byte ';'
                jne .firstColumn
                
            ; checking second column
            .secondColumn:
                mov al, [di]
                inc di
                
                cmp al, byte 'B'
                je .skipALine
                cmp al, byte 'b'
                je .skipALine
                cmp al, byte 'C'
                je .skipALine
                cmp al, byte 'c'
                je .skipALine
                
                cmp al, byte ';'
                jne .secondColumn
                jmp .addNumber      ; Adding number because line corresponds to filter.
                
            .addNumber:
                call procAddNumber
                
            
            ; If it is not the end of file, jump back to main loop
            .skipALine:
            cmp [readTheLastLine], byte 0
            je .untilEndOfFile
            
            ; Writing to file (number, how many good lines)
            ; **I cant do this part**
            mov bx, [writingDescriptor]
            mov cx, 2h
            mov dx, lineCount
            mov ah, 40h
            int 21h
        
        
        ; Closing Files
        .end:
            mov bx, [writingDescriptor]
            call procFClose
        
        .writingError:
            mov bx, [readingDescriptor]
            call procFClose
        
        exit
        
%include 'yasmlib.asm'

; void procReadLine()
; Read line to buffer 'line'
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 [readTheLastLine], byte 1
    .endOfLine:
    
    mov [line+si], byte '$'
    mov [lineLength], si
    
    pop si
    pop cx
    pop bx
    pop ax
    ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    
procAddNumber:
    push si
    push ax
    push bx
    push cx
    push dx
    
    ;lineCount++
    mov ax, [lineCount]
    inc ax
    mov [lineCount], ax
    
    pop dx
    pop cx
    pop bx
    pop ax
    pop si
    ret

section .data

    readingFile:
        db 'input.dat', 00
        
    readingDescriptor:
        dw 0000
        
    writingFile:
        times 128 db 00
        
    writingDescriptor:
        dw 0000
        
    readTheLastLine:
        db 00
        
    line:
        db 64
        times 66 db '$'
        
    lineLength:
        dw 0000
    
    lineCount:
        dw 0000

宏的 GitHub 链接:yasmlib.asm/yasmmac.inc

任何帮助,将不胜感激。

【问题讨论】:

    标签: file assembly decimal x86-16 yasm


    【解决方案1】:

    我不知道如何打印文件中的十进制数。我将这个数字以十六进制形式存储在内存中。我需要将该数字转换为十进制并将其打印到另一个文件中。

    问题的解决方案已经在yasmlib.asm文件中了!它包含一个代码procUInt16ToStr这会将 AX 中的无符号数字转换为 DX 中地址处的 ASCIIZ 字符串。
    它不返回字符串的长度,因此您必须遍历字符串并使用procFPutChar将单个字符发送到文件。或者,最好在字符串上循环以建立字符串长度并使用 DOS 函数 40h 一次全部输出(就像你已经在做的那样)。

    如果您有兴趣了解如何要将整数转换为字符串,您可以阅读我的 Q/A Displaying numbers with DOS

    .WritingToFile:
      mov  dx, Buffer
      mov  ax, [linecount]
      call procUInt16ToStr  ; produces an ASCIIZ string at DX
      mov  si, dx
    .again:
      lodsb
      cmp  al, 0
      jne  .again
      sub  si, dx
      lea  cx, [si - 1]     ; -1 because we don't want to send the zero
      mov  bx, [writingDescriptor]
      mov  ah, 40h          ; DOS.WriteToFile
      int  21h              ; -> AX CF
    

    小心这些

    .untilEndOfFile:
        call procReadLine
        .firstColumn:
            mov al, [di]
    

    此代码在未初始化寄存器 (mov di, line) 的情况下使用 DI。

    .skipALine:
        cmp [readTheLastLine], byte 0
        je .untilEndOfFile
    

    检查读最后一行变量来得太晚了!您需要在从procReadLine程序:

    .untilEndOfFile:
        call procReadLine
        cmp  byte [readTheLastLine], 0
        je   .WritingToFile
        mov  di, line
    .firstColumn:
        mov al, [di]
        ...
        jmp  .untilEndOfFile
    .WritingToFile:
    

    你不需要那么浪费procAddNumber程序来增加行数多变的。
    只需将call procAddNumber 替换为inc word [linecount]

    【讨论】:

      【解决方案2】:

      虽然另一个答案涉及您关于编写数字的文本表示的问题,但此答案集中在对任务要求的基本误解上。

      任务:计算前两个部分中有多少行包含字母“B”和“C”

      您当前的程序正在计算既不包含“B”也不包含“C”的行。与所问的相反。接下来将为您提供包含“B”或“C”的行数。

      .untilEndOfFile:
          call procReadLine
          cmp  byte [readTheLastLine], 0
          je   .WritingToFile
      
          ...
      
          jne  .secondColumn
          jmp  .untilEndOfFile
      .skipALine:
          inc  word [linecount]
          jmp  .untilEndOfFile
      .WritingToFile:
      

      请注意,上面仍然不是字面上“包含字母'B''C'”,更像是“包含字母 'B'或者'C'”。但别担心,在编程中非常重要的区别在日常演讲/写作中可能并不总是被认为那么重要。

      【讨论】:

        猜你喜欢
        • 2022-11-12
        • 2021-10-27
        • 2013-05-03
        • 1970-01-01
        • 2010-10-12
        • 2010-11-26
        • 2018-09-10
        • 2014-03-16
        • 2015-01-03
        相关资源
        最近更新 更多