質問
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 printtext
に push $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番目の予感は間違っていたと思います。問題を見つけたように見えますので、ポイントは論争です。