Hi !:)
Under Masm, these two manners to call a procedure, who is the fastest and optimized ?


;n?1

mov ebx,offset At
mov ecx,offset Proj
call testproj

testproj:
push edx
.if dword ptr[ecx] == 1
mov eax,[ebx+4]
add eax,12
mov edx,[ecx+4]
add edx,12
.if edx > eax
add eax,[ebx+36]
.if edx < eax
mov eax,[ebx+8]
mov edx,[ecx+8]
add edx,6
.if edx > eax
add eax,[ebx+40]
.if edx < eax
mov dword ptr[ebx+28],1
mov dword ptr[ecx],0
.endif
.endif
.endif
.endif
.endif
pop edx
ret
;---------------------------------------------------
;n?2

invoke testproj,addr At, addr Proj

testproj proc Adr_At:DWORD, Adr_Proj:DWORD
push edx
.if Adr_Proj == 1
mov eax,Adr_At+4
add eax,12
mov edx,Adr_Proj+4
add edx,12
.if edx > eax
add eax,Adr_At+36
.if edx < eax
mov eax,Adr_At+8
mov edx,Adr_Proj+8
add edx,6
.if edx > eax
add eax,Adr_At+40
.if edx < eax
mov Adr_At+28,1
mov Adr_Proj,0
.endif
.endif
.endif
.endif
.endif
pop edx
ret
testproj endp

Thanks.
Friendly......Gges
Posted on 2002-08-05 07:30:25 by Asmgges
Well, if optimization is an issue here, I advice you to not use MASM HLA keywords...
The jumps generated by the assembler may be enhanced by rewriting them manually most of the times...

I researched about this there is few months ago... to know what was the best manner to call a function/procedure, but I d'ont remember the results...
Many parameters plays (calling convention, and such), but the fastest would be to use registers to pass arguments... but it has inconvenients...

If the speed is important and you have to avoid calling overhead, write it as a macro, but if it is used frequently, your executable will grow up quickly...
Posted on 2002-08-05 07:37:22 by JCP
Hi! Readiosys:)
Yes, for the HLA you are right but it is just for the way of calling a procedure.
In your opinion n?1 work better?
I can not put this portion of code in macro, she is very often called.
Gges
Posted on 2002-08-05 07:54:31 by Asmgges
compare, benchmark, dissasemble, analyse...

You will find Maverick's procedures to benchmark a portion of code on the FAQ section...
I think the second solutions force MASM to create a stack frame for the procedure, but I'm not sure it doesn't does this everytime... as I said, I tested that sometime ago...

Imho, the best thing to do is to pass parameters to registers if you want speed, generally... but you can hardly reuse the code in C programs, ie.
But unless speed is very critical, don't consider optimizing this, the best thing you may win is one or two cycles... on some CPUs...
Posted on 2002-08-05 08:03:14 by JCP
To be complete I have still to add instructions to the way n?1, it a little slows down appeal.


;n?1
push ebx
push ecx
mov ebx,offset At
mov ecx,offset Proj
call testproj
pop ecx
pop ebx

Thank you very much :)
Friendly........Gges
Posted on 2002-08-05 08:12:48 by Asmgges
If you need to preserve registers, then I would push the parameters directly on the stack... and not by registers...
Posted on 2002-08-05 08:41:09 by JCP
;n?3 ;)


testproj, offset At, offset Proj


testproj MACRO Adr_At:REQ, Adr_Proj:REQ
.if Adr_Proj == 1
push edx
mov eax, Adr_At+4
mov edx, Adr_Proj+4
.if edx > eax
; add eax, 12 ; I don't think these effect anything?
; add edx, 12 ; ;)
add eax, Adr_At+36
.if edx < eax
mov eax, Adr_At+8
mov edx, Adr_Proj+8
add edx, 6
.if edx > eax
add eax, Adr_At+40
.if edx < eax
mov Adr_At+28, 1
dec Adr_Proj ; it was one above!
.endif
.endif
.endif
.endif
pop edx
.endif
ENDM
Getting rid of the HLL syntax isn't going to help this algo by itself. Instead try to move instructions into the center, in the hopes that the branch will be taken and the code will not execute. In many ways there is not negitive cost for this in the case where the branch isn't taken. (ex. See how the push/pop is moved inside.) Also, adding 12 to both EAX/EDX seems to accomplish nothing? Remember your school math here. :)
Posted on 2002-08-05 08:46:35 by bitRAKE
Readiosys :)
But it will be all the same necessary to protect them in the function to make calculations and in more I would have parameters has to call back of the pile?
It makes less instructions not?:confused:
Friendly.......Gges
Posted on 2002-08-05 08:54:37 by Asmgges
Your objectives seems to be unclear...

