Procedures require a label at the start of the procedure and a return at the end. Procedures are normally defined by using the PROC directive at the start of the procedure and the ENDP directive at the end. The RET instruction is normally placed immediately before the ENDP directive. The assembler makes sure that the distance of the RET instruction matches the distance defined by the PROC directive. The basic syntax for PROC is
labelPROC [[NEAR|FAR]]
.
.
.
RET [[constant]]
label ENDP
The CALL instruction pushes the address of the next instruction in your code onto the stack and passes control to a specified address. The syntax is
CALL {label|register|memory}
The operand contains a value calculated at run time. Since that operand can be a register, direct memory operand, or indirect memory operand, you can write call tables similar to the jump table illustrated in Section 7.1.1.2.
Calls can be near or far. Near calls push only the offset portion of the calling address and therefore must be within the same segment or group. You can specify the type for the target operand, but if you do not, MASM uses the declared distance (NEAR or FAR) for operands that are labels and for the size of register or memory operands. Then the assembler encodes the call appropriately, as it does with unconditional jumps (see Sections 7.1.1, “Unconditional Jumps,” and 7.1.2, “Conditional Jumps”).
MASM 6.0 optimizes a call to a far label when the label is in the current segment by generating the code for a near call, saving one byte.
You can define procedures without PROC and ENDP, but if you do, you must make sure that the size of the CALL matches the size of the RET. You can specify the RET instruction as RETN (Return Near) or RETF (Return Far) to override the default size:
call NEAR PTR task ; Call is declared near
. ; Return comes to here
.
.
task: ; Procedure begins with near label
.
. ; Instructions go here
.
retn ; Return declared near
The syntax for RETN and RETF is
label: |label NEAR
statements
RETN[[constant]]
label LABEL FAR
statements
RETF [[constant]]
The RET instruction (and its RETF and RETN variations) allows an optional constant operand that specifies a number of bytes to be added to the value of the SP register after the return. This operand adjusts for arguments passed to the procedure before the call, as shown in the example in Section 7.3.4, “Using Local Variables.”
Summary: Incorrect size for RET can cause your program to fail.
When you define procedures without PROC and ENDP, you must make sure that calls have the same size as corresponding returns. For example, RETF pops two words off the stack. If a NEAR call is made to a procedure with a far return, not only is the popped value meaningless, but the stack status may cause the execution to return to a random memory location, resulting in program failure.
There is an also an extended PROC syntax that automates many of the details of accessing arguments and saving registers. See Section 7.3.3, “Declaring Param-eters with the PROC Directive.”