News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Making return values in procs

Started by Lonewolff, April 26, 2018, 09:56:09 AM

Previous topic - Next topic

Lonewolff

Hi guys,

It's easy enough to make return values of DD's etc and 'mov' them in to your variable upon return.

But what if you want a return value of a struct?

Say you have a struct containing a dozen DD's for example, how to you handle that sort of thing on return?

Thanks in advance :)

Siekmanski

I'm not sure if you meant this?

.const
MEDIATIMERS struct
    Timer1  dd ?
    Timer2  dd ?
    Timer3  dd ?
    Timer4  dd ?
MEDIATIMERS ends

.data?
align 4
Timers    MEDIATIMERS <?>

.code
    mov Timers.Timer1,0    ; write to struct member
    mov eax,Timers.Timer4  ; read from struct member

Creative coders use backward thinking techniques as a strategy.

jj2007

Perhaps it's not yet clear. You have two options:

- mov eax,Timers.Timer4: you return one value in eax (it could be another register - unusual but possible)

- eax returns just an error code; in this case, the proc got, as one argument, a pointer to the structure, and it filled the values into that structure. So, in a sense, you "return" a filled structure, plus an error code.

Lonewolff

I mean for example something like this (in C++)

Matrix c = MatrixMultiply(a, b);

So you feed in a and b, into a proc and it outputs the result in to 'newMat'.

How do you fill 'newMat' in ASM without using it as an input parameter.

At this stage I am doing a work around and using a 'c' input param as the result. But, how do you fill 'c' without using it as a parameter?


Siekmanski

align 16
D3DMatrixMultiply proc pOut:DWORD,pM1:DWORD,pM2:DWORD
; Out = M1 * M2

mov     eax,pM2

movaps  xmm4,[eax]
movaps  xmm5,[eax+16]
movaps  xmm6,[eax+32]
movaps  xmm7,[eax+48]

mov     edx,pM1
mov     eax,pOut

i = 0
REPT 4
movaps  xmm0,[edx+i]
movaps  xmm1,xmm0
movaps  xmm2,xmm0
movaps  xmm3,xmm0
shufps  xmm0,xmm0,00000000b
shufps  xmm1,xmm1,01010101b
shufps  xmm2,xmm2,10101010b
shufps  xmm3,xmm3,11111111b
mulps   xmm0,xmm4
mulps   xmm1,xmm5
mulps   xmm2,xmm6
mulps   xmm3,xmm7
addps   xmm2,xmm0
addps   xmm3,xmm1
addps   xmm3,xmm2
movaps  [eax+i],xmm3
i = i + 16
ENDM   
ret
D3DMatrixMultiply endp
Creative coders use backward thinking techniques as a strategy.

Lonewolff

Isn't pOut a parameter though? Your Proc has 3 parameters.

You seem to be using the same 'workaround' as I am.

Siekmanski

a == pM1
b == pM2
c == pOut

    invoke D3DMatrixMultiply,offset c,offset a,offset b

Matrices need to be 16 byte aligned.
Creative coders use backward thinking techniques as a strategy.

Lonewolff

I think you are missing the meaning of question.

I'll see if I can give a better example.


Take this example then (C++)


struct Thing
{
     float a,b,c,d,e,f,g,h;
}

Thing SomeFunc(Thing blah1, Thing blah2)
{
    // do something with thing blah1 & 2
    // doesn't really matter what

    return someNewThing;
}


Thing blahC
blahC = SomeFunc(blahA, blahB);

Siekmanski

You have to create memory to write "blahC" to.
That's exactly what my routine does pOut is your blahC.

It reads 2 matrices, multiplies them and writes the new calculated matrix in pOut.
Creative coders use backward thinking techniques as a strategy.

Lonewolff

Ok, but just say you have the space created for blahC in the .data section? No way to write the result directly to that without passing as a parameter?

Siekmanski

Yes, I have allocated memory for the empty matrix in the data section, the routine writes the result to that empty matrix memory.
Creative coders use backward thinking techniques as a strategy.

Lonewolff

Yes, but you still need to pass that as a param to the function. Can't just use it as a return value.

Siekmanski

You must think in assembly now, your result is a return value of 64 bytes.
C++ maybe solves it for you, but now you're a real programmer and have to manage those things yourself.  :badgrin:
Creative coders use backward thinking techniques as a strategy.

Lonewolff

Quote from: Siekmanski on April 26, 2018, 12:31:22 PM
You must think in assembly now, your result is a return value of 64 bytes.
C++ maybe solves it for you, but now you're a real programmer and have to manage those things yourself.  :badgrin:

Yep, that's cool. Just wondering if there was a way to do this natively in ASM.  :t

I'll continue thinking 'out of the box'  :biggrin:

jj2007

You can, of course, write in your proc to a hardcoded matrix in the .data? section. But it's considered bad programming.

Your proc should work without that dirty trick. For example, you could HeapAlloc a new matrix inside the proc, and return the pointer in eax (or zero for failure); note, though, that HeapAlloc is align 8 (there is Alloc16 - maybe you find a CRT equivalent)