Return Must Match Memory Model for CALL to Label in Proc

Last reviewed: January 23, 1995
Article ID: Q70671
The information in this article applies to:
  • Microsoft Macro Assembler for MS-DOS, version 5.1, 5.1a, 6.0, 6.0a, and 6.0b
  • Microsoft Macro Assembler for OS/2, versions 5.1, 5.1a, 6.0, 6.0a, and 6.0b

SUMMARY

With the Macro Assembler (MASM), if a CALL is made to a label within a procedure, a near call is generated by default. Depending on the memory model being used, you may need to explicitly specify the correct return.

MORE INFORMATION

The standard RET instruction pops off the return address depending on the memory model. In a small memory model program, the RET instruction is converted to a RETN, which only pops off the offset to return. In medium and large memory models, the RET is converted to RETF, which pops off both the segment and offset to return from the far call. Because a call to a label within a procedure always results in a near call, the RETF instruction that is generated in medium and large models will pop a segment value for the return address that was never pushed.

To ensure that the right size address is popped off the stack relative to that pushed on the stack, one of the following methods may be used:

  1. Use the RET return, but push CS before the call so that the segment and offset will both be on the stack for the far return:

          PUSH CS
          CALL label1
    

- or -

  1. Use the FAR PTR override on the call along with a RET to return, so that both segment and offset are pushed and popped off the stack:

          CALL FAR PTR label1
    

- or -

  1. Use the LABEL FAR directive along with a RET return so that the assembler will generate a far return to match the far label call:

          label1 LABEL FAR
    

- or -

  1. If the label is called ONLY from within the procedure, use RETN explicitly (instead of RET) to indicate the NEAR return, so that only the offset is popped off the stack:

          label1:
    
                   RETN
    
    
The sample code below demonstrates the need for the proper return for a call to a label. When assembled and run as is, the code will hang the computer. Adding any of the solutions described above will correct the code. Comments are included at the locations where each correction should go.

Sample Code

; Assemble options needed : none

.MODEL large

.STACK

.CODE

start: call proc1

        mov ah, 4ch
        mov al, 0
        int 21h

proc1   PROC
                       ; #1 - add PUSH CS instruction here
        CALL label1    ; #2 - change call to CALL FAR PTR label1
        RET

label1:                ; #3 - change label to label1 LABEL FAR
        RET            ; #4 - change return to RETN

proc1   ENDP

END start


Additional reference words: kbinf 5.10 5.10 6.00 6.00a 6.00b
KBCategory: kbprg
KBSubCategory: MASMLngIss


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: January 23, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.