Printf float in nasm build 64-bit

I want to print a float value with printf

global main extern printf section .data string: db `%f\n`, 0 section .bss rs: resq 1 [...] movq xmm0, [rs] mov rdi, string mov rax, 0 call printf 

rs contains a floating value of 1.6

 (gdb) x/fg &rs 0x600ad8 <rs>: 1.6000000000000001 

but the program prints

 [ username@localhost folder]$ ./programname 0.000000 

who can get print program 1.6? what am I doing wrong?

+1
source share
2 answers

I suspect the problem is setting your rax code to 0 , while it should be 1 because you are passing a floating point argument (see here for details). Basically, rax should contain the number of variable arguments passed to the xmmN registers.

Edit:

The printf crash is apparently caused by a flashing stack when the program movaps when the movaps command is movaps (which expects the memory operand to be aligned on a 16-byte boundary):

 => 0x7ffff7a65f84 <__printf+36>: movaps %xmm0,0x50(%rsp) 0x7ffff7a65f89 <__printf+41>: movaps %xmm1,0x60(%rsp) 0x7ffff7a65f8e <__printf+46>: movaps %xmm2,0x70(%rsp) 0x7ffff7a65f93 <__printf+51>: movaps %xmm3,0x80(%rsp) 0x7ffff7a65f9b <__printf+59>: movaps %xmm4,0x90(%rsp) 0x7ffff7a65fa3 <__printf+67>: movaps %xmm5,0xa0(%rsp) 0x7ffff7a65fab <__printf+75>: movaps %xmm6,0xb0(%rsp) 0x7ffff7a65fb3 <__printf+83>: movaps %xmm7,0xc0(%rsp) 

When you enter main stack does not equal 16 bytes, but if you fix this, the program will work fine. Below is my test program (pay attention to sub rsp, 8 at the beginning):

 global main extern printf section .data string db `%f\n`, 0 rs dq 1.6 section .text main: sub rsp, 8 movq xmm0, qword [rs] mov rdi, string mov rax, 1 call printf add rsp, 8 mov eax, 0x60 xor edi, edi syscall 
+4
source

what am I doing wrong?

First : make sure that you are using the correct calling convention (stack, registers, left to right, right to left, etc.). If your program really prints a floating-point number, although this is not the one you need, then at least the format string is transmitted correctly (or you are very lucky, and printf found the address of the format string in the right place, even if you don’t indicated his address).

Second : the number you are trying to print ... is it floating or double? rs defined as the value of the square (64 bits), but floats are 32 bits. So, if the first point was checked, and that’s fine, I suggest you use "%lf" as the format instead of "%f" .

By the way: why do you put RAX = 0 ? What does this mean for calling printf ?

UPDATE: This may help you. Disassembling a stupid program ( fc ):

 #include <stdio.h> main() { float x; x = 1.6; printf ("%f\n", x); } 

$ gcc -c -S fc

$ less fs

  .file "fc" .section .rodata .LC1: .string "%f\n" .text .globl main .type main, @function main: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 movq %rsp, %rbp .cfi_offset 6, -16 .cfi_def_cfa_register 6 subq $16, %rsp movl $0x3fcccccd, %eax movl %eax, -4(%rbp) movss -4(%rbp), %xmm0 cvtps2pd %xmm0, %xmm0 movl $.LC1, %eax movq %rax, %rdi movl $1, %eax call printf leave 
+1
source

All Articles