Reputation: 3
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
Upvotes: 0
Views: 2924
Reputation: 222908
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
, because C rules implicitly promote float
arguments to double
for variadic functions.
The easiest way to do this might be to insert add $-8, %esp
before the FSTS result
instruction and change the FSTS result
instruction to FSTL (%esp)
to store a 64-bit double
to the stack. (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.
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
Upvotes: 4