The MASM Forum

64 bit assembler => 64 bit assembler. Conceptual Issues => Topic started by: markallyn on October 29, 2017, 04:55:17 AM

Title: unknown argument type -> xmm0
Post by: markallyn on October 29, 2017, 04:55:17 AM
Hello everyone,

Ah yes, still the steep learning curve is still steep.

I have no idea why ML64 is claiming that the XMM0 register is an "unknown argument type" when it hits the following couple of lines:
Quote
{prolog}

sub rsp, 30h
movsd  xmm0, pie ;pie is declared a real8 in 3.14159 in data segment
invoke printf, ADDR format, xmm0

...
{epilog}


I must be doing something stupid because using CPUID it is clear that the SSE technology is there on the board.

Regards,
Mark Allyn
Title: Re: unknown argument type -> xmm0
Post by: jj2007 on October 29, 2017, 08:30:53 AM
Mark,
The problem is probably the CRT. This code works just fine:include \Masm32\MasmBasic\Res\JBasic.inc
.code
pie REAL8 3.141592653589793238
Init
  movsd  xmm0, pie ;pie is declared a real8 in 3.14159 in data segment
  usedeb=1
  deb 4, "PI in xmm0", f:xmm0
  Inkey Chr$("This code was assembled with ", @AsmUsed$(1), " in ", jbit$, "-bit format")
EndOfCode


Output:
PI in xmm0      f:xmm0  3.141592654
This code was assembled with ml64 in 64-bit format
Title: Re: unknown argument type -> xmm0
Post by: markallyn on October 29, 2017, 09:11:25 AM
Hi JJ,

Thanks for responding.  I do appreciate it!  After considerable messing around it turned out that the problem was coming from the invoke macro.  Invoke doesn't appear to "know" the sse registers.  If I use a call printf instruction, then printf  "sort of" works. I use the qualifier "sort of" because the xmm0 register must first be placed in a gp register--in this case rdx (rcx contains the format).  In other words, printf doesn't seem to know the sse registers for floats.  don't understand why this is going on.  If you can enlighten me on this point it would be very informative for me.

The other puzzling feature of this concerns the rax register.  In linux systems rax contains the number of sse registers in a variadic function.   Apparently, this isn't the case with masm 64.  Am I wrong?

Regards,
Mark

Title: Re: unknown argument type -> xmm0
Post by: hutch-- on October 29, 2017, 11:17:33 AM
The "invoke" macro is written in accordance with the Microsoft ABI which directly handles from BYTE to QWORD as register/stack arguments. When you use SSE or AVX registers you load the directly and use the CALL mnemonic.
Title: Re: unknown argument type -> xmm0
Post by: aw27 on October 29, 2017, 06:37:50 PM
Quote
I must be doing something stupid because using CPUID it is clear that the SSE technology is there on the board.
All x64 CPUs support at least SSE2.
Title: Re: unknown argument type -> xmm0
Post by: jj2007 on October 29, 2017, 07:01:28 PM
Quote from: markallyn on October 29, 2017, 09:11:25 AMInvoke doesn't appear to "know" the sse registers.  If I use a call printf instruction, then printf  "sort of" works. I use the qualifier "sort of" because the xmm0 register must first be placed in a gp register--in this case rdx (rcx contains the format).  In other words, printf doesn't seem to know the sse registers for floats.

Mark,
As Hutch alluded already, using xmm regs so directly is not really foreseen by the x64 ABI, and it would be surprising if good ol' CRT was more advanced. So a workaround is needed. Nice to see that rdx works, here is another one:
  sub rsp, 2*REAL8 ; simulate a memory variable (attention alignment & shadow space...)
  movlps [rsp], xmm0
  jinvoke crt_printf, Chr$("xmm0", 9, "%f", 13, 10), REAL8 ptr [rsp]
  add rsp, 2*REAL8


This works exactly like...

jinvoke crt_printf, Chr$("pie", 9, "%f"), pie

...where jinvoke knows from the .data declaration that pie is a REAL8.
Title: Re: unknown argument type -> xmm0
Post by: aw27 on October 29, 2017, 07:14:17 PM
Quote
sub rsp, REAL8         ; simulate a memory variable (attention alignment & shadow space...)
It should be aligned before so it becomes not aligned.
Title: Re: unknown argument type -> xmm0
Post by: jj2007 on October 29, 2017, 07:25:18 PM
Right, corrected above. I haven't touched this stuff for a while, apologies :bgrin:
Title: Re: unknown argument type -> xmm0
Post by: hutch-- on October 29, 2017, 10:18:46 PM
I am yet to see why anyone would want to pass registers as arguments when the Microsoft ABI specifically uses 4 64 bit registers, rcx, rdx, r8 and r9 and you just cannot fit anything bigger into a 64 bit register. If you want to pass data in SSE, AVX or AVX2 registers to a procedure, write the data directly to the registers then call the procedure using any of the 64 bit registers OR SMALLER. Those larger registers are NOT CHANGED when an ABI compliant procedure call is made as it only uses the previously mentioned 4 specific registers and if there are more than 4 arguments stack addresses are used.

