Read txt on Assembly i8086

Asked

Viewed 873 times

1

I have the following code to read txt file:

; um programa que demonstra a criação de um arquivo e a
; leitura do mesmo

.model small
.stack
.code 

start:

mov ax,@data        ; endereço de base do segmento de dados
mov ds,ax       ; é colocado em ds

mov dx,OFFSET FileName  ; coloca o endereço do nome do arquivo em dx
mov al,2        ; modo de acesso - leitura e escrita
mov ah,3Dh      ; função 3Dh - abre um arquivo
int 21h         ; chama serviço do DOS

mov Handle,ax       ; guarda o manipulador do arquivo para mais tarde
jc ErrorOpening     ; desvia se carry flag estiver ligada - erro!

mov dx,offset Buffer    ; endereço do buffer em dx
mov bx,Handle       ; manipulador em bx
mov cx,100      ; quantidade de bytes a serem lidos
mov ah,3Fh      ; função 3Fh - leitura de arquivo
int 21h         ; chama serviço do DOS

jc ErrorReading     ; desvia se carry flag estiver ligada - erro!

mov bx,Handle       ; coloca manipulador do arquivo em bx
mov ah,3Eh      ; função 3Eh - fechar um arquivo
int 21h         ; chama serviço do DOS

mov cx,100      ; comprimento da string
mov si,OFFSET Buffer    ; DS:SI - endereço da string
xor bh,bh       ; página de vídeo - 0
mov ah,0Eh      ; função 0Eh - escrever caracter

NextChar:

lodsb           ; AL = próximo caracter da string
int 10h         ; chama serviço da BIOS
loop NextChar

mov ax,4C00h        ; termina programa
int 21h 

ErrorOpening:

mov dx,offset OpenError ; exibe um erro
mov ah,09h      ; usando a função 09h
int 21h         ; chama serviço do DOS
mov ax,4C01h        ; termina programa com um errorlevel =1 
int 21h 

ErrorReading:
mov dx,offset ReadError ; exibe um erro
mov ah,09h      ; usando a função 09h
int 21h         ; chama serviço do DOS
mov ax,4C02h        ; termina programa com um errorlevel =2
int 21h

.data
Handle DW ?             ; para guardar o manipulador do arquivo
FileName DB "C:\test.txt",0     ; arquivo a ser aberto
OpenError DB "Ocorreu um erro(abrindo)!$"
ReadError DB "Ocorreu um erro(lendo)!$"
Buffer DB 100 dup (?)   ; buffer para armazenar dados

END start

It would be possible to read until the end of the file without having to inform the amount of bytes to be read?

1 answer

0


To read the file without specifying the size, you need to read until you detect the end of the file.

An example of how to change the program to read larger files without specifying the size:

In the file read routine, modify to read a fixed size block and change the address of the buffer as the text blocks are read. To detect the end of the file, compare the amount of bytes read with the requested amount and finish if it is smaller (INT 21,3F):

        ...
        mov dx,offset Buffer    ; endereço do buffer em dx

    LerBloco:                   ; início da leitura do bloco

        mov bx,Handle           ; manipulador em bx
        mov cx,512              ; quantidade de bytes a serem lidos
        mov ah,3Fh              ; função 3Fh - leitura de arquivo
        int 21h                 ; chama serviço do DOS

        jc ErrorReading         ; desvia se carry flag estiver ligada - erro!

        add [BytesLidos], cx    ; adiciona a quantidade de bytes lidos
        cmp ax, cx              ; compara quantos bytes foram lidos com a quantidade solicitada na função            
        jb  Continuar           ; sair da leitura, caso seja menor (final do arquivo encontrado!)

        add dx,512              ; avança o buffer de leitura
        cmp dx, FimBuffer       ; verifica se chegou no final do buffer
        jae Continuar           ; se dx for maior ou igual ao final, sair da leitura
        jmp LerBloco

    Continuar:

        mov bx,Handle           ; coloca manipulador do arquivo em bx
        mov ah,3Eh              ; função 3Eh - fechar um arquivo
        int 21h                 ; chama serviço do DOS

        mov cx,[BytesLidos]     ; comprimento da string (Ler o valor da variável BytesLidos)
        mov si,OFFSET Buffer    ; DS:SI - endereço da string
        xor bh,bh               ; página de vídeo - 0
        mov ah,0Eh              ; função 0Eh - escrever caracter
        ...

In the data area, set the variables Byteslidos, Fimbuffer and increase buffer size:

    .data
    BytesLidos  DW 0                ; Bytes lidos do arquivo
    Buffer      DB 4096 dup (?)     ; buffer para armazenar dados
    FimBuffer   DW $-Buffer         ; Endereço do fim do buffer

With these changes, the program can read a file of up to 4096 bytes (maximum buffer size) without having to specify previously the size to be read.

If you need to read larger files, you can create a logic similar to this one to read a block, print and restart the buffer, read the next one, print and restart the buffer, and so on.

  • Thanks, it helped a lot! Another thing, I could read through this code line by line instead of reading by blocks?

  • @Samuelhenrique No. DOS has no line reading function. You would need to implement logic to search for the character '\r' (LF) and find out where the end of each line is inside the buffer.

  • Okay, I have a job to do that I need to manipulate the lines of a txt where each line represents data from a sensor. It would be better then to read the file this way and then manipulate by buffer?

  • If the file is small (up to buffer size), yes. You can read the entire file to the buffer and then process. If it is big, it is better to process in parts, as I explained in the reply

  • Okay, thanks for your help!

  • You’re welcome! If the answer was helpful, please mark it as accepted: https://pt.meta.stackoverflow.com/questions/1078/como-e-por-que-aceitar-uma-resposta/1079

  • One more question: in the program will be made the readings of 4 files, being that 3 need to go to memory and the other the teacher said not to go, I can keep it in some other storage location or there is this possibility? 'Cause if there isn’t, I believe I’ll have to read the data and treat it right away.

  • If it cannot go to memory (buffer), the only likely output is to read and already process.

  • Okay, but what would that code look like? You could replace the buffer with a register or something like that?

  • You can read 1 byte and already process, but anyway, reading that byte goes to a memory position. Try to implement the reading with 1 byte and, in case of problems, ask a new question here.

  • Reading the file that should not be in memory I am doing one line at a time but when reading a complete line, I need to empty the buffer and make the reading of the next one from the beginning of the buffer. I tried to clean the buffer in several ways but did not succeed. Do you know any way to do this?

  • To restart the buffer, just load the register dx with the address offset Buffer again. Anyway, you need to change the logic of the program, because DOS does not have the concept of "line" and the reading can only occur for memory, be it 1 byte or 512 bytes (or any size), therefore, the logic of the program will be very different.

Show 7 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.