x86 ASM - 逐行读取

x86 ASM - Read line by line

好吧,我只想逐行读取文本,然后输出。


我做的事情:


问题:


.txt example

    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  

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

您有:

zero_terminator:
        mov [si], 0 

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

        mov byte ptr [si], 0 

你在这行有一个错字,末尾有一个冒号:

        jmp read_line:

应该是:

        jmp read_line

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

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

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

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

一旦你打印出一行你inc SI 和return 来阅读字符。由于您已经打印出该行,您也可以通过将 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