GNU アセンブラーでは$
、リテラル値 (命令にエンコードされる値) を指定します。ラベルの値はそのアドレスです。$x
、$format
、$result
、およびは、これらのラベル$text
のアドレスです。それらは、ラベル付けしている値があるアドレスです。printf
のアドレスを使用しません%f
。アドレスではなく、浮動小数点数の値を渡す必要があります。double
また、Frank Kotler が指摘しているように、32 ビットではなく64 ビットとして渡す必要がありますfloat
。
add $-8, %esp
これを行う最も簡単な方法は、命令の前に(またはadd %esp, $-8
、アセンブラー バージョンのオペランドの順序に応じて)を挿入し、アセンブラーに応じて命令をまたはにFSTS result
変更することです。(また、浮動小数点スタックから値をそのままにしておくのではなく、そこから値をポップしたり、ポップしたりすることもできます。)次に、 .FSTS result
FST (%esp)
FSTL (%esp)
FSTP (%esp)
FSTPL (%esp)
push $result
これらの変更により、スタック (add
命令内) に 8 バイトが割り当てられ、浮動小数点の結果がそれらの 8 バイトに格納されます。
また、あなたのコードは、呼び出されたルーチンに渡された引数をクリーンアップする責任があると思います.2つの引数をポップするために呼び出した後、スタックポインタに8を追加し、新しい8バイトの引数をポップするためscanf
に呼び出した後、12を追加する必要があります.printf
フォーマット文字列の 4 バイト アドレス。を呼び出してプログラムを終了するため、これらの変更がなくてもプログラムが動作する場合がありますexit
。ret
ただし、スタックをクリーンアップせずに命令を使用してルーチンから戻ることはできません。
補足
次のコードはideone.comで動作し、アセンブラー (gcc-4.7.2) の 2 番目の選択肢を使用しています。
.text
text: .asciz "Function result: %4.2f \n"
.data
x: .float 2.0
one: .float 1.0
result: .float 0.0
format: .asciz "%f"
.global main
main:
push $x
push $format
call scanf
add $8, %esp
FINIT
FLDS x
FMULS x #x*x
FADDS one
FSQRT
FSUB one
add $-8, %esp
FSTPL (%esp)
xor %eax, %eax
push $text
call printf
add $12, %esp
pushl $0
call exit