问题
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
回答1:
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
来源:https://stackoverflow.com/questions/16629805/display-floating-point-by-printf