Printing Contents of a .txt file in x86 NASM Assembly Language

huangapple go评论57阅读模式
英文:

Printing Contents of a .txt file in x86 NASM Assembly Language

问题

I am learning Assembly Language and am trying to print a .txt file. Here's my code:

[org 0x0100] 
 jmp start 
filename: db 'test1.txt', 0 ;file that is to be loaded
buffer:   times 4096 db 0 ;allocating 4K of space to store file contents
handle:   dw 0      ;handle for the file

start:
    ; open the file
    mov ah, 0x3d     ; service 3d - open file
    mov al, 0       ; read-only mode
    mov dx, filename
    int 0x21
    mov [handle], ax  ; save the file handle

    ; read the file into buffer
    mov ah, 0x3f     ; service 3f - read from file
    mov bx, [handle]
    mov cx, 4096     ; read up to 4096 bytes
    mov dx, buffer
    int 0x21

    ; print the buffer to the console
    mov dx, buffer  ; making sure it actually prints buffer
    mov ah, 9       ; service 9 - print string
    int 0x21

    ; close the file
    mov ah, 0x3e     ; service 3e - close file
    mov bx, [handle]
    int 0x21

    ; exit the program
    mov ax, 0x4c00 ; terminate program 
    int 0x21

However, it only prints whitespace followed by 6-8 lines of garbage. Inside the file is only a single word.

I am using DOS Box portable to compile and run my COM format assembly code and here's how I'm doing it.
I compile the program and make a .com executable for it and in addition, the .lst is made for debugging:
nasm myProgram.asm -o myProgram.com -l myProgram.lst
to run the program, I just enter myProgram.com

