Search code examples
linuxassemblyprintfnasmglibc

Printing floating point numbers in assembler


I'm trying to print a floating-point value from assemler calling a printf function. It works fine with strings and integer values but fails printing floats. Here is an example of working code:

global  main
extern  printf

section .data
  message:    db      "String is: %d %x %s", 10, 0
  end_message:    db    ".. end of string", 0 

section .text
  main:
    mov eax, 0xff
    mov     edi, message
    movsxd rsi, eax
    mov rdx, 0xff
    mov rcx, end_message
    xor rax, rax
    call printf
    ret

String is: 255 ff .. end of string

So, the parameters are passed through registers: edi contains address of a formatting string, rsi and rdx contain the same number to print in decimal and hex styles, rcx contains end of a string, rax contains 0 as we do not have a float to print. This code works fine but something changes while trying to print float:

global main

extern printf

section .data
    val: dq 123.456
    msg: db "Result is: %fl",10, 0

section .text
    main:
    mov rdi,msg
    movsd xmm0,[val]
    mov eax,1
    call printf

    mov rax, 0
    ret

This code snipped can be compiled but returns segmentation fault being executed. It seems that the problem is in wrong value of xmm0 but trying to change movsd xmm0,[val] to movsd xmm0,val gives an

error: invalid combination of opcode and operands

message. The compiler is NASM running on openSuSe 12.3

Update. I tried to make a c program and produce a .S assembly. It gives a very weird solution:

main:
.LFB2:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $32, %rsp
    movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    movq    val(%rip), %rax
    movq    %rax, -24(%rbp)
    movsd   -24(%rbp), %xmm0
    movl    $.LC0, %edi
    movl    $1, %eax
    call    printf
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret

Is it possible to write a simple printf example?


Solution

  • for your assembler problem: you need to align the stack before your main program starts.

    insert

    sub rsp, 8
    

    right after main:

    then add it again before ret:

    add rsp, 8