2016-04-23 6 views
0

fgetsを使用してバッファに入力を読み込もうとしました。私は3つのパラメータをプッシュしましたが、セグメンテーションエラーが発生しました。私はGDBの問題を見ようとしましたが、私がそこにいるというメッセージを理解できませんでした。
これはコードです:アセンブリでのfgetsを使用したセグメンテーションエラー

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 ([email protected]=0xf7fb1c20 <_IO_2_1_stdin_>, 
     [email protected]=0x80484f0 "\n", n=8, [email protected]=9, [email protected]=10, 
     [email protected]=1, [email protected]=0x0) at   iogetline.c:86 
     86  iogetline.c: No such file or directory. 

私のコードが間違っていますか?

+1

あなたの 'buffer'は読み取り専用データセクション' .rodata'にあります。代わりに '.data'に置きます。 segfaultは、メモリの読み取り専用領域に書き込もうとして発生します。 –

+1

また、 'db 10'は、おそらく10バイトではなく、値 '10'を持つ1バイトを割り当てます。 – Jester

+1

実際には '.bss'セクションに置き、' resb 10 'を使用して10バイトを予約します。現在のバージョンは1バイトで、 '{10}'に初期化されています。何の理由もなく実行可能ファイルに0の束を格納したくないのです。それはbssのためのものです。 –

答えて

1

fgets.rodataセクションのアドレスに書き込むように依頼しています。もちろん読み込み専用です。

バッファを.bssセクションに置き、resb 10を使用して10バイトを予約します。現在のバージョンは1バイトで、{ 10 }に初期化されています。何の理由もなく実行可能ファイルに0の束を格納したくないのです。それは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とのもの)を必要としません。通常、使用するコール保存レジスタは、毎回ではなく、保存/復元するだけです。

マイケル・ペッチは、スタティック・ストレージを使用する代わりに、バッファーのためにスペースを確保することを推奨します。ローカル配列を使用する同等のC関数のコンパイラ出力を見てください。 (例えば、http://gcc.godbolt.org/)。

関連する問題