Example 1: show how the codes we learn builds and tear down a stack frame
 

 public class Sample 
 {
    public static void main( )
    {
       A(1111,2222);
    }

    public static int A( int a, int b )
    {
       int  x, y, z;    // Define 3 local vars 

       // I want to show you where to
       // find the parameters and 
       // local variables on the stack

       return(9999);    // A( ) simply returns 9999
    }
 }
   

This examples shows you the steps to build + tear down stack frame for 1 (non-leaf) subroutine

Assembler code for the skeletal example

main:
        mov   r0, #2222    // Pass 2222 as parameter 2 on stack
        push  {r0}

        mov   r0, #1111    // Pass 1111 as parameter 1 on stack
        push  {r0}

        bl    A            // Call function A
        add   sp, sp, #8   // Clean up parameters on the stack

        // When A returns, you will see the return value in r0 = 9999

        nop
        nop
Stop:
        nop


/* ==============================================
   Function A: param and locals in stack
   ============================================== */
A:
        // When run in EGTAPI - you will see {1111, 2222} on stack

        /* ****************************************
           Prelude: build stack frame
           **************************************** */
        push    {lr}            // Save return address in LR
        push    {fp}            // Save Frame Pointer in FP
        mov     fp, sp          // Initialize my own FP
        sub     sp, sp, #12     // I create 3 local variable in stack

        // How to to access parameters and local variables
        // stored in the program stack

        ldr     r0, [fp, #8]    // Get parameter 1 = 1111
        str     r0, [fp, #-12]  // Store in local variable 1
        ldr     r1, [fp, #12]   // Get parameter 2 = 2222
        str     r1, [fp, #-8]   // Store in local variable 2
        add     r0, r0, r1
        str     r0, [fp, #-4]   // Store sum in local variable 3


       /* ====================================================
           We can use a register to return the return value
           ==================================================== */
        mov   r0, #9999         // Pass return value in register r0

        /* ************************************************
           Postlude: break down stack frame
           ************************************************ */
        mov     sp, fp          // De-allocate the local variables
        pop     {fp}            // Restore old FP

        pop     {pc}            // Return
   

DEMO:   /home/cs255001/demo/asm/8-sub/skel-access.s

Important facts to notice in the example

  • Before main( ) calls A( ), the program stack is empty

  • After A( ) finishes building the stack frame, the stack frame has this structure:

  • After main( ) cleans up the parameters, the program stack is also empty

Example 2: show how the codes we learn builds and tear down 2 stack frames

 public class Sample 
 {
    public static void main( ) {
       A(1111,2222);
    }

    public static int A( int a, int b ) {
       int  x, y, z;    // Define 3 local vars 

       B(3333,4444,5555);

       return(9999);    // A( ) simply returns 9999
    }

    public static int B( int a, int b, int c ) {
       int  x, y;       // Define 2 local vars  

       return(8888);
    }
 }
   

This examples shows you the steps to build + tear down stack frame for 2 (non-leaf) subroutines

Assembler code for the skeletal example

main:
        mov   r0, #2222    // Pass 2222 as parameter 2 on stack
        push  {r0}

        mov   r0, #1111    // Pass 1111 as parameter 1 on stack
        push  {r0}

        bl    A            // Call function A
        add   sp, sp, #8   // Clean up parameters on the stack

        // When A returns, you will see the return value in r0 = 9999

        nop
        nop
Stop:
        nop


/* ==============================================
   Function A: param and locals in stack
   ============================================== */
A:
        // When run in EGTAPI - you will see {1111, 2222} on stack

        /* ****************************************
           Prelude: build stack frame
           **************************************** */
        push    {lr}            // Save return address in LR
        push    {fp}            // Save Frame Pointer in FP
        mov     fp, sp          // Initialize my own FP
        sub     sp, sp, #12     // I create 3 local variable in stack

        nop                     // These instructions in A( ) can use stack
        nop                     // to access parameters and local variables


        /* =========================================
           Call B( ) with 3 parameters
           ========================================= */
        mov   r0, #5555    // Pass 5555 as parameter 3 on stack
        push  {r0}

        mov   r0, #4444    // Pass 4444 as parameter 2 on stack
        push  {r0}

        mov   r0, #3333    // Pass 3333 as parameter 1 on stack
        push  {r0}

        bl    B            // Call function B
        add   sp, sp, #12  // Clean up parameters on the stack

        nop                // We are back in A( )
        nop                // We will now return to main( )




       /* ====================================================
           We can use a register to return the return value
           ==================================================== */
        mov   r0, #9999         // Pass return value in register r0

        /* ************************************************
           Postlude: break down stack frame
           ************************************************ */
        mov     sp, fp          // De-allocate the local variables
        pop     {fp}            // Restore old FP

        pop     {pc}            // Return
   

DEMO:   /home/cs255001/demo/asm/8-sub/skel-stack2.s

Important facts to notice in the example

  • Before main( ) calls A( ), the program stack is empty

  • After A( ) finishes building the stack frame, the stack frame has this structure:

Continue...

Important facts to notice in the example

  • After B( ) finishes building the stack frame, the stack frame has this structure:

    Notice that A( )'s parameters and local variables are still saved on the stack !

Continue...

Important facts to notice in the example

  • After B( ) has returned and A( ) has cleaned up the parameters in the program stack, the program stack is restored back to:

    Notice that the FP register is restored so A( ) can use the base address in FP to access its parameters and local variables !

Continue...

Important facts to notice in the example
 

  • Before main( ) make a function call, the program stack was empty

  • After main( ) has clean up the parameters in the program stack, the program stack is empty again !!!

    (That's what we want !!! We do not want to leave any garbage on the program stack !!!)

 

End of the comments...