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 :)
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
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.
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?
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
Isn't pOut a parameter though? Your Proc has 3 parameters.
You seem to be using the same 'workaround' as I am.
a == pM1
b == pM2
c == pOut
invoke D3DMatrixMultiply,offset c,offset a,offset b
Matrices need to be 16 byte aligned.
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);
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.
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?
Yes, I have allocated memory for the empty matrix in the data section, the routine writes the result to that empty matrix memory.
Yes, but you still need to pass that as a param to the function. Can't just use it as a return value.
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:
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:
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 (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1378) - maybe you find a CRT equivalent)
Yeah, I thought of something like this, but it would slowdown the code considerably.
And I have made my functions 'data.' free. So there isn't any hidden memory usage, also using registers as much as I can to keep speed right up there.
There is no difference between C/C++ and MASM, simply C/C++ hides the complexity from you.
"... and larger structures and class objects .... are returned in memory. To pass "in memory", the caller allocates memory and passes a pointer to it as a hidden first parameter; the callee populates the memory and returns the pointer, popping the hidden pointer when returning."
There is really no other way to do it without a lot of malabarism.
Quote from: aw27 on April 26, 2018, 03:17:27 PM
There is no difference between C/C++ and MASM, simply C/C++ hides the complexity from you.
"... and larger structures and class objects .... are returned in memory. To pass "in memory", the caller allocates memory and passes a pointer to it as a hidden first parameter; the callee populates the memory and returns the pointer, popping the hidden pointer when returning."
There is really no other way to do it without a lot of malabarism.
Ah cool. That makes a lot of sense.
Not for the faint of hearts, as Hutch says
welcome to the world of macho programmers, if it's only one line of code, it's not asm (surely, this is only a joke :D)
Quote from: Ascended on April 26, 2018, 11:55:41 AM
A) Ok, but just say you have the space created for blahC in the .data section?
B) No way to write the result directly to that without passing as a parameter?
Your question B) seems to me curious because you dont want to pass the output address as
a parameter. And the answer to your question is
YES you can ... but you have a lot of problems ...
Quote
.data?
blahC dd 16 dup (?) ; for matrix 4x4 real4
.code
MultiplyMatAbyB proc pMatA:DWORD, pMatB:DWORD
push edi
mov edi, offset blahC
; now we have HERE the output address in edi
; or replace edi by edx and comment push and pop
; do what you want
pop edi
ret
MultiplyMatAbyB endp
So, for
each output matrix blahD,
blahE,...,
blahZ you need to write
one procedure to do what you want to do. Is this what you want to do ? Is it usable ? (
maybe if you dont need to save each result)