x64 assembly has a fairly standard calling convention for passing arguments: first argument goes in RDI, second in RSI, and so on. Thus, if I want to print the quotient of dividing two floating-point values with the printf
function, I would think to do something like this:
.section .data
outfloatfmt: .asciz "%lf\n"
.section .text
.extern printf
.global main
main:
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movq $7, -16(%rbp) # x = 7
movq $2, -8(%rbp) # y = 2
fld -16(%rbp) # Move x into st0 register.
fld -8(%rbp) # Move y into st1 register.
fdivp %st(1) # Divide st0 by st1 and store quotient in st0.
fstpl -16(%rsp) # Store quotient back out to local variable x.
movq -16(%rsp), %rsi # Load quotient into rsi.
leaq outfloatfmt(%rip), %rdi
movq $0, %rax
callq printf
addq $16, %rsp
movq %rbp, %rsp
popq %rbp
ret
This always results in an output of 0.00000. The RSI register seems to have a ridiculously long hex value stored after I perform the relevant movq
instruction. I'm not sure if it has something to do with the fact that I'm storing the rest of the floating-point quotient back out to local memory and then into an integer register (but even if this is the case, shouldn't printf
interpret these bytes as a floating-point value?).
If I try print/f $st0
or print/f $st1
in GDB, neither contain the correct values. What am I doing wrong?