I am porting a function from inline assembly to MASM in Visual Studio 2013 and am having trouble getting a return value out of it.
Here is the C caller and the assembly function prototype:
extern "C" void AbsMax(__m128d* samples, int len, __m128d* pResult);
__m128d AbsMax(__m128d* samples, int len)
{
__m128d absMax = { 0, 0 };
AbsMax(samples, len, &absMax);
return absMax;
}
And the assembly function:
.686 ;Target processor. Use instructions for Pentium class machines
.xmm
.model flat, c ;Use the flat memory model. Use C calling conventions
.code ;Indicates the start of a code segment.
AbsMax proc samples:PTR DWORD, len:DWORD, result:PTR XMMWORD
;; Load up registers. xmm0 is min, xmm1 is max. L is Ch0, H is Ch1.
mov ecx, [len]
shl ecx, 4
mov esi, [samples]
lea esi, [esi+ecx]
neg ecx
pxor xmm0, xmm0
pxor xmm1, xmm1
ALIGN 16
_loop:
movaps xmm2, [esi+ecx]
add ecx, 16
minpd xmm0, xmm2
maxpd xmm1, xmm2
jne _loop
;; Store larger of -min and max for each channel. xmm2 is -min.
pxor xmm2, xmm2
subpd xmm2, xmm0
maxpd xmm1, xmm2
movaps [result], xmm1 ; <=== access violation here
xor eax, eax
xor ebx, ebx
ret
AbsMax ENDP
END
As I understand the convention for MASM, return values are normally returned out through the EAX register. However, since I'm trying to return a 128-bit value I'm assuming an out parameter is the way to go. As you can see in the assembly listing, assigning the out parameter (movaps [result]
) is causing an access violation (Access violation reading location 0x00000000). I've validated the address of result in the debugger and it looks fine.
What am I doing wrong?
__m128d
is defined with a __declspec to align it properly and I double checked the address in the debugger. – Desbergresult
into a register and do the indirect write through it:movaps XMMWORD PTR [ebx], xmm1
for example. – Oviparous_mm_setzero_pd
,_mm_min_pd
,_mm_max_pd
,_mm_sub_pd
, and_mm_store_pd
should do the job, and be portable between x86 and x64 targets. – Oviparous