[英]Segmentation fault using fgets in assembly
我试图用fgets将输入读入缓冲区。 我推了3个参数,但是出现了分割错误。 我试图查看GDB的问题,但是我不明白我收到的消息。
这是代码:
section .rodata
buffer: db 10
section .text
align 16
global main
extern fgets
extern stdin
main:
push ebp
mov ebp, esp
pushad
push dword[stdin]
push 10;
push buffer;
call fgets;
add esp, 12
popad
mov esp, ebp
pop ebp
ret
这是我得到的消息:
Program received signal SIGSEGV, Segmentation fault.
__GI__IO_getline_info (fp=fp@entry=0xf7fb1c20 <_IO_2_1_stdin_>,
buf=buf@entry=0x80484f0 "\n", n=8, n@entry=9, delim=delim@entry=10,
extract_delim=extract_delim@entry=1, eof=eof@entry=0x0) at iogetline.c:86
86 iogetline.c: No such file or directory.
我的代码有什么问题?
之所以.rodata
段错误,是因为您要求fgets
写入.rodata
节中的地址。 当然是只读的。
将缓冲区放在.bss
节中,并使用resb 10
保留10个字节。 您当前的版本是一个字节,初始化为{ 10 }
。 您不想无缘无故地在可执行文件中存储一堆零。 这就是bss的目的。
section .bss
buffer: resb 10
buffer_length equ $ - buffer
section .text
align 16
global main
extern fgets
extern stdin
main:
push dword [stdin]
push buffer_length
push buffer ; 3 pushes gets the stack back to 16B-alignment
call fgets
add esp, 12
ret
在此函数中,您不需要pusha
或堆栈框架(带有ebp的东西)。 通常,您只保存/恢复要使用的呼叫保留寄存器,而不是每次都保存/恢复。
正如Michael Petch指出的那样,最好在堆栈上为缓冲区保留空间,而不要使用静态存储。 查看使用本地数组的等效C函数的编译器输出。 (例如,在http://gcc.godbolt.org/上 )。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.