Reputation: 17
I'm trying to print float values to console but it gives unexpected results too large number having different sign.
Program
.data
float_: .asciz "%f\n"
n1: .float 10.4
n2: .float 10.3
.text
.globl main
main:
sub $1, %esp
finit
flds n1
fsubs n2
fsts 1(%esp)
movl 1(%esp), %eax
call pfl
addl $1, %esp
.exit:
movl $1, %eax
movl $0, %ebx
int $0x80
pfl:
pushal
push %eax
push $float_
call printf
add $8, %esp
popal
ret
Output
Different every time but between -400...0.0... to -500000..0.0...
Upvotes: 0
Views: 507
Reputation: 58762
Various problems with your code. Most importantly, %f
expects a double
but you pass a float
. See man 3 printf or a C book. Furthermore a float
is 4 bytes so you'd be well advised to allocate 4 bytes not 1. To make matters worse, you are not even using the 1 byte allocated since that is at (%esp)
but you used 1(%esp)
. For a double you will need 8 bytes. Next, you forgot to pop the value from the FPU. Also, current calling conventions require 16 byte aligned stack, even in 32 bit mode.
Finally, it's not recommended to use the exit system call directly in main
or other code that uses libc function. Instead, just ret
or call exit
if you really insist to make sure libc cleanup (like flushing stdio buffers) happens. Otherwise you'll get no output if you redirect stdout to a file so it's full-buffered.
Here is a possible version fixing all of the above:
.data
float_: .asciz "%f\n"
n1: .float 10.4
n2: .float 10.3
.text
.globl main
main:
sub $12, %esp # 8 bytes for double, + 4 bytes for alignment
flds n1
fsubs n2
fstpl (%esp) # pop double from fpu
movl (%esp), %eax # low 4 bytes
movl 4(%esp), %edx # high 4 bytes
call pfl
addl $12, %esp
ret
## input: EDX:EAX = the bit-pattern for a double
pfl:
push %edx
push %eax
push $float_ # 3x push realigns the stack by 16 again
call printf
add $12, %esp
ret
Bouncing your double
through integer registers is unnecessary; if you inlined call printf
into your main function you could have just used fstpl
to put the double
on the stack right above a pointer to the format string.
Or made your pfl
function takes its input in %st(0)
instead of integer registers, since you're making up a custom calling convention anyway.
(I assume your next question is going to be why it prints 0.099999
instead of 0.1
:))
Upvotes: 3