26

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
4

4 に答える 4

16

に変更push printtextpush $printtextます。

printtextそのままでは、アドレスをプッシュするのではなく、アドレスから値をロードしてそれをプッシュしています。'test'したがって、ポインターではなく 32 ビットの数値として渡しており、printfそれをアドレスとして解釈してクラッシュさせようとしています。

于 2011-01-13T04:16:21.093 に答える
9

アセンブリ言語関数を使い始めるための最良の方法の1つは、Cで同様の関数を記述し、アセンブリリスト(-Sgcc上)を生成するコンパイラスイッチを使用して関数をビルドすることです。次に、コンパイラーが行ったことの出力を調べ、必要に応じて変更できます。

printfこれは、(引数の数が可変であるために)異なる呼び出し規約を使用するような関数を呼び出す場合に特に便利です。これらの関数の呼び出しは、非varargs関数の呼び出しとはまったく異なる場合があります。

于 2011-01-13T03:57:34.880 に答える
6

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

pushl printtext

むしろ

pushl $printtext

助けてくれてありがとう、時間を無駄にしてごめんなさい:P

于 2011-01-13T04:13:57.833 に答える
2

この後:

push printtext
call printf

あなたが欲しい:

addl $4, %esp

詳細な説明:

x86 Linuxを使用しているので、呼び出し規約では、呼び出し先がパラメーターをクリーンアップする必要があると思います。を呼び出す前にポインタをプッシュしたため、その関数の命令が発生printfした後、スタックは4ずれています。ret

アップデート:

ええ、わかりました。私はIntel構文に慣れていたので、引数の順序を頭の中で逆にしています。の近くで正しく復元しているので、実際にはaddlバックの欠如はesp問題ではありません。次の推測では、渡した文字列にnullターミネータがありません...何をするのか見てみましょう...espretprintfgas

アップデート2:

OK、gasnullは文字列を終了するので、2番目の予感は間違っていたと思います。問題を見つけたようですので、要点は議論の余地があります。

于 2011-01-13T04:00:45.417 に答える