assembly 用x86 NASM汇编语言打印.txt文件的内容

xkrw2x1b  于 2023-05-18  发布在  其他
关注(0)|答案(2)|浏览(141)

我正在学习汇编语言,并试图打印一个.txt文件。下面是我的代码:

[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

但是,它只打印空格,后面跟着6-8行垃圾。文件里只有一个字。
我使用DOS盒便携式编译和运行我的COM格式汇编代码,这里的我是如何做到这一点。我编译程序并使其成为.com可执行文件,此外.lst是为了调试而制作的:nasm myProgram.asm -o myProgram.com -l myProgram.lst来运行程序,我只需要输入myProgram.com
经过研究,并审查a similar question的问题,在我的代码似乎是没有添加偏移,而打印。代码应该是mov dx, offset buffer。事实证明,我的编译器不支持这种语法,并给出了一个语法错误。我试过手动添加偏移量mov dx, [buffer + 2](我试过改变偏移量大小),但它只是打印更多的垃圾,只是在不同的模式。

pdkcd3nj

pdkcd3nj1#

下面的代码使用函数AH=0x40将数据写入标准输出,而不是使用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
wribegjk

wribegjk2#

基于0Signal之前的回答,我能够编写一个代码来打印文件,我还采纳了vitsoft的建议,添加了一个检查文件是否实际打开或读取,如果没有,则打印一个错误。
但是,在这里我必须在文本的末尾添加一个空终止符'$'。确实有一种方法可以手动计算字符串的长度,然后在长度的索引处添加空结束符,但它似乎太麻烦了。
相反,存在更可行的方法,即使用服务ax 3f或ax 40来读取、写入文件。正如Nate所建议的,这些服务返回ax寄存器中文件的长度(该服务实际读取的字符)。
我有ax寄存器,其中包括文件的长度,并添加了缓冲区的起始索引。这指向我添加了DOS的空终止符的最后一个索引,即$。
下面是我如何实现它:

[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

相关问题