News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Am I doing it right?

Started by Farabi, March 24, 2010, 12:32:59 PM

Previous topic - Next topic

Farabi

Is this right?


fOpenCVcvCreateVideoWriter proc lpFileName:dword,nType:dword[b],flFrame:qword[/b],nSize:POINT,nFlag:dword

push nFlag
push nSize.y
push nSize.x
push [b]dword ptr flFrame[4][/b]
push [b]dword ptr flFrame[0][/b]
push nType
push lpFileName
call cvCreateVideoWriter
add esp,28

ret
fOpenCVcvCreateVideoWriter endp
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

qWord

yes.
Why not declaring an prototype for this function and then use invoke - looks nicer :bg

cvCreateVideoWriter proto c :DWORD,:DWORD,:QWORD,:DWORD,:DWORD,:DWORD
...
invoke cvCreateVideoWriter,lpFileName,nType,flFrame,nSize.x,nSize.y,nFlag

FPU in a trice: SmplMath
It's that simple!

Farabi

Quote from: qWord on March 24, 2010, 12:57:46 PM
yes.
Why not declaring an prototype for this function and then use invoke - looks nicer :bg

cvCreateVideoWriter proto c :DWORD,:DWORD,:QWORD,:DWORD,:DWORD,:DWORD
...
invoke cvCreateVideoWriter,lpFileName,nType,flFrame,nSize.x,nSize.y,nFlag



I will need the lib function and I dont know how to produce it, so I used GetProcAddress and call it directly.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

dedndave

        add     esp,28

        ret

        ret     28

:bg

MichaelW

Dave,

ML will add the 28 to the RET, and the stack adjustment after cvCreateVideoWriter returns is necessary because it uses the C calling convention.

Farabi,

Based on this:

typedef struct
{
    int width;
    int height;
}
CvSize;

#define CV_FOURCC(c1,c2,c3,c4)  \
    (((c1)&255) + (((c2)&255)<<8) + (((c3)&255)<<16) + (((c4)&255)<<24))

/* initialize video file writer */
CVAPI(CvVideoWriter*) cvCreateVideoWriter( const char* filename, int fourcc,
                                           double fps, CvSize frame_size,
                                           int is_color CV_DEFAULT(1));


Your code looks right to me. Have you considered using the MASM32 CPROTO macro? You will still need to use LoadLibrary and GetProcAddress, but you would then be able to use invoke and let it generate the code to push the parameters, including the REAL8 and the POINT structure.

In the course of finding the header files I found a statement that the compiled libraries are available only for MinGW, not for the Microsoft compilers.
eschew obfuscation

dedndave

well - if you didn't use the default epilogue, you could combine the balancing pops with the ret

however, the whole thing might be better off written as a macro rather than as a proc
it seems silly to push all those parms, call the proc, then push them all again, only to have to pop them all off, twice

japheth

Quote from: dedndave on March 25, 2010, 03:02:30 AM
well - if you didn't use the default epilogue, you could combine the balancing pops with the ret

Hm, I'm sceptical about this. But lets wait until BogdanOntanu has discovered your post. He will "wash you the head" (literally translated from German).

Quote
however, the whole thing might be better off written as a macro rather than as a proc
it seems silly to push all those parms, call the proc, then push them all again, only to have to pop them all off, twice

This is necessary, because with the C calling convention, the callee is allowed to modify the values of the parameters.

Farabi

Quote from: MichaelW on March 25, 2010, 02:37:05 AM
Dave,

ML will add the 28 to the RET, and the stack adjustment after cvCreateVideoWriter returns is necessary because it uses the C calling convention.

Farabi,

Based on this:

typedef struct
{
    int width;
    int height;
}
CvSize;

#define CV_FOURCC(c1,c2,c3,c4)  \
    (((c1)&255) + (((c2)&255)<<8) + (((c3)&255)<<16) + (((c4)&255)<<24))

/* initialize video file writer */
CVAPI(CvVideoWriter*) cvCreateVideoWriter( const char* filename, int fourcc,
                                           double fps, CvSize frame_size,
                                           int is_color CV_DEFAULT(1));


Your code looks right to me. Have you considered using the MASM32 CPROTO macro? You will still need to use LoadLibrary and GetProcAddress, but you would then be able to use invoke and let it generate the code to push the parameters, including the REAL8 and the POINT structure.

In the course of finding the header files I found a statement that the compiled libraries are available only for MinGW, not for the Microsoft compilers.


If I used the CPROTO macro RadAsm will not show the full name on the Function list, it mean, longer time to type.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

dedndave

lol Japheth
i tend to iggy everything bogdan says   :P

as for making it C compatible, there has to be a better way than pushing everything twice
Onan doesn't seem to be reading any of the possibly-modified returned parms
even if he were, the desired returned values could be saved in variables prior to balancing the stack
this just seems like a lot of bloat to me

Farabi

Anyway, what is good FOURCC for mpeg file? I tried to record the video but it doesnot work. That was wierd, it was worked before.
Those who had universe knowledges can control the world by a micro processor.
http://www.wix.com/farabio/firstpage

"Etos siperi elegi"

MichaelW

Quote from: dedndave on March 25, 2010, 03:02:30 AM
well - if you didn't use the default epilogue, you could combine the balancing pops with the ret

however, the whole thing might be better off written as a macro rather than as a proc
it seems silly to push all those parms, call the proc, then push them all again, only to have to pop them all off, twice

