I'm trying to get my head around printing doubles in assembly but I'm failing miserably. I'm getting segfault when calling my own function that I'm planning to use as a helper to print doubles for debugging purposes. I was following these printf
examples: https://www.csee.umbc.edu/portal/help/nasm/sample.shtml
My code currently looks like this:
section .data
formatStrf: db `The number is %f\n`,0
section .text
extern printf
printfcallfloat:
;Pass in RDI
PUSH RDI ;Preserve value of rdi
PUSH RAX ;Preserve value of RAX
PUSH RDI;The value we want to print
PUSH DWORD formatStrf
CALL printf ;Segfault
POP RAX;Pop the stack back (too lazy to manually change the RSP value)
POP RAX
POP RAX;Restore the RAX and RDI
POP RDI
RET
I'm passing the floating point value to the RDI
reg as follows:
MOVSD QWORD [RSP], XMM0 ;Copy to stack
MOV RDI, QWORD [RSP]
CALL printfcallfloat
EDIT: I'm running this on linux.
On x86_64, arguments are passed in registers, and not on the stack (the stack is used only if the size of the arguments to too large to fit in the registers). All the gory details1 are laid out in the SYSV ABI for x86_64
The basics of that is that the first 6 integer/pointer arguments are passed in RDI/RSI/RDX/RCX/R8/R9, while the first 8 float/double arguments are passed in XMM0..XMM7. In addition, you need to specify the number of XMM registers used for arguments in AL2. So in your case, you want the format in RDI, the double value in XMM0 and 1 in AL
The wikipedia page also has lots of good (concise) info about this.
1For non-Microsoft systems -- MS being MS they do things in their own incompatible way
2You only actually need to set this for varargs functions that use at least one XMM register. For non-varargs functions it will be ignored, and if it is set too large for a varargs function, the result will be a few wasted cycles (saving uneeded XMM regs), but wont actually break anything.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments