无法读取文件内容

时间:2014-05-20 22:50:45

标签: assembly nasm

我正在尝试学习汇编,到目前为止我只使用了高级语言,如c或java。 我回顾了去年c中的一些作业,其中一个是制作命令行刽子手游戏,所以我想我会尝试在程序集中实现它。我正在尝试阅读.txt文件,但似乎并没有让它正常工作。出于测试目的,我只想将文件直接打印到终端,但由于某种原因,sys_read失败。

以下是代码:

SYS_EXIT equ 1                          ; UNIX system call sys_exit
SYS_READ equ 3                          ; UNIX System call sys_read
SYS_WRITE equ 4                         ; UNIX System call sys_write
SYS_OPEN equ 5                          ; UNIX System call sys_open

STDIN equ 0                             ; File descriptor for Standard in stream
STDOUT equ 1                            ; File descriptor for Standard out stream

; print to standard out macro
    %macro print 2
        pushad                          ; Save all regisers
        mov eax, SYS_WRITE              ; Write system call
        mov ebx, STDOUT                 ; File descriptor for stdout
        mov ecx, %1                     ; Message to print as argument 1
        mov edx, %2                     ; Message length as argument 2
        int 0x80                        ; Call kernel
        popad                           ; restore all registers
    %endmacro

; print string to standard out macro
    %macro print_str 1
        section .data
            %%str db %1                 ; adress to hold string
            %%strL equ $ - %%str        ; length of string
        section .text   
            print %%str, %%strL         ; print string to stdout using print macro
    %endmacro

; print newline
    %macro println 0        
        section .data           
            %%strln db 0xA, 0xD         ; adress to hold newline and carrige return
        section .text
            print %%strln, 2            ; print newline
    %endmacro

; print string with trailing newline
    %macro print_str_ln 1
        section .data
            %%str db %1                 ; adress to hold string
            %%strL equ $ - %%str        ; length of string
        section .text   
            print %%str, %%strL         ; print string to stdout using print macro
            println                     ; prints newline
    %endmacro

; exit program
    %macro exit 1
        mov eax, SYS_EXIT               ; Exit system call
        mov ebx, $1                     ; Return value
        int 0x80                        ; call kernel
    %endmacro

section .text
    global _start                       ; Required for linker (ld)
_start:                                 ; Linker entry point
    print_str_ln "Welcome to hangman"   ; print message to user
    println                             ; print newline
    call open_file                      ; open file and read
    exit 0                              ; exit program

; Open the words list file
open_file:
    mov eax, SYS_OPEN                   ; System call open
    mov ebx, word_source_file           ; Points to filepath
    xor ecx, ecx                        ; O_RDONLY
    xor edx, edx                        ; mode is ignored when O_CREATE isn't specified
    int 0x80                            ; call kernel
    test eax, eax                       ; check output of SYS_OPEN
    jns read_file                       ; If sign flag set, read file
    print_str_ln "Could not open file"  ; Print error message to user
    exit 1                              ; exit program

; read the file that was opened
read_file:
    mov ebx, eax                        ; move file descriptor from eax to ebx
    mov eax, SYS_READ                   ; system call SYS_READ
    mov ecx, buffer                     ; The buffer
    mov edx, bufferlen                  ; The length of the buffer
    int 0x80                            ; call kernel
    test eax, eax                       ; check for errors
    jz split_words                      ; If EOF return
    print_str_ln "Counld not read file" ; Print error message
    js exit 1                           ; If read faild exit

; TESTING - Print contentsof buffer
split_words:
    mov edx, eax                        ; The amount of bytes read, returned from sys_read
    mov eax, SYS_WRITE                  ; System call sys_write
    mov ebx, STDOUT                     ; File descriptor (stdout)
    mov ecx, buffer                     ; The buffer
    int 0x80                            ; call kernel
    ret                                 ; return


section .bss
    buffer resb 2048                    ; A 2kb buffer ussed to read

section .data
bufferlen dw 2048                       ; The length of buffer
newline db 0xA, 0xD                     ; Newline and carrige return
word_source_file db 'words.txt', 0      ; The path to the words file 

现在,当我使用汇编程序和链接器并运行时,我得到:

$ nasm -f elf hangman.asm
$ ld -m elf_i386 -o hangman hangman.o
$ ./hangman 
Welcome to hangman

Counld not read file

我不知道自己做错了什么,而且我还很擅长集会。 谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

您应该学会使用调试器,这样您就可以修复自己的错误。但是,在这种情况下,打印的错误消息确切地指出了问题的位置,所以即使只是重新阅读你自己的评论,你也可以在头脑中做到这一点:

test eax, eax                       ; check for errors
jz split_words                      ; If EOF return
print_str_ln "Counld not read file" ; Print error message
js exit 1                           ; If read faild exit

显然,读取会导致您认为错误以外的其他内容。它不是错误,系统调用返回读取的字节数。但是,鉴于split_words处的代码块,您当然已经知道了。

长话短说:你可能想要jnz split_words而不是jz split_words。从长远来看,您可能需要多次read次调用才能重复填充缓冲区。