kulik555
kulik555

Reputation: 3

Display floating point by printf

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

Answers (1)

Eric Postpischil
Eric Postpischil

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.

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

Upvotes: 4

Related Questions