0

printf を使用した浮動小数点値の表示に問題があります。

数学関数の結果を表示しようとしていますが、常に 0.00 になります。

私が間違っていることを教えてください。

私のGNU ASコード:

.text
text: .ascii  "Function result: %4.2f \n"
.data
x: .float 2.0
one: .float 1.0
result: .float 0.0


format: .ascii "%f"


.global main

main:
push $x
push $format
call scanf


FINIT

FLDS x  

FMULS x     #x*x

FADDS one   

FSQRT       

FSUB one        

FSTS result

xor %eax, %eax


push $result
push $text

call printf


pushl $0
call exit
4

1 に答える 1

3

GNU アセンブラーでは$、リテラル値 (命令にエンコードされる値) を指定します。ラベルの値はそのアドレスです。$x$format$result、およびは、これらのラベル$textのアドレスです。それらは、ラベル付けしている値があるアドレスです。printfのアドレスを使用しません%f。アドレスではなく、浮動小数点数の値を渡す必要があります。doubleまた、Frank Kotler が指摘しているように、32 ビットではなく64 ビットとして渡す必要がありますfloat

add $-8, %espこれを行う最も簡単な方法は、命令の前に(またはadd %esp, $-8、アセンブラー バージョンのオペランドの順序に応じて)を挿入し、アセンブラーに応じて命令をまたはにFSTS result変更することです。(また、浮動小数点スタックから値をそのままにしておくのではなく、そこから値をポップしたり、ポップしたりすることもできます。)次に、 .FSTS resultFST (%esp)FSTL (%esp)FSTP (%esp)FSTPL (%esp)push $result

これらの変更により、スタック (add命令内) に 8 バイトが割り当てられ、浮動小数点の結果がそれらの 8 バイトに格納されます。

また、あなたのコードは、呼び出されたルーチンに渡された引数をクリーンアップする責任があると思います.2つの引数をポップするために呼び出した後、スタックポインタに8を追加し、新しい8バイトの引数をポップするためscanfに呼び出した後、12を追加する必要があります.printfフォーマット文字列の 4 バイト アドレス。を呼び出してプログラムを終了するため、これらの変更がなくてもプログラムが動作する場合がありますexitretただし、スタックをクリーンアップせずに命令を使用してルーチンから戻ることはできません。

補足

次のコードは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
于 2013-05-19T10:37:39.823 に答える