In the story of Hansel and Gretel, they lost the bread crumbs that point the way back home:
This analogy is also applicable in function calls because:
|
Let's write this sequence of function calls using what we just learned:
public static void main(String[] args)
{
A( );
}
public static void A( )
{
...
B( ); // Calls B( )
...
}
public static void B( )
{
... // Does not call any method/function
...
}
|
The function call code:
main:
mov r0, #1111
mov r1, #1111
bl A
mov r2, #2222
mov r3, #2222
Stop:
nop
A:
mov r0, #3333
mov r1, #3333
bl B // Overwrites lr (A's return address to main !)
mov r2, #4444
mov r3, #4444
mov pc, lr // A fails to return to main !!!
B:
mov r0, #9999
mov r1, #9999
mov pc, lr // B succeeds to return to A
|
DEMO: /home/cs255001/demo/asm/8-sub/bl+rts2.s
Why the function A( ) cannot return to main( ):
main:
mov r0, #1111
mov r1, #1111
bl A // Saves return address to main in lr
mov r2, #2222 // <--- return address used by A
mov r3, #2222
Stop:
nop
A:
mov r0, #3333
mov r1, #3333
bl B // A has lost its return address to main !
mov r2, #4444
mov r3, #4444
mov pc, lr // Therefore: A cannot return to main !!!
B:
mov r0, #9999
mov r1, #9999
mov pc, lr
|
DEMO: /home/cs255001/demo/asm/8-sub/bl+rts2.s
|
Question: which data structure should we use to save the return addresses ???
Suppose:
main( ) -----> A( ) -----> B( )
{ { {
A( ); B( ); ...
} } }
|
Return order is: Last In First Out (LIFO)
main( ) <----- A( ) <----- B( )
{ { {
A( ); B( ); ...
} } }
|
|