質問

Cプロジェクトから呼び出されたアセンブリで関数を使用しようとしています。この関数はlibc関数を呼び出すことになっています printf(), 、しかし、私はセグメンテーションの欠陥を取得し続けています。

.cファイルには、関数の宣言があります。

int do_shit_in_asm()

.asmファイルに私が持っています

.extern printf
.section .data
         printtext:
              .ascii "test"
.section .text
.global do_shit_in_asm
.type do_shit_in_asm, @function

do_shit_in_asm:
    pushl %ebp
    movl %esp, %ebp
    push printtext
    call printf
    movl %ebp, %esp
    pop %ebp
ret

どれでも ポインター コメントをいただければ幸いです。

as func.asm -o func.o

gcc prog.c func.o -o prog
役に立ちましたか?

解決

変化する push printtextpush $printtext.

現状では、アドレスから値を読み込んでいます printtext アドレスを押すのではなく、それを押します。したがって、あなたは通り過ぎます 'test' ポインターではなく、32ビット番号として printf それを住所として解釈し、クラッシュしようとしています。

他のヒント

アセンブリ言語関数を始めるための最良の方法の1つは、Cで同様の関数を記述し、アセンブリリストを生成するコンパイラスイッチでそれを構築することです(-S GCCで)。次に、コンパイラが行ったことの出力を調査し、必要に応じて変更できます。

これは、ような関数を呼び出している場合に特に便利です printf 異なる呼び出し条約を使用します(引数の数が変動します)。これらの関数を呼び出すことは、非バラルグ関数を呼び出すこととはまったく異なる場合があります。

問題は、私が使用していたことでした

pushl printtext

むしろ

pushl $printtext

みんなに助けてくれてありがとう、そしてあなたの時間を無駄にしてくれて申し訳ありません:P

この後:

push printtext
call printf

あなたが望む:

addl $4, %esp

さらに説明:

x86 Linuxを使用しているため、通話条約がパラメーターをクリーンアップするためにCalleeが必要とすると仮定します。呼び出す前にポインターを押したからです printf, 、その機能の後、スタックは4ずつオフになっています ret 指示が起こりました。

アップデート:

ええ、OK、私はIntel Syntaxに慣れていたので、私は頭の中で議論の順序を後方に取得していました。実際、の欠如 addl 戻る esp あなたが復元しているので、問題ではありません esp あなたの近くに正しく ret. 。私の次の推測では、あなたが渡している文字列が printf ヌルターミネーターが不足しています...何を見てみましょう gas やる...

更新2:

わかった、 gas Nullはあなたのために文字列を終了するので、私の2番目の予感は間違っていたと思います。問題を見つけたように見えますので、ポイントは論争です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top