Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- Watcom C/C++ User's Guide - let us now consider the example in the previous section except this time we http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
Let us now consider the example in the previous section except this time we
will use the stack-based calling convention.  The most significant
difference between the stack-based calling convention and the register-based
calling convention is the way the arguments are passed.  When using the
stack-based calling conventions, no registers are used to pass arguments.
 Instead, all arguments are passed on the stack.

Let us look at the stack upon entry to myrtn.


     Small Code Model
     Offset
             +----------------+
       0     | return address | <- ESP points here
             +----------------+
       4     | argument #1    |
             |                |
             +----------------+
      12     | argument #2    |
             |                |
             +----------------+
      16     | argument #3    |
             |                |
             +----------------+
      24     |                |


     Big Code Model
     Offset
             +----------------+
       0     | return address | <- ESP points here
             |                |
             +----------------+
       8     | argument #1    |
             |                |
             +----------------+
      16     | argument #2    |
             |                |
             +----------------+
      20     | argument #3    |
             |                |
             +----------------+
      28     |                |

Notes:

 1. The return address is the top element on the stack.  In a small code
    model, the return address is 1 double word (32 bits)

Register EBP is normally used to address arguments on the stack.  Upon entry
to the function, register EBP is set to point to the stack but before doing
so we must save its contents.  The following two instructions achieve this.


     push    EBP           ; save current value of EBP
     mov     EBP,ESP       ; get access to arguments

After executing these instructions, the stack looks like this.


     Small Code Model
     Offset
             +----------------+
       0     | saved EBP      | <- EBP and ESP point here
             +----------------+
       4     | return address |
             +----------------+
       8     | argument #1    |
             |                |
             +----------------+
      16     | argument #2    |
             |                |
             +----------------+
      20     | argument #3    |
             |                |
             +----------------+
      28     |                |


     Big Code Model
     Offset
             +----------------+
       0     | saved EBP      | <- EBP and ESP point here
             +----------------+
       4     | return address |
             |                |
             +----------------+
      12     | argument #1    |
             |                |
             +----------------+
      20     | argument #2    |
             |                |
             +----------------+
      24     | argument #3    |
             |                |
             +----------------+
      32     |                |

As the above diagrams show, the argument are all on the stack and are
referenced by specifying an offset from register EBP.

Upon exit from myrtn, we must restore the value of EBP.  The following two
instructions achieve this.


     mov     ESP,EBP       ; restore stack pointer
     pop     EBP           ; restore EBP

The following is a sample assembly language function which implements myrtn.


     Small Memory Model (small code, small data)
     DGROUP        group   _DATA, _BSS
     _TEXT         segment byte public 'CODE'
                   assume  CS:_TEXT
                   assume  DS:DGROUP
                   public  myrtn
     myrtn         proc    near
                   push    EBP
                   ; save EBP
                   mov     EBP,ESP   ; get access to arguments
     ;
     ; body of function
     ;
                   mov     ESP,EBP   ; restore ESP
                   pop     EBP
                   ; restore EBP
                   ret
                   ; return
     myrtn         endp
     _TEXT         ends


     Large Memory Model (big code, big data)
     DGROUP        group             _DATA, _BSS
     MYRTN_TEXT segment byte public 'CODE'
                   assume            CS:MYRTN_TEXT
                   public            myrtn
     myrtn         proc              far
                   push              EBP
                   ; save EBP
                   mov               EBP,ESP
                   ; get access to arguments
     ;
     ; body of function
     ;
                   mov               ESP,EBP
                   ; restore ESP
                   pop               EBP
                   ; restore EBP
                   ret
                   ; return
     myrtn         endp
     MYRTN_TEXT ends

Notes:

 1. Global function names must not be followed with an underscore as was the
    case with the register-based calling convention.  Global variable names
    must not be preceded with an underscore as was the case with the
    register-based calling convention.

 2. All used 80x86 registers except registers EAX, ECX and EDX must be saved
    on entry and restored on exit.  Segment registers DS and ES must also be
    saved on entry and restored on exit.  Segment register ES does not have
    to be saved and restored when using a memory model that is not a small
    data model.  Note that segment registers only have to be saved and
    restored if you are compiling your application with the "r" option.

 3. The direction flag must be clear before returning to the caller.

 4. In a small code model, any segment containing executable code must
    belong to the segment "_TEXT" and the class "CODE".  The segment "_TEXT"
    must have a "combine" type of "PUBLIC".  On entry, CS contains the
    segment address of the segment "_TEXT".  In a big code model there is no
    restriction on the naming of segments which contain executable code.

 5. In a small data model, segment register DS contains the segment address
    of the group "DGROUP".  This is not the case in a big data model.

 6. When writing assembly language functions for the small code model, you
    must declare them as "near".  If you wish to write assembly language
    functions for the big code model, you must declare them as "far".

 7. In general, when naming segments for your code or data, you should
    follow the conventions described in the section entitled "Memory Layout"
    in this chapter.

 8. The caller is responsible for removing arguments from the stack.

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson