0

I have a question about printing a floating point number and difference between a double word and quad word data. Here is my example

section .data
number dq 2.0
form db '%.2f',0
section .text
extern printf
global main:
push rbp
mov rbp,rsp
push rdi
push rsi
push rbx

movq xmm0,[number]
push qword[number]
mov rdi,form
mov rax,1
call printf

pop rbx
pop rsi
pop rdi
mov rsp,rbp
pop rbp
ret

Output is :2.0 that is ok but here is a problem if a number is double word

section .data
number dd 2.0
form db '%.2f',0
section .text
extern printf
global main:
push rbp
mov rbp,rsp
push rdi
push rsi
push rbx

movd xmm0,[number]
push qword[number]
mov rdi,form
mov rax,1
call printf

pop rbx
pop rsi
pop rdi
mov rsp,rbp
pop rbp
ret

then output is 0.00, but when I check a xmm0 register I notice that in first case the content is something like this 8_float={0x0,0x2,...},v4_double={0x2,0x0...}, and in second case is 8_float={0x2,0x0,..},v4_double={0x0,0x0,..} so that mean that printf always check a v4_double? I try to printf a double with %lf, but it is the same result 0.00, do you have some idea I try even with different move like movsd,movups,movapd,.. but that does not help me. Do you have some idea?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • 1
    `%d` looks for an integer arg, of course. And yes, it will only accept a `double`, not a `float`, because C's default arg promotion applies for variadic functions. (And of course only scalar `double` in the low element of an XMM reg.) – Peter Cordes Jan 18 '19 at 09:34
  • But I try with %lf and the same result is 0.00 – Marko Škorić Jan 18 '19 at 09:36
  • 1
    Putting the bit-pattern for `2.0f` as the low 32 bits of the mantissa of a `double` (with the rest of the register all zero) represents a *very* small subnormal `double`, which prints as `0.0` unless you use `%g` or `%e`, or a very large number of decimal places. The 2nd half of my answer on the linked duplicate already explains this. – Peter Cordes Jan 18 '19 at 09:38
  • 1
    `%lf` and `%f` are the same format, for printf. – Peter Cordes Jan 18 '19 at 09:39
  • I try with %g and %e but output is 5.43.... so that is not what I looking for – Marko Škorić Jan 18 '19 at 09:41
  • 2
    It's *impossible* to tell printf that you've passed it a `float`. There is no conversion specifier for it. `%g` will print the `double` represented by type-punning a `float` to `double`. Perhaps `%a` (hex double) will make this clearer for you if you still haven't understood that printf is interpreting the register contents as a `double`, but you're passing a 32-bit dword `float` bit pattern. Read the wikipedia links in my answer if you want to understand FP binary representation. – Peter Cordes Jan 18 '19 at 09:45
  • I still do not know how to print content of 8_float so that output is 2.00 – Marko Škorić Jan 18 '19 at 09:51
  • 1
    Load it with `CVTSS2SD` to convert it to `double`, like the answer on the linked duplicate says (in one of the bolded parts). Or do you just mean inside GDB? The `v8_float` view of the register is purely a GDB thing, showing you different ways to interpret the 128 bits of an XMM register. (And it's `v8_float`, not `8_float`). – Peter Cordes Jan 18 '19 at 10:04

0 Answers0