Judging from this test:

;====================================================================
.NOLIST
;====================================================================
    include \masm32\include\masm32rt.inc
;====================================================================
.LISTALL
;====================================================================
    .data
    .code
;====================================================================

proc2 proc c p1:DWORD, p2:DWORD, p3:DWORD
    print str$(p1),9
    print str$(p2),9
    print str$(p3),13,10
    ret
proc2 endp

;====================================================================

.data
    proc1_return_address dd 0
.code

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

proc1 proc p1:DWORD, p2:DWORD, p3:DWORD
    pop proc1_return_address
    call proc2
    push proc1_return_address
    ret 12
proc1 endp

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

;====================================================================
start:
;====================================================================
    print hex$(esp),13,10
    invoke proc1, 1, 2, 3
    print hex$(esp),13,10,13,10

    inkey "Press any key to exit..."
    exit

;====================================================================
end start


For the 5 parameters involved, it looks like you could reduce the code size by perhaps 20 bytes, at the cost of making the code harder to understand.

eschew obfuscation

Astro

#11
Hi,

My brain is fried LOL. Hope the following makes sense. Excuse some of the comments - I'm trying to keep track of everything, not preach to the converted.

If I missed the point, I apologize.

Your function, modified:



; blah blah

call fOpenCVcvCreateVideoWriter ; I'm guessing you make this call somehow...

; blah blah

fOpenCVcvCreateVideoWriter proc ;;;;;;;;; lpFileName:dword,nType:dword[b],flFrame:qword[/b],nSize:POINT,nFlag:dword ; 28 bytes

; push ebp
; mov ebp,esp ; (I noticed in my apps that this is always explictly added to my code when it is built)

; STACK CONTENTS [LOCATION]:
; EIP+4 [ESP+4]
; EBP [ESP]

; The following call will cause a push of EIP+4 to the stack. As you have not pop'd the contents, and subsequently not push'd them again
; we need to adjust the stack to act as if the original call to this proc never happened. It requires some careful counting, so check this twice.
;
; We know we had a push of ebp before anything here happened, so we first restore ebp to the state before the call to this proc:

pop ebp

; STACK CONTENTS [LOCATION]:
; EIP+4 [ESP]

; we now hide the return address push'd from the original call (requires temporary global DWORD)
mov eax,[esp]
mov TempEIP,eax

add esp,4 ; remove the return address from the stack

; STACK CONTENTS [LOCATION]:
; LAST PUSHED VARIABLE [ESP]

call cvCreateVideoWriter ; make the call - the stack should be as if the call to this proc never happened

; There are 28 bytes to clean from the stack, and we need to restore the world before returning otherwise we die
; First, clean the stack of the variables:

add esp,24 ; 28 - 4 to make room for the restoration of the return address, whilst cleaning the stack at the same time

; Next restore the balance of the world:

mov ecx,TempEIP
mov [esp],ecx

; STACK CONTENTS [LOCATION]:
; EIP+4 [ESP]

push ebp

; STACK CONTENTS [LOCATION]:
; EIP+4 [ESP+4]
; EBP [ESP]

; pop ebp ; (I noticed in my apps that this is always explictly added to my code when it is built)

; The world is restored!

ret

fOpenCVcvCreateVideoWriter endp


Without the comments, the function looks like:

fOpenCVcvCreateVideoWriter proc

pop ebp
mov eax,[esp]
mov TempEIP,eax
add esp,4 ; remove the return address from the stack

call cvCreateVideoWriter ; make the call

add esp,24 ; clean the stack of the variables
mov ecx,TempEIP
mov [esp],ecx
push ebp

ret

fOpenCVcvCreateVideoWriter endp


You could make macros from the two code blocks quite easily to clean up the code. The above should work, but is untested. Hope it is kind of what you're looking for! :bg Will hopefully be faster than a lot of push'ing and pop'ing.

I guess if you really wanted to abuse the registers, you could store the return address in fs:[0]:

push dword ptr fs:[0] ; store current exception handler
; push params
call fOpenCVcvCreateVideoWriter
pop dword ptr fs:[0] ; restore exception handler

;.........................
;.........................
;.........................


fOpenCVcvCreateVideoWriter proc

;.........................

; Replace the following three lines:

;mov eax,[esp]
;mov TempEIP,eax
;add esp,4 ; remove the return address from the stack

; With:

pop dword ptr fs:[0] ; store the return address as the exception handler! It might blow up though if it is ever called

;.........................

;add esp,24 ; clean the stack of the variables
;mov ecx,TempEIP
;mov [esp],ecx

add esp,28 ; clean the stack of the variables
push dword ptr fs:[0]

;.........................

fOpenCVcvCreateVideoWriter endp


and eliminate TempEIP. You still end up with 4 memory accesses, but might be slightly quicker, and several bytes shorter.

Without comments:

;....
push dword ptr fs:[0]
; push...
call fOpenCVcvCreateVideoWriter
pop dword ptr fs:[0]
;....

fOpenCVcvCreateVideoWriter proc

pop ebp
pop dword ptr fs:[0]

call cvCreateVideoWriter ; make the call

add esp,28 ; clean the stack of the variables
push dword ptr fs:[0]
push ebp

ret

fOpenCVcvCreateVideoWriter endp


Best regards,
Robin.