flat assembler
Message board for the users of flat assembler.

Index > Windows > Unable to print single precision float using printf in x64

Author
Thread Post new topic Reply to topic
Rick



Joined: 11 Jan 2022
Posts: 5
Rick
I'm trying to simply print a single precision float using printf, so far I've tried the following methods:
Code:
format PE64 console
entry start

include "../include/macros/import.inc"
include "../include/macros/proc64.inc"
include "../include/macros/struct.inc"
include "../include/macros/import64.inc"

section '.data' data readable writeable
align 8
number      dd    12.1
fmt         db    'The number is %f',10,0

section '.text' code readable executable

start:
    sub     rsp, 8  ; 16bit align

    ; does not work
    invoke  printf, fmt, [number]

    ; does not work
    pxor        xmm0, xmm0      ; clean
    cvtss2sd    xmm0, [number]  ; load and convert to double ptr  
    lea         ecx,  [fmt]     ; load format string
    call        [printf]

    ; does not work
    lea         ecx, [fmt]      ; load format string
    mov         edx, [number]   ; load number
    call        [printf]

invoke  ExitProcess, 0

section '.idata' import data readable writeable
library kernel, 'KERNEL32.DLL',\
    msvcrt, 'MSVCRT.DLL'

import kernel,\
        ExitProcess,'ExitProcess'

import msvcrt,\
    printf, 'printf'
    

As I am understanding I need to convert the single precision to a double because that is required for vararg function calls in c. I tried that in the second example with no result unfortunately. Changing number to dq makes the first and last example work if all the registers are changed to the x64 version
Post 13 Jan 2022, 14:16
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 738
tthsqe
> Changing number to dq makes the first and last example work if all the registers are changed to the x64 version

I think the vararg arguments to printf are all void* like hence are treated like "integer" arguments in the ABI. Certainly I wouldn't expect printf to look in xmm0 fir an argument as the function is not type safe.
Post 13 Jan 2022, 17:29
View user's profile Send private message Reply with quote
Rick



Joined: 11 Jan 2022
Posts: 5
Rick
tthsqe wrote:
> Changing number to dq makes the first and last example work if all the registers are changed to the x64 version

I think the vararg arguments to printf are all void* like hence are treated like "integer" arguments in the ABI. Certainly I wouldn't expect printf to look in xmm0 fir an argument as the function is not type safe.


Good one, never thought about that, I'll try it that way.
Post 13 Jan 2022, 19:26
View user's profile Send private message Reply with quote
Rick



Joined: 11 Jan 2022
Posts: 5
Rick
I've found the solution, it's indeed required to pass the arguments as if integer arguments as @tthsqe mentioned. Here the final solution:
Code:
format PE64 console
entry start

include "../include/macros/import.inc"
include "../include/macros/proc64.inc"
include "../include/macros/struct.inc"
include "../include/macros/import64.inc"

section '.data' data readable writeable
number      dd    12.1
fmt         db    'The number is %f',10,0

section '.text' code readable executable

start:
    sub     rsp, 8  ; 16bit align

    cvtss2sd    xmm0, DWORD PTR number  ; convert single to double precision
    movq        rdx, xmm0               ; move into rdx as argument
    lea         rcx, [fmt]
    call        [printf]

invoke  ExitProcess, 0

section '.idata' import data readable writeable
library kernel, 'KERNEL32.DLL',\
    msvcrt, 'MSVCRT.DLL'

import kernel,\
        ExitProcess,'ExitProcess'

import msvcrt,\
    printf, 'printf'    
Post 13 Jan 2022, 19:33
View user's profile Send private message Reply with quote
tthsqe



Joined: 20 May 2009
Posts: 738
tthsqe
Note that the MS ABI and system V ABI are quite different on printf: in linux you would indeed put the floating point arguments in xmm0, xmm1, ... , and then tell it the number of floating point arguments you used in `al`. This works up to 8 floating point arguments, then the rest are put on the stack.
Post 14 Jan 2022, 13:41
View user's profile Send private message Reply with quote
Roman



Joined: 21 Apr 2012
Posts: 1088
Roman
Quote:
sub rsp, 8 ; 16bit align

Its align 64 bits!
Post 15 Jan 2022, 11:09
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 491
Location: Russia
macomics
Code:
push rax ; shorter
; OR
and spl, -16 ; correct align 128 bits    

Roman wrote:
Quote:
sub rsp, 8 ; 16bit align
Its align 64 bits!
Its align 128 bits.
Post 15 Jan 2022, 12:10
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.