Review:   function call + return
 

Function call + return expressed in high level programming language syntax:

   function f1( )               function f2( ) 
   {                   +------->{         
       ...             |            ...  |
       ...             |            ...  |
       ...       call  |            ...  |
       f2( ) ----------+            ...  |
       ...   <--------------+       ...  |
       ...                  |       ...  V 
       ...                  +------ return;
   }                             } 
   
 

We have learned how the compiler will translate (= implement) the function call + return.

Review:   function call + return
 

Function call + return in ARM assembler   -   works only if f2 is a leaf function:

 f1:                                           
                       +---->  f2:  ...
       ...             |            ...  |
       ...             |            ...  |
       ...       call  |            ...  |
       bl f2 ----------+            ...  |
       ...   <--------------+       ...  |
       ...                  |       ...  V 
       ...                  +------ mov  pc, lr
                                  
   
 

 

Review:   function call + return
 

Function call + return in ARM assembler   -   general solution (will always work):

 f1:                                           
                       +---->  f2:  push {lr}
       ...             |            ...  |
       ...             |            ...  |
       ...       call  |            ...  |
       bl f2 ----------+            ...  |
       ...   <--------------+       ...  |
       ...                  |       ...  V 
       ...                  +------ pop {pc}
                                  
   
 

 

There are 3 more things to discussed in function call + return
 

Consider a function (= method) definition in a high level programming language:

 /* ------------------------------------------------------
    sumRange(A,a,b): returns (A[a] + A[a+1] + ... + A[b-1]) 
    ------------------------------------------------------ */ 
 int sumRange( int[] A, int a, int b )           
 {
     int i, s;

     s = 0;
     for (i = a, i < b; i++)
        s = s + A[i];
     return(s);
 }
   

There are 3 things missing in the discussion

There are 3 more things to discussed in function call + return
 

(1):   a function can receive parameters:

 /* ------------------------------------------------------
    sumRange(A,a,b): returns (A[a] + A[a+1] + ... + A[b-1]) 
    ------------------------------------------------------ */ 
 int sumRange( int[] A, int a, int b )           
 {
     int i, s;

     s = 0;
     for (i = a, i < b; i++)
        s = s + A[i];
     return(s);
 }
   

Questions:   (a) how are parameters passed to a function and (2) how to access them ?

There are 3 more things to discussed in function call + return
 

(2):   a function can return a value:

 /* ------------------------------------------------------
    sumRange(A,a,b): returns (A[a] + A[a+1] + ... + A[b-1]) 
    ------------------------------------------------------ */ 
 int sumRange( int[] A, int a, int b )           
 {
     int i, s;

     s = 0;
     for (i = a, i < b; i++)
        s = s + A[i];
     return(s);
 }
   

Questions:   (a) how does a function return a value and (2) how to use the return value ?

There are 3 more things to discussed in function call + return
 

(3):   a function can have local variables (that are only accessible within the function body):

 /* ------------------------------------------------------
    sumRange(A,a,b): returns (A[a] + A[a+1] + ... + A[b-1]) 
    ------------------------------------------------------ */ 
 int sumRange( int[] A, int a, int b )           
 {
     int i, s; // Local variables 

     s = 0;
     for (i = a, i < b; i++)
        s = s + A[i];
     return(s);
 }
   

Questions:   (a) how to create local variables and (2) how to use the local variables ?

No new assembler instructions needed !

  • Good news:

    • We have learned all the necessary assembler instructions to implement:

      • Parameter passing
      • Returning a value
      • Allocating local variables

    I.e.::

    • There is NO additional assembler instructions needed to:

      • Pass parameters to functions
      • Return a function value
      • Allocate local variables for function

  • How to implement parameter passing, returning a value and allocating local variables:

    • organize (using the registers or the runtime (program) stack) !      

Prelude to the discussion - terminology: caller and callee

Terminology:

  • Caller (= calling method)

      • Caller = the method that calls another method

        The caller may pass one or more parameter(s) to a called method          


  • Callee (= called method)

      • Callee = the method that got called (by another method)

        The callee may pass a (= one) return value back to its caller    

How to pass parameters to a callee
 

How the caller passes parameters to the callee:

  • Parameter passing is implemented by an agreement (= contract) between

      1. The caller (= calling method)             and       

      2. The callee (= called method)

    on:

      1. Where (= location) to pass (= store) the value of each parameter              

      2. How (= by value or by reference) to pass each parameter:

        • Pass by value              or
        • Pass by reference

        (Note: there are other (lesser known) parameter passing methods...)

How to pass the return value to the caller
 

How the callee passes a return value to the caller:

  • Returning a value is implemented by an agreement between

      1. The calling method             and       

      2. The called method

    on:

      1. Where (= location) to pass (= store) the return value produced by the callee

Because function returns a single value:

  • The return location used by compilers is always a register

    (Usually register r0)

Places (= locations) that you can use to pass parameters, and store local variables
 

The (memory) locations used to pass parameters:

  1. Registers inside the CPU:

      • Advantage:       simple to use and understand

      • Disadvantage:   will only work with leaf functions    


  2. Program (runtime) stack in the memory:

      • Advantage:         will work with any (leaf + non-leaf) function    

      • Disadvantage:   more difficult to use and understand    

I will discuss method 1 (using registers) first...