Eve if you roll your own procedure calls you are doing double data transfer to and from a larger than 64 bit register which makes your procedure call slower for no purpose.
Title: Re: unknown argument type -> xmm0
Post by: habran on October 30, 2017, 05:55:53 AM
UASM is able to handle xmm, ymm and zmm register with VECTORCALL 8)
I have attached asm file with examples how to use it.
Check it.
Title: Re: unknown argument type -> xmm0
Post by: habran on October 30, 2017, 06:00:37 AM
here (http://www.terraspace.co.uk/uasm243_ext.pdf) is more about using VECTORCALL :biggrin:
Title: Re: unknown argument type -> xmm0
Post by: markallyn on October 30, 2017, 09:58:26 AM
Hello everyone,

My thanks to all of you for helping me with this one.  I haven't yet looked at Habran's material, but will certainly do so.

As a beginner I can only say that I do strange, inexplicable things with code simply as experiments.  Sometimes they work, sometimes not.  This one didn't work in the sense of producing usable code, but for beginner experiments it did yield a great deal of useful information--thanks to all of you--so, in a sense, it succeeded. 

More to follow ...

Regards to all.
Mark
Title: Re: unknown argument type -> xmm0
Post by: felipe on October 30, 2017, 12:16:15 PM
markallyn: It's ok to experiment in a controlled way i think. But if you don't want to waste time, it will be bettter for you to learn basic things (whatever the subject can be), then the errors in these controlled environment will be more illustrating for you.

Just an advice, btw.  :icon14:
Title: Re: unknown argument type -> xmm0
Post by: markallyn on November 01, 2017, 12:32:17 AM
Hello again, everyone,

OK, here is my last post on this one, though others may wish of course to respond.

The following code works.  Printf is called with rdx containing the results of a silly little SIMD addition of two real8 floats per vector.

Quote
include \masm32\include64\masm64rt.inc
printf   PROTO :QWORD, :VARARG

.data
frmt   BYTE   "%lf",13,10,0
dblfrmt   BYTE   "%lf",13,10,0
ALIGN 16
v1   REAL8    1.5,1.6
ALIGN 16
v2   REAL8   2.5,2.6


.data?
ALIGN 16
buff   real8 2 dup(?)


.code
main PROC
align 16
movapd   xmm0, v1 ;[eax]
movapd   xmm1, v2 ;[ebx]
addpd    xmm0, xmm1
movapd   [buff], xmm0
mov   rdx, real8 ptr[buff]
invoke   printf, ADDR frmt, rdx
mov   rdx, real8 ptr[buff+8]
invoke   printf, ADDR frmt, rdx
ret
main ENDP
END

One important finding of this experiment was that the numbers must be real8.  Printf doesn't work if one attempts to print real4's as decimal numbers.  It will print the correct ieee754 hex representation if the format string is %x, but not if it is %f.

I do have one question.  Must I use an ALIGN 16 directive for each of the float8 statements or would a single ALIGN 16 at the beginning of the .DATA segment be sufficient to align everything to 16 bytes?

Lastly, to Felipe.  I couldn't agree more with your advice to learn the basics first.  I'd love to do that.  But there arises the question:  What are "the basics"?  I work on my own.  I have no colleagues, although I do have a very patient dog.  And I have the forum--you guys.  And a couple of books.  That's it.  So, I blunder along doing the best I can.

Thanks, folks.

Mark
Title: Re: unknown argument type -> xmm0
Post by: hutch-- on November 01, 2017, 01:09:54 AM
Mark,

If you set an "align 16" at a location in the .data section, the following variable will only remain aligned if they are all 16 bytes long. The alignment is required if you are going to use instructions that require alignment, some do and some don't. As space is not a big deal in 64 bit code, you do better if all of your data is aligned properly.
Title: Re: unknown argument type -> xmm0
Post by: jj2007 on November 01, 2017, 01:54:01 AM
Quote from: hutch-- on November 01, 2017, 01:09:54 AMThe alignment is required if you are going to use instructions that require alignment, some do and some don't

Specifically, movaps requires alignment but movups/movdqu etc don't, and the speed penalty is normally negligible.

Btw the alignment of SIMD instructions concerns memory (.data?), not code. So align 16 in the code section is not required and does not do anything useful.
Title: Re: unknown argument type -> xmm0
Post by: felipe on November 01, 2017, 11:49:09 AM
markallyn: I understood. I still don't try 64 bits. I think that when i get started i will find resources to learn it ( i love studying with good books). Probably my 16 and 32 bits experience will help me. I know is a hard advice to follow. I once got it from an assembly proffesor from an ARM book last year i think, it was somenthing related to trying random things in your programs to see what can happen, but he say that you really don't gain more knowledge with that.

Of course you can't know if you don't try, but i think i like to study in a more methodical way.

:icon14: :icon14: :icon14: :icon14: :icon14:
Title: Re: unknown argument type -> xmm0
Post by: felipe on November 02, 2017, 03:32:22 PM
Btw markallyn i wasn't trying to discourage your efforts, i was just trying to give you an advice to optimize your time.
:icon14:

As you can figure i'm not an expert (i will love to  :P) so you can safely ignore me completly.
:biggrin: