繁体   English   中英

在程序集中使用fget进行分段错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM