|
In this webpage, I want to show you the effect of these sequence of instructions and their effect on the program stack with 3 examples
main( ) { Calls a function A and passes 2 parameters to A. In Java, this would be written as: A(1111,2222) } A( int a, int b ) { A( ) has 3 local variables. In Java, you would write: int x, y, z; // Define 3 local vars return(9999); // A( ) always returns 9999 } |
I will only show you how the parameters and local variables are stored in the program stack
The assembler code is as follows:
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 /* ==================================================== 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 |
I will show this example in class and also highlight the effect of the instructions
What you should notice is:
|
How to run the program:
|
main( ) { A(1111,2222) } A( int a, int b ) { int x, y, z; // Define 3 local vars B(3333,4444,5555); return(9999); } B( int a, int b, int c ) { int x, y; // Define 2 local vars return(8888); } |
I will only show you how the parameters and local variables are stored in the program stack
The assembler code is as follows:
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 |
I will show this example in class and also highlight the effect of the instructions
What you should notice is:
|
How to run the program:
|
Then you can easily understand that you access the parameters and local variables with these offsets:
localVar1 = param1; localVar2 = param2; localVar3 = param1 + param2; |
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 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 pop {fp} pop {pc} // Return |
How to run the program:
|