从 NASM 调用 C 函数 fgetc,它总是 returns a -1
Calling C function fgetc from NASM, it always returns a -1
使用 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
好的,根据评论,我认为这将是我们可能的答案:
- 使用 nasm
编译时使用 -f elf32
- 与 GCC 链接时使用
-m32
。
您的代码有几个问题。一个与 fgetc
无关。你像这样进行 fopen 调用:
mov DWORD [esp], file_name
mov DWORD [esp + 4], file_mode
call fopen
add esp, 8
两条MOV指令破坏了调用函数的return地址。当您从函数 main
中 return 时,这可能会导致段错误。我相信它应该是这样的:
push file_mode
push file_name
call fopen
add esp, 8
fgetc
returns EOF (在 Linux EOF 通常映射到 -1 ).相反,您正在检查 ASCII 值 0 (nul) 以检测流的结尾。 ASCII 0(nul) 是可从流中读取的有效字符。您应该更改此检查:
cmp ebx, 0
je no_characters_left
至:
cmp ebx, -1
je no_characters_left
使用 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
好的,根据评论,我认为这将是我们可能的答案:
- 使用 nasm 编译时使用
- 与 GCC 链接时使用
-m32
。
-f elf32
您的代码有几个问题。一个与 fgetc
无关。你像这样进行 fopen 调用:
mov DWORD [esp], file_name
mov DWORD [esp + 4], file_mode
call fopen
add esp, 8
两条MOV指令破坏了调用函数的return地址。当您从函数 main
中 return 时,这可能会导致段错误。我相信它应该是这样的:
push file_mode
push file_name
call fopen
add esp, 8
fgetc
returns EOF (在 Linux EOF 通常映射到 -1 ).相反,您正在检查 ASCII 值 0 (nul) 以检测流的结尾。 ASCII 0(nul) 是可从流中读取的有效字符。您应该更改此检查:
cmp ebx, 0
je no_characters_left
至:
cmp ebx, -1
je no_characters_left