从NASM调用C函数fgetc,它总是返回-1

时间:2015-11-10 04:03:42

标签: assembly nasm

使用NASM,我正在尝试打开文本文件并打印文本文件的每个字符。问题是,fgetc不断返回-1

    extern  printf
    extern  fopen
    extern  fgetc
    extern  fclose

SECTION .data           ; Data section, initialized variables

    p1_fmt:   db   0xA, "blah", 0xA, 0xA, 0
    p2_fmt:   db   0xA, "Opening: stuff.txt", 0xA, 0xA, 0
    p3_fmt:   db   0xA, "Closing.", 0xA, 0xA, 0
    result_fmt:   db   0xA, "search results: a=%d, e=%d, i=%d, o=%d, u=%d", 0
    p5_fmt:   db   0xA, "debug", 0
    p6_fmt:   db   0xA, "character: %d", 0xA, 0
    file_name:  db  "stuff.txt", 0
    file_mode:  db  "r", 0

SECTION .bss            ; Data section, uninitialized variables

    num_a   resd 0
    num_e   resd 0
    num_i   resd 0
    num_o   resd 0
    num_u   resd 0


SECTION .text           ; Code section.

    global main         ; the standard gcc entry point

main:               ; the program label for the entry point
    push    p1_fmt
    call    printf
    add     esp, 4

    push    p2_fmt
    call    printf
    add     esp, 4

    ;push    file_mode
    ;push    file_name

    mov     DWORD [esp], file_name
    mov     DWORD [esp + 4], file_mode
    call    fopen
    add     esp, 8

    push   eax ; push file pointer on stack.

    character:
        call    fgetc ; an int is in eax now
        mov     ebx, eax ; ebx holds this int too

        ; this continuously print a -1...
        push    ebx
        push    p6_fmt
        call    printf
        add     esp, 8

        cmp ebx, 0
        je no_characters_left

        ; need to loop thru all the characters.
        cmp     ebx, 97
        je vowel_a

        cmp     ebx, 101
        je vowel_e

        cmp     ebx, 105
        je vowel_i

        cmp     ebx, 111
        je vowel_o

        cmp     ebx, 117
        je vowel_u
        jne character

        vowel_a:
            mov eax, num_a
            inc eax
            mov [num_a], eax
            jmp character
        vowel_e:
            mov eax, num_e
            inc eax
            mov [num_e], eax
            jmp character
        vowel_i:
            mov eax, num_i
            inc eax
            mov [num_i], eax
            jmp character
        vowel_o:
            mov eax, num_o
            inc eax
            mov [num_o], eax
            jmp character
        vowel_u:
            mov eax, num_u
            inc eax
            mov [num_u], eax
            jmp character

    no_characters_left:
        call fclose
        add esp, 4 ; remove file pointer off the stack

        push    p5_fmt
        call    printf
        add     esp, 4

    mov     eax, 0      ; normal, no error, return value
    ret                 ; return

2 个答案:

答案 0 :(得分:1)

您的代码存在一些问题。一个与fgetc无关。你这样做 fopen 调用:

    mov     DWORD [esp], file_name
    mov     DWORD [esp + 4], file_mode
    call    fopen
    add     esp, 8

两个 MOV 指令销毁了调用函数的返回地址。从函数main返回时,这可能会导致段错误。我相信它应该是这样的:

    push    file_mode
    push    file_name
    call    fopen
    add     esp, 8

fgetc返回 EOF (在Linux EOF 上通常映射到-1)。而是检查ASCII值0(nul)以检测流的结束。 ASCII 0(nul)是从流中读取的有效字符。你应该改变这个检查:

    cmp ebx, 0
    je no_characters_left

为:

    cmp ebx, -1
    je no_characters_left

答案 1 :(得分:0)

好的,基于评论,我认为这将是我们可能的答案:

  1. 使用nasm
  2. 进行编译时使用-f elf32
  3. 与GCC关联时使用-m32