Code: Select all
type double_complex
re as double
im as double
end type
sub cadd naked cdecl(byref result as double_complex, byref x as double_complex, byref y as double_complex)
asm
movsd xmm0, QWORD PTR [rdx+8]
movsd xmm1, QWORD PTR [rdx]
addsd xmm0, QWORD PTR [r8+8]
addsd xmm1, QWORD PTR [r8]
movsd QWORD PTR [rcx+8], xmm0
movsd QWORD PTR [rcx], xmm1
ret
end asm
end sub
when writing naked functions, you don't have the convenience of accessing the arguments by name, and local variables must be either registers or the stack.
also, unlike non-naked functions, you don't have the ease of storing the return value in [function], if it's a foating point value then you store the return value in xmm0 before ret, but how to return a simple structure like above?
I thought that it would be returned in the registers xmm0 and xmm1, but no.
by trial and error I found that for this example the address for the return value is stored in register rcx a
it was by chance that rax had the value of rcx, however one must copy rcx to rax before ret.
I also found that register usage don't match that of MS documentation https://docs.microsoft.com/en-us/cpp/bu ... ster-usage
rcx is for 1st argument
rdx is for 2nd argument
r8 is for 3rd argument
but I found that the arguments were passed in registers rdx and r8 and apparently rcx is used for the return address, ok here's the function
Code: Select all
function cadd naked cdecl(byref x as double_complex, byref y as double_complex) as double_complex
asm
movsd xmm0, QWORD PTR [rdx]
movsd xmm1, QWORD PTR [rdx+8]
addsd xmm0, QWORD PTR [r8]
addsd xmm1, QWORD PTR [r8+8]
movsd QWORD PTR [rcx], xmm0 're
movsd QWORD PTR [rcx+8], xmm1 'im
mov rax, rcx
ret
end asm
end function
Code: Select all
dim as double_complex x, y, z
x.re=0.5
x.im=0.3
y.re=.8
y.im=.9
z=cadd(x, y)
print z.re,z.im
sleep
Code: Select all
1.3 1.2