通过printf显示浮点 [英] Display floating point by printf
问题描述
我试图显示一些数学函数的结果,但是我总是得到0.00。
我可以帮助我,告诉我做错了什么?
我的GNU AS代码:
.text
text:.ascii函数结果:%4.2f \\\
.data
x:.float 2.0
one:.float 1.0
结果:.float 0.0
格式:.ascii%f
.global主要
主要:
推动$ x
推动$格式
呼叫scanf
FINIT
FLDS x
FMULS x#x * x
FADDS 1
FSQRT
FSUB one
FSTS结果
xor%eax,%eax
$ b push $ result
push $ text
$ b $ call printf
$ b $ pushl $ 0
call exit
在GNU汇编中, $
指定一个文字值进入指令)。标签的值是它的地址。所以 $ x
, $格式
, $结果
和 $ text
是这些标签的地址;他们是你有标签值的地址。 printf
不会使用%f
的地址。您必须传递浮点数的值,而不是其地址。而且,正如弗兰克·科特勒(Frank Kotler)指出的那样,你必须把它作为一个64位的 double
,而不是32位的 float
。
最简单的方法是插入 add $ -8,%esp
(或<$在$ FSTS结果
指令前修改c $ c> add%esp,$ -8 ,取决于汇编器版本中操作数的顺序) FSTS结果
指令到 FST(%esp)
或 FSTL(%esp)
,这取决于你的汇编程序。 (也可以使用 FSTP(%esp)
或 FSTPL(%esp)
)然后删除 push $ result
。
这些更改将分配八个(在 add
指令中)并将浮点结果存储到这八个字节中。
另外,我希望你的代码负责清理传递给被调用例程的参数:在调用 scanf
来弹出两个参数之后,它应该向堆栈指针添加8个字符,在调用 printf
后添加十二个参数,弹出新的八字节参数和格式字符串的四字节地址。由于您通过调用 exit
来终止程序,因此您的程序可能在没有这些更改的情况下运行。但是,如果不清除堆栈,就不可能从 ret
指令的例程返回。
补充
以下代码可在 ideone.com 上使用汇编程序(gcc-4.7.2)的第二个选择:
$ $ $ $ $ $ $ $ $ $ $ $ $文本:.asciz函数结果: %4.2f \\\
.data
x:.float 2.0
one:.float 1.0
结果:.float 0.0
格式:.asciz%f
.global main
main:
push $ x
push $ format
call scanf
add $ 8,%esp
FINIT
FLDS x
FMULS x#x * x
FADDS一
FSQRT
FSUB一
加$ -8,%esp
FSTPL(%esp)
xor%eax,%eax
push $ text
call printf
add $ 12,%esp
pushl $ 0
退出
I have problem with display floating point value using printf.
I'm trying display result of some math function, but I always get 0.00.
Could you help me and tell what I'm doing wrong?
My GNU AS code:
.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
In the GNU assembler, $
designates a literal value (a value that is encoded into the instruction). The value of a label is its address. So $x
, $format
, $result
, and $text
are the addresses of those labels; they are the addresses where you have the values you are labeling. printf
does not use an address for %f
. You must pass the value of the floating-point number, not its address. And, as Frank Kotler notes, you must pass it as a 64-bit double
, not a 32-bit float
.
The easiest way to do this might be to insert add $-8, %esp
(or add %esp, $-8
, depending on the order of operands in your assembler version) before the FSTS result
instruction and change the FSTS result
instruction to either FST (%esp)
or FSTL (%esp)
, depending on your assembler. (Also, these could be FSTP (%esp)
or FSTPL (%esp)
to pop the value from the floating-point stack instead of leaving it there.) Then delete the push $result
.
These changes will allocate eight bytes on the stack (in the add
instruction) and store the floating-point result to those eight bytes.
Also, I expect your code is responsible for cleaning up arguments passed to called routines: It should add eight to the stack pointer after calling scanf
to pop the two arguments, and it should add twelve after calling printf
to pop the new eight-byte argument and the four-byte address of the format string. Your program may work without these changes since you terminate the program by calling exit
. However, it would not be possible to return from a routine with the ret
instruction without cleaning up the stack.
Supplement
The following code works at ideone.com, using the second choice for Assembler (gcc-4.7.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
这篇关于通过printf显示浮点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!