2014-05-20 4 views
0

어셈블리를 배우려고하는데, 지금까지는 c 또는 java와 같은 고급 언어 만 사용했습니다. 지난 해 C에서 몇 가지 과제를 거슬러 올라가서 그 중 하나가 행맨 (hangman) 게임을 만드는 것이므로 어셈블리에서 이것을 구현하려고 할 것이라고 생각했습니다. .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 

영 (0) 이외의 어떤 결과 읽기있는 당신을 오류를 고려하십시오. 오류가 아니므로 시스템 호출은 읽은 바이트 수를 반환합니다. 물론 코드 블록이 split_words 인 경우 이미 알고있는 것입니다.

짧은 이야기 : jz split_words 대신 jnz split_words을 원할 것입니다. 장기적으로 버퍼를 반복적으로 채우려면 복수의 read 호출이 필요할 것입니다.

관련 문제