What registers do you need to preserve ? For what do you need to preserve the registers?

I advice you to do the register preservation inside of the procedure rather than outside of it...
But I'm reading the thread very quickly since I'm at work and don't have much time now...
Posted on 2002-08-05 09:10:26 by JCP
I believe that we go away us from the question of the first post.:)
Registers must be protected because this function is included in the other functions and the procedures and all the available registers are used, I have necessarily to restore them with their values of origin after use.
BitRAKE beautiful demonstration but it is the macro and you that do you think of the question procedures or functions under Masm?
Friendly........Gges
Posted on 2002-08-05 09:43:01 by Asmgges
Under MASM use PROC. I do, but only to decorate the function and document the interface - I turn off PROLOGUE/EPILOGUE code generation in most cases. Also, labels in PROCs are local by default and this is good for the programmer. :)
Posted on 2002-08-05 10:03:53 by bitRAKE

I believe that we go away us from the question of the first post.:)
Registers must be protected because this function is included in the other functions and the procedures and all the available registers are used, I have necessarily to restore them with their values of origin after use.
BitRAKE beautiful demonstration but it is the macro and you that do you think of the question procedures or functions under Masm?
Friendly........Gges


I don't think we go away from the original question...
In order to have the best solution, one must know the exact situation and environment...
Posted on 2002-08-05 10:09:48 by JCP
Thank you BitRAKE, it is true that PROC under MASM does not miss advantages.
:)
Friendly...........Gges
Posted on 2002-08-05 10:16:42 by Asmgges
Readiosys, is correct as well. It is not one or the other - for we can use all at the same time. PROC, functions, macros - they are good together. Use them all and get comfortable with the syntax.
Posted on 2002-08-05 10:26:13 by bitRAKE
Naturally that Readiosys is right also and I thank him for giving the opinion, it depends on the environment and on the context, the functions with addressing indexed are more difficult to read and I wondered if it had more speed than MASM'S PROC which are more legible and easier to use.
Thank you to you Readiosys,bitRAKE:)
Friendly.......Gges
Posted on 2002-08-05 10:38:03 by Asmgges
Unfortunately, the two versions are not equivalent.
testproj proc Adr_At:DWORD, Adr_Proj:DWORD

push edx
.if Adr_Proj == 1
mov eax,Adr_At+4
The value of Adr_Proj is offset Proj, which is very unlikely to ever equal 1. Also, mov eax,Adr_At+4 loads EAX with the value of Adr_Proj, not with the data at . The x86 does not perform data indirection via memory. MASM operand expression syntax is not C expression syntax.

bitRAKE fixed the problem by changing the PROC to a macro. But as you may know, a macro creates several copies if it is used more than once.
Posted on 2002-08-05 18:58:01 by tenkey
If speed is the need do all the code in line.
If speed and size use labels and not procs.
If understanding is the need use only procs.
IMHO Trade offs Trade offs
Posted on 2002-08-05 19:08:46 by Roy Cline
Unfortunately, the two versions are not equivalent.

Yes you are right :) , there is confusion between address and contents of address then here is equivalents
The same speed or different?



;n?1

push ebx
push ecx
mov ebx,offset At
mov ecx,offset Proj
call testproj
pop ecx
pop ebx

testproj:
.if dword ptr[ecx] == 1
mov eax,[ebx+4]
.endif
ret
;---------------------------------------------------
;n?2

invoke testproj,addr At, addr Proj

testproj proc Adr_At:DWORD, Adr_Proj:DWORD
push ebx
push ecx
mov ebx,Adr_At
mov ecx,Adr_Proj
.if dword ptr[ecx] == 1
mov eax,[ebx+4]
.endif
pop ecx
pop ebx
ret
testproj endp

Friendly....Gges
Posted on 2002-08-06 02:45:24 by Asmgges
The second form is slightly slower. The more work you do in the PROC, the less overhead (%-wise).

Assuming PROC generates STDCALL convention, the INVOKE and PROC look like this:
    push offset At

push offset Proj
call testproj


testproj:
push ebp
mov ebp,esp

; ... user code...

; expansion of [b]ret[/b]
mov esp,ebp
ret 8
If PROC generates C (or CDECL) convention, I expect it to look like this:
    push offset At

push offset Proj
call testproj
add esp,8


testproj:
push ebp
mov ebp,esp

; ... user code...

; expansion of [b]ret[/b]
mov esp,ebp
ret
Posted on 2002-08-07 17:05:04 by tenkey
Thank you tenkey for these good explanations:)
Friendly.......Gges
Posted on 2002-08-08 02:05:08 by Asmgges