2014-05-20 95 views
0

我想学习大会,到目前为止,我只使用像c或java这样的高级语言。 我回顾了去年在c中的一些作业,其中一个是制作命令行hang子手游戏,所以我认为我会尝试在程序集中实现这一点。我正在尝试读取.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 

我不知道我做错了,我组装仍然很新。 谢谢你的帮助。

+0

如果你给它的文件的完整路径会发生什么? – user3344003

回答

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来重复填充缓冲区。