2017-11-07 17 views
0

アセンブリレベルでsyscallを実行するときにasnasmと異なる動作をする理由を理解しようとしています。私は処罰の大食主なので、私はIntel構文を使用しています。私はld -s -o prog prog.oas -o prog.o prog.sとリンクして組み立てGNUアセンブラを使ってsyscallを実行するときのSegfault

.intel_syntax noprefix 
    .section .rodata 
.LC0: 
    .string "Hello world!\n" 
    .text 
    .globl _start 
    .type _start, @function 
_start: 
    mov edx, 13 
    mov ecx, OFFSET FLAT:.LC0 
    mov eax, 4 
    int 0x80 
    ret 

:ここに私のプログラムです。

しかし、私はそれを実行したときに、私が取得:

$ ./prog 
Hello world! 
Segmentation fault (core dumped) 

GDBは、ここでは特に有用ではありません。 stepiretの場合、Cannot access memory at address 0x1と表示されます。 ESPの値であるため、不可解である:

(gdb) info registers esp 
info registers esp 
esp   0xbffff660  0xbffff660 

なぜ、このプログラムセグメンテーション違反していますか?

+0

プログラムから 'ret'するだけでは、' exit'システムコールが必要です。 '1'はスタックの先頭にある引数(' argc')の数なので、 'ret'は明示的な結果を持つアドレスとしてそれを使用しようとします。 – Jester

答えて

2

正常に終了しないためです。 _startに親スタックフレームがないため、スタックフレームを戻すとクラッシュする可能性があります。あなたがあなた自身の_startを書いている場合

あなたはあなたのための標準ライブラリの_start実装コールexitを持っているmainから復帰することができますが、あなたはに戻るには親のスタックフレームがありませんよう、自分をexitを呼び出す必要があります。

+1

@DanBarowyほとんどコピーされますか?私は大部分が問題であるかもしれないことを心配しています。 'ret'が動作していた場合、' _start'はエントリーポイントではなく、 'main'が入ります。 _C_ランタイムが必要なため、リンクする方法は異なります。本の中のどのページ/例が主にコピーしましたか? –

+0

私の最後のコメントは削除されたコメントになります;-) –

+2

@DanBarowy私はさらに一歩進んでいきます。その本は単に駄目であり、捨てるべきです。それは、DOSプログラマーのために書かれたように、最後に急いでLinuxに適応しているように見えます。 (そして、多くのLinuxの詳細は、2000年に出版されたように真剣に古くなっています...) – duskwuff

関連する問題