2

I am trying to assemble following code using NASM on Windows. The printf function is supposed to take xmm0 through xmm2 for fractional point arguments. Why do I have to place fractional arguments in RDX, R8 and R9? Novice here.

global main                     
extern printf
section .data   
    ;Area = pi * r^2            
    pi  dq 3.141592653589793238                 
    radius dq 10.0
    fmt dq "Pi=%.10f  radius=%.10f  area=%.10f",10,0 
section .bss                                                    
section .text                                   
main:
    push    rbp
    mov     rbp,rsp
    sub     rsp,32          ;shadow space
    
    mov     rcx, fmt                    
    movq    xmm0, [pi]
    movq    rdx,xmm0
    
    movq    xmm1, [radius]
    movq    r8,xmm1 

    movq     xmm2, [pi]
    mulsd    xmm2, xmm1; pi*r multiply scalar double
    mulsd    xmm2, xmm1; pi * r^2
    movq     r9,xmm2      
           
    call     printf

    add      rsp, 32                
    leave
    ret

The procedure for fractional arguments is quite different between Microsoft x64 and System-V x64. The problem arose will porting the program designed for Linux to NASM on windows. The code is given in book 'Beginning x64 Assembly Programming' by Jo Van Hoey.

https://github.com/mabs239/beginning-x64-assembly-programming/blob/master/Chapter%2042/42%20variadic1/variadic1.asm

https://github.com/mabs239/beginning-x64-assembly-programming/blob/master/Chapter%2012/12%20function2/function2.asm

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Abu Bakar
  • 175
  • 1
  • 9
  • Aren't you supposed to put the number of floating-point arguments (3) in `rax` before calling `printf`? – Michael Jan 29 '21 at 16:58
  • Does this answer your question? [Why is %eax zeroed before a call to printf?](https://stackoverflow.com/questions/6212665/why-is-eax-zeroed-before-a-call-to-printf) – Michael Jan 29 '21 at 16:59
  • @Michael No. That is for system-v. Mine is specifically for windows 64. Following the book example from: https://github.com/mabs239/beginning-x64-assembly-programming/blob/master/Chapter%2042/42%20variadic1/variadic1.asm – Abu Bakar Jan 29 '21 at 17:17
  • 4
    That's briefly explained in [Microsoft's documentation](https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-160#calling-convention-defaults): _"For vararg or unprototyped functions, any floating point values must be duplicated in the corresponding general-purpose register. ... both the integer register and the floating-point register must contain the value, in case the callee expects the value in the integer registers"_. They don't seem to go into any more detail than that. – Michael Jan 29 '21 at 17:23
  • 2
    @Michael: seems clear the design is to simplify implementation of variadic functions: dump all 4 incoming register args to the shadow space to form an array of all args. But if you need to know which is FP and which is integer, it wouldn't be simple. So just dump integer. – Peter Cordes Jan 29 '21 at 20:50

0 Answers0