【问题标题】:x86 ASM - Read line by linex86 ASM - 逐行读取
【发布时间】:2015-11-10 20:52:01
【问题描述】:

好的,我要做的就是从文本中逐行读取然后输出。


我做的事情:

  • 读取单个字符,添加到字符串
  • 搜索 LF
  • 输出字符串
  • 从头再来,直到 EOF

问题:

  • 不知道如何在它忙于 3Fh 时计算 40h 中断的 cx(尝试创建一些新变量,但最终出现一堆错误)
  • 某种奇怪的结果 - 几个空行和最后一个

.txt 示例

    some
    random

    text
    .model small

    .stack  100h 

    .data 
            filename    db 255 dup(0)   
            text        db 255 dup(0)
            char        db ?
            line        db 255 dup(0)           

            filehandle  dw ?

    .code 
            newline macro    ;NEW LINE 
                             ;
            mov dl, 10       ;
            mov ah, 02h      ;                   
            int 21h          ;
                             ;
            mov dl, 13       ;
            mov ah, 02h      ;                     ;
            int 21h          ;                
            endm             ;NEW LINE
    main:   

            mov ax, @data    
            mov ds, ax   

            lea si, filename
            mov ah, 01h      ;read character

    char_input:

            int 21h         

            cmp al, 0dh      ;enter     
            je zero_terminator

            mov [si], al    
            inc si

            jmp char_input  

    zero_terminator:

            mov [si], 0 

    open_file:

            lea dx, filename         
            mov al, 0          
            mov ah, 3Dh      ;open file
            int 21h  

            mov filehandle, ax

            lea si, text   

            newline

    read_line:
            mov ah, 3Fh      ;read file
            mov bx, filehandle  
            lea dx, char         
            mov cx, 1  

            int 21h  

            cmp ax, 0       ;EOF            
            je EO_file

            mov al, char        

            cmp al, 0ah     ; line feed
            je LF  

            mov [si], al
            inc si      

            jmp read_line:

    EO_file:

            lea dx, text
            mov ah, 40h     ;print 
            mov cx, 255
            mov bx, 1       
            int 21h

            mov ah, 4ch     
            int 21h 

    LF:       
            lea dx, text
            mov ah, 40h     ;print
            mov cx, 255
            mov bx, 1

            int 21h

            inc si
            jmp read_line

     end main  

【问题讨论】:

  • 您似乎一次读取一个字符的文本文件。如果您只想在最后一次输出所有行,为什么不进行一次大读取呢?你的代码中没有足够多的 cmets,所以我不知道那些 DOS 系统调用甚至应该做什么。 (因为幸运的是我从来没有为 DOS 编写过代码。)用系统调用的名称来注释系统调用号将是一个好的开始。
  • 这不是一个完整的程序,只是一个开始。稍后我将不得不从每一行的用户输入中找到一些字符串。
  • 您能等到用户输入之后再读取文件吗?或者,如果您需要将整个文件保存在内存中,您可能应该有超过 255 个字符的空间!在读取时将其标记为行,并将偏移量数组存储到每行的开头可能会很有用。否则,您只需在搜索时动态检测换行符。或者你是用'\0'分隔它们而不是换行吗?我还没弄清楚你的程序是怎么设计的。
  • 你能编译这段代码吗? jmp read_line: 末尾有一个额外的冒号应该是 jmp read_line 。由于 TASM 不知道此语句 mov [si], 0 中操作数的大小(您要移动一个字节还是一个字?)它应该是 mov byte ptr [si], 0,因为您似乎正在处理单个字节(字符)

标签: assembly x86 dos x86-16 tasm


【解决方案1】:

这是为了让您继续前进,而不是解决代码中的所有错误:

你有:

zero_terminator:
        mov [si], 0 

这个想法是将一个 0 字节移动到 SI 指向的位置。 TASM 不明白您想要将单个字节移动到 [SI],因此应该明确告知这是您的意图:

        mov byte ptr [si], 0 

你在这一行有一个错字,最后有一个冒号:

        jmp read_line:

应该是:

        jmp read_line

您的代码的主要问题是,当要打印读入 text 字符数组的字符时,您需要在 CX 中指定要打印的字符数。您可以使用如下代码指定 255:

LF:
        lea dx, text
        mov ah, 40h     ;print
        mov cx, 255

由于 SI 包含指向最后读取的字符的指针,您可以从 SI 中减去 text 的地址(偏移量)以获得缓冲区中的字符数。所以上面的可以改成:

LF:
        lea dx, text
        mov ah, 40h     ;print
        mov cx, si      ;CX = # characters. Move pointer to last char to it
        sub cx, dx      ;Subtract the offset of text (in DX) from CX
                        ;To get the actual number of chars in the buffer

一旦你打印出一行,你就会加入 SI 并返回读取字符。由于您已打印出该行,您还可以通过将 SI 重置为开头,从 text 缓冲区的开头重新开始:

        mov si, dx ; start from beginning of buffer (DX=beginning of text buffer)

或者你可以移动 DX 已经包含 text 的偏移量并设置 SI 到它:

这与您在开始读取数据时最初设置的方式相同。

您的EOF 代码也有类似的问题,它要求将缓冲区中的字节数放入ECX。所以这段代码:

EO_file:

        lea dx, text
        mov ah, 40h     ;print
        mov cx, 255
        mov bx, 1
        int 21h

可以改为:

LF:
        lea dx, text
        mov ah, 40h     ;print
        mov cx, si      ;CX = # characters. Move pointer to last char to it
        sub cx, dx      ;Subtract the offset of text (in DX) from CX
                        ;To get the actual number of chars in the buffer

通过所有这些更改,您将获得如下程序:

    .model small
    .stack  100h

    .data
            filename    db 255 dup(0)
            text        db 255 dup(0)
            char        db ?
            line        db 255 dup(0)

            filehandle  dw ?

    .code
            newline macro    ;NEW LINE
                             ;
            mov dl, 10       ;
            mov ah, 02h      ;
            int 21h          ;
                             ;
            mov dl, 13       ;
            mov ah, 02h      ;                     ;
            int 21h          ;
            endm             ;NEW LINE
    main:

            mov ax, @data
            mov ds, ax

            lea si, filename
            mov ah, 01h      ;read character

    char_input:

            int 21h

            cmp al, 0dh      ;enter
            je zero_terminator

            mov [si], al
            inc si

            jmp char_input

    zero_terminator:

            mov byte ptr [si], 0

    open_file:

            lea dx, filename
            mov al, 0
            mov ah, 3Dh      ;open file
            int 21h

            mov filehandle, ax

            lea si, text

            newline

    read_line:
            mov ah, 3Fh      ;read file
            mov bx, filehandle
            lea dx, char
            mov cx, 1

            int 21h

            cmp ax, 0       ;EOF
            je EO_file

            mov al, char

            cmp al, 0ah     ; line feed
            je LF

            mov [si], al
            inc si

            jmp read_line

    EO_file:

            lea dx, text    ;DX=offset(address) of text
            mov ah, 40h     ;print
            mov cx, si      ;CX = # characters. Move pointer to last char to it
            sub cx, dx      ;Subtract the offset of text (in DX) from CX
                            ;To get the actual number of chars in the buffer
            mov bx, 1
            int 21h

            mov ah, 4ch
            int 21h

    LF:
            lea dx, text    ;DX=offset(address) of text
            mov ah, 40h     ;print
            mov cx, si      ;CX = # characters. Move pointer to last char to it
            sub cx, dx      ;Subtract the offset of text (in DX) from CX
                            ;To get the actual number of chars in the buffer
            mov bx, 1

            int 21h

            mov si, dx      ;Start from beginning of buffer 
                            ;(DX=beginning of text buffer)
            jmp read_line

     end main

【讨论】:

  • 完美! mov si, dx 是我真正需要的!谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-16
  • 2010-11-07
  • 1970-01-01
相关资源
最近更新 更多