News:

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

PROTO vs PROC

Started by unktehi, March 03, 2009, 09:32:06 PM

Previous topic - Next topic

unktehi

Can someone help me understand the difference between using PROTO and PROC?

Don't they pretty much do the same thing?

The book describes proto as a directive that helps the assembler validate procedure calls by verifying arguments by checking argument lists against procedure declarations.  Does this mean that proto checks the declarations of a procedure stated elsewhere or does proto replace the proc call and check the arguments with it?

Mark Jones

A PROC's arguments are defined by a PROTO statement. Then, when you use the PROC, the types supplied to it are checked against the PROTO. This is supposed to help prevent confusing errors by forcing the coder to supply the correct data types to PROCs.
"To deny our impulses... foolish; to revel in them, chaos." MCJ 2003.08

KeepingRealBusy

If the PROC is defined in the same assembly before it is referenced, then the PROC serves as its own PROTO, the assembler has enough information to validate the arguments. If the PROC is not yet defined when referenced, then the assembler needs a PROTO which defines at least the parameters required by the PROC so validation can be done.

unktehi

So it sounds like you can have both a PROC and  PROTO call in the same file.  The proto verifying the information in the proc - correct? (The book doesn't have any examples of code with both shown if that is the case).

MichaelW

A label PROC...ENDP is a procedure definition. A PROTO is a type of declaration that provides the minimal information necessary to call the procedure using INVOKE. A PROTO is not necessary to call a procedure using CALL. The prototyped procedure can be defined in the current module, or in some other module or library.
eschew obfuscation

redskull

Nether are 'officially' necessary.  PROC/ENDP is, in essence, a macro that automatically builds you a stack frame (and tears it down later), but it has the added advantage that it allows the use of INVOKE, which in turn is essentially a macro which PUSHes your parameters and executes the CALL.  But again, you can do it all by hand (and probably should, at least once, so you know what it being automatically put into your code).  The PROTO, on the other hand, is just a 'heads up' to the assembler about the number of arguments a PROC has, in the event you INVOKE it beforehand.  The assembler reads the source top-to-bottom, so if you try and invoke a function before the assembler has gotten around to reading it, it has no idea about the number of parameters it has.  The PROTO is not necessary if you make sure to put the function being called earlier in the source than the function calling it (By the time it gets to the INVOKE, it has already completed the PROC and therefore knows how many parameters it needs).  Just to be clear: PROC/ENDP and INVOKE will put extra instructions into your code (to make the stack frame and make the calls), but PROTO will not.  Both are just shortcuts to automate the PUSH/PUSH/PUSH/PUSH/CALL method of function calls, ubiquitous to win32 programming.

-ac
Strange women, lying in ponds, distributing swords, is no basis for a system of government

PBrennick

A PROTO allows you to use forward referencing at compile time. Otherwise the procedure would be unknown during the first pass. If the procedure being invoked is placed BEFORE the invoke statement the PROTO is unnecessary. Although it is unnecessary in that case, it still is useful as it does parameter matching and will burp out a message if you do not have the correct amount of parameters. Because of this, I always use PROTO statements.

Paul
The GeneSys Project is available from:
The Repository or My crappy website

Vortex

Hi unktehi,

redskull is right, the PROC/ENDP pair is a macro and you can code your own functions without the overhead :


include     SimpleFunc.inc

.data
format1     db '50 - 10 = %d',0

.data?
buffer      db 20 dup(?)

.code

start:

    push    10
    push    50
    call    substract
    invoke  wsprintf,ADDR buffer,ADDR format1,eax
    invoke  StdOut,ADDR buffer
    invoke  ExitProcess,0

substract:

    mov     eax,DWORD PTR [esp+4]
    sub     eax,DWORD PTR [esp+8]
    ret     2*4

END start

[attachment deleted by admin]

jj2007

Here is a variant that you might occasionally see here: OPTION PROLOGUE:NONE switches the automatic stack frame off. The MyProc below produces exactly the same code as subtract, but it allows calling with invoke. Note the two equates ARG1 and ARG2 - they allow to use mov eax, ARG1 as if there was a stack frame.

None of these solutions is "better" - it's a matter of personal preferences, and maybe readability and ease of maintenance.

Note that both versions require a ret 2*4 - since there is no EPILOGUE macro, you must tell the assembler how to adjust the stack before returning.

include     SimpleFunc.inc

MyProc PROTO: DWORD, :DWORD
ARG1 equ DWORD PTR [esp+4]
ARG2 equ DWORD PTR [esp+8]

.data
format1 db '50 - 10 = %d', 13, 10, 0

.data?
buffer      db 20 dup(?)

.code

start:

    push    10
    push    50
    call    subtract

    invoke  wsprintf,ADDR buffer,ADDR format1,eax
    invoke  StdOut,ADDR buffer


    invoke MyProc, 50, 10

    invoke  wsprintf,ADDR buffer,ADDR format1,eax
    invoke  StdOut,ADDR buffer
   

    invoke  ExitProcess,0

subtract:

    mov     eax,DWORD PTR [esp+4]
    sub     eax,DWORD PTR [esp+8]
    ret     2*4

OPTION PROLOGUE:NONE
OPTION EPILOGUE:NONE

MyProc proc arg1_dummy:DWORD, arg2_dummy:DWORD
    mov eax, ARG1
    sub eax, ARG2
    ret 2*4
MyProc endp

; more procs without stack frame here...

OPTION PROLOGUE:PrologueDef
OPTION EPILOGUE:EpilogueDef

END start