After researching, and reviewing a similar question the problem in my code seems to be not adding an offset while printing. And the code is supposed to be mov dx, offset buffer. As it turns out, my compiler does not support this syntax and gives a syntax error. I have tried to manually add the offset mov dx, [buffer + 2] (I've tried changing the offset size) but it just prints more garbage, just in a different pattern.

英文:

I am learning Assembly Language and am trying to print a .txt file. Here's my code:

[org 0x0100] 
 jmp start 
filename: db 'test1.txt', 0 ;file that is to be loaded
buffer:   times 4096 db 0 ;allocating 4K of space to store file contents
handle:   dw 0      ;handle for the file

start:
    ; open the file
    mov ah, 0x3d     ; service 3d - open file
    mov al, 0       ; read-only mode
    mov dx, filename
    int 0x21
    mov [handle], ax  ; save the file handle

    ; read the file into buffer
    mov ah, 0x3f     ; service 3f - read from file
    mov bx, [handle]
    mov cx, 4096     ; read up to 4096 bytes
    mov dx, buffer
    int 0x21

    ; print the buffer to the console
    mov dx, buffer  ; making sure it actually prints buffer
    mov ah, 9       ; service 9 - print string
    int 0x21

    ; close the file
    mov ah, 0x3e     ; service 3e - close file
    mov bx, [handle]
    int 0x21

    ; exit the program
    mov ax, 0x4c00 ; terminate program 
    int 0x21

However, it only prints whitespace followed by 6-8 lines of garbage. Inside the file is only a single word.

I am using DOS Box portable to compile and run my COM format assembly code and here's how I'm doing it.
I compile the program and make a .com executable for it and in addition the .lst is made for debugging:
nasm myProgram.asm -o myProgram.com -l myProgram.lst
to run the program, I just enter myProgram.com

After researching, and reviewing a similar question the problem in my code seems to be not adding an offset while printing. And the code is supposed to be mov dx, offset buffer . As it turns out, my compiler does not support this syntax and gives a syntax error. I have tried to manually ad the offset mov dx, [buffer + 2] (I've tried changing the offset size) but it just prints more garbage, just in a different pattern.

答案1

得分: 1

以下是已翻译的代码部分:

Code below uses function AH=0x40 to write data to standard output, console instead of using AH=0x9.

    org 100h

    jmp start 

    filename: db 'test1.txt', 0 ;file that is to be loaded
    buffer: times 4096 db 0 ;allocating 4K of space to store file 
    handle: dw 0 ;handle for the file
    BytesRead: dw 0

    start:
    ; open the file
    mov ah, 0x3d ; service 3d - open file
    mov al, 0 ; read-only mode
    mov dx, filename
    int 0x21

    mov [handle], ax ; save the file handle

    ; read the file into buffer
    mov ah, 0x3f ; service 3f - read from file
    mov bx, [handle]
    mov cx, 4096 ; read up to 4096 bytes
    mov dx, buffer
    int 0x21

    ;-- Print to file, device AH=0x40
    ; We use 1, output to screen. 
    ;0 - input stream (console)
    ;1 - output stream (console)
    ;2 - diagnostic stream (console)
    ;3 - aux stream (serial port)
    ;4 - prn stream (printer) 

    mov [BytesRead], ax

    mov ah, 0x40 ; service 0x40 - write to file/device
    mov bx, 0x1 ; change current file handle to standard output, console
    mov cx, [BytesRead]     
    mov dx, buffer
    int 0x21

    ;-- Print character one by one AH=0x2
    ;mov [BytesRead], ax

    ;mov cx, [BytesRead]
    ;mov bx, buffer

    ; Print:
    ; mov ah, 0x2
    ; mov dl, [bx]
    ; int 0x21
    ; inc bx
    ; loop Print

    ;----------------------------

    ; mov dx, buffer ; making sure it actually prints buffer
    ;mov ah, 9 ; service 9 - print string
    ;int 0x21

    ; close the file
    mov ah, 0x3e ; service 3e - close file
    mov bx, [handle]
    int 0x21

    End:
    ; exit the program
    mov ax, 0x4c00 ; terminate program 
    int 0x21

希望这有所帮助!如果您需要进一步的翻译或解释,请告诉我。

英文:

Code below uses function AH=0x40 to write data to standard output, console instead of using AH=0x9.

org 100h

jmp start 

filename: db 'test1.txt', 0 ;file that is to be loaded
buffer:    times 4096 db 0 ;allocating 4K of space to store file 
handle:   dw 0      ;handle for the file
BytesRead: dw 0

start:
; open the file
mov ah, 0x3d     ; service 3d - open file
mov al, 0       ; read-only mode
mov dx, filename
int 0x21

mov [handle], ax  ; save the file handle

; read the file into buffer
mov ah, 0x3f     ; service 3f - read from file
mov bx, [handle]
mov cx, 4096     ; read up to 4096 bytes
mov dx, buffer
int 0x21

;-- Print to file,device AH=0x40
; We use 1, output to screen. 
;0 - input stream (console)
;1 - output stream (console)
;2 - diagnostic stream (console)
;3 - aux stream (serial port)
;4 - prn stream (printer) 

mov [BytesRead],ax

mov ah, 0x40     ; service 0x40 - read to file/device
mov bx, 0x1     ;change current file handle to standard output, console
mov cx, [BytesRead]     
mov dx, buffer
int 0x21

;-- Print character one by one AH=0x2
;mov [BytesRead],ax

;mov cx, [BytesRead]
;mov bx, buffer

;    Print:
;    mov ah,0x2
;    mov dl,[bx]
;    int 0x21
;    inc bx
;loop Print

;----------------------------

; mov dx, buffer  ; making sure it actually prints buffer
;mov ah, 9       ; service 9 - print string
;int 0x21

; close the file
mov ah, 0x3e     ; service 3e - close file
mov bx, [handle]
int 0x21

End:
; exit the program
mov ax, 0x4c00 ; terminate program 
int 0x21

答案2

得分: 1

根据0Signal的先前回答,我能够制作一个代码来打印文件,我还采纳了vitsoft的建议,添加了一个检查,以确保文件是否已打开或读取,并在未成功时打印错误。

但是,在这个过程中,我需要在我的文本末尾添加一个空终止符字符' $ '。实际上存在一种手动计算字符串长度然后在长度的索引处添加空终止符字符的方法,但这似乎太繁琐。

相反,有一种更可行的方法,即使用服务ax3f或ax40,这些服务用于读取、写入文件。正如Nate所建议的,这些服务将文件的长度(实际读取的字符数)返回到ax寄存器中。

我有包含文件长度的ax寄存器,并添加了缓冲区的起始索引。这指向了我添加DOS的空终止符'$'的最后索引。

这是我如何实施的:

[org 0x0100]
jmp start
filename: db 'test1.txt', 0 ;要加载的文件
buffer:   times 4096 db 0 ;分配4K的空间来存储文件内容
handle:   dw 0      ;文件句柄
length:   dw 0      ;文件长度

openfailed: db '无法打开文件$'
readfailed: db '无法读取文件$'

start:
    ; 打开文件
    mov ah, 0x3d     ; 服务3d - 打开文件
    mov al, 0       ; 只读模式
    mov dx, filename
    int 0x21
    jnc read        ; 如果没有错误,继续执行
    mov dx, openfailed ; 打印错误
    jmp finalexit

read:
    mov [handle], ax  ; 保存文件句柄

    ; 读取文件到缓冲区
    mov ah, 0x3f     ; 服务3f - 从文件中读取
    mov bx, [handle]
    mov cx, 4096     ; 读取最多4096字节
    mov dx, buffer
    int 0x21
    jnc printbuffer ; 如果没有错误,继续执行
    mov dx, readfailed ; 打印错误
    jmp finalexit

printbuffer:
    ; 将缓冲区打印到控制台
    mov si, 0 ; 初始化si寄存器为零
    lea si, [buffer] ; 将缓冲区的起始索引加载到si寄存器
    add si, ax  ; ax已经包含读取的字节数
    mov byte[si], '$' ; 在缓冲区末尾添加空终止符。
    mov dx, buffer

finalexit:
    mov ah, 9       ; 服务9 - 打印字符串
    int 0x21

    ; 关闭文件
    mov ah, 0x3e     ; 服务3e - 关闭文件
    mov bx, [handle]
    int 0x21

    ; 退出程序
    mov ax, 0x4c00 ; 终止程序
    int 0x21
英文:

Based on 0Signal's previous answer I was a able to make a code to print the file, I also took vitsoft's suggestion to add a check if the files actually opened or read and print an error if they didn't.

However, in this I have to add a null terminator character '$' at the end of my text. There does exist a way to manually calculate the length of a string and then add the null terminator character at the length's index but it seems too cumbersome.

Instead, there is a more viable approach i.e. to use service ax3f or ax40 which are used to read, write the file. As suggested by Nate, these services return the length(the characters this service actually reads) of the file in the ax register.

I had the ax register which included the length of the file and added the starting index of the buffer. This pointed to the last index where I added the null terminator of DOS which is $.

Here's how I implemented it:

[org 0x0100] 
 jmp start 
filename: db 'test1.txt', 0 ;file that is to be loaded
buffer:   times 4096 db 0 ;allocating 4K of space to store file contents
handle:   dw 0      ;handle for the file
length:   dw 0      ;length of the file

openfailed: db 'File could not be opened$' 
readfailed: db 'File could not be read$' 

start:
    ; open the file
    mov ah, 0x3d     ; service 3d - open file
    mov al, 0       ; read-only mode
    mov dx, filename
    int 0x21
    jnc read        ;proceed if no errors
    mov dx, openfailed ;print the error
    jmp finalexit
    
read:
    mov [handle], ax  ; save the file handle

    ; read the file into buffer
    mov ah, 0x3f     ; service 3f - read from file
    mov bx, [handle]
    mov cx, 4096     ; read up to 4096 bytes
    mov dx, buffer
    int 0x21
    jnc printbuffer ;proceed if no errors
    mov dx, openfailed ;print the error
    jmp finalexit

printbuffer:
    ; print the buffer to the console
    mov si, 0 ;initialize the si register to zero
    lea si, [buffer] ;load the buffer's staring index in si register
    add si, ax  ;ax already has the size of the bytes that were read
    mov byte[si], '$' ;adding the null terminator at the end of buffer.
    mov dx, buffer

finalexit:
    mov ah, 9       ; service 9 - print string
    int 0x21

    ; close the file
    mov ah, 0x3e     ; service 3e - close file
    mov bx, [handle]
    int 0x21

    ; exit the program
    mov ax, 0x4c00 ; terminate program 
    int 0x21

huangapple
  • 本文由 发表于 2023年5月15日 00:15:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76248517.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定