Using the Stack Frame - ContinuedΒΆ
This more elaborate example has code for two functions, one of which calls the other.
The first function is closeEnough, which has two parameters and two int variables, thus requiring 16 bytes of space in addition to the room for lr and fp:
Address | Contents | |
---|---|---|
0xffffffe8 | diffMagnitude | (fp - 20) |
0xffffffec | diff | (fp - 16) |
0xfffffff0 | y | (fp - 12) |
0xfffffff4 | x | (fp - 8) |
0xfffffff8 | old fp (for closeEnough's caller) | (fp - 4) |
0xfffffffc | lr | fp |
0x00000000 | ... |
The abs
function only has one parameter and no local variables,
so its stack frame only requires 4 bytes beyond the lr and fp:
Address | Contents | |
---|---|---|
0xffffffdc | x | (fp - 8) |
0xffffffe0 | old fp (for abs's caller) | (fp - 4) |
0xffffffe4 | lr | fp |
0xffffffe8 | ... |
As you watch the code run, have both the disassembly and memory panes open so you can pay attention to how the fp
(r11
) is keeping track of the current stack frame and loads and stores are addressing memory relative to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | .data
a: .word 25
b: .word 26
/*
Main program sets r6 to 1 if a and b are within 1 of each other
otherwise set r6 to 0
Calls closeEnough function to help do the job
*/
.text
.global _start
_start:
@load a and b into "permanent" registers
LDR r4, =a
LDR r4, [r4]
LDR r5, =b
LDR r5, [r5]
@save any r0-r3 I need... (none)
MOV r0, r4 @load the parameters
MOV r1, r5
BL closeEnough
MOV r6, r0 @get my return value, store into r6
@restore any r0-r3... (none)
@stop program
end: B end
@exit linux style
@MOV r7, #1
@SWI 0
@----------------------------------------------------------------------
/* CloseEnough - determine if two numbers are within one of each other
Calls abs to help do the job.
bool closeEnough(int x, int y) {
int diff = x - y;
int diffMagnitude = abs(diff);
return (diffMagnitude <= 1);
}
Params:
r0 = x
r1 = y
Return:
r0 = 1 if within 1, 0 otherwise
Stack Frame:
-------------------------------
FramePointer
Relative
Address Contents
-------------------------------
-20 diffMagnitude
-16 diff
-12 y
-8 x
-4 old fp
0 my lr
*/
closeEnough:
@@@ Prologue ----------------------------------------
PUSH {fp, lr} @store my return address and previous fp
@If we were going to use r4+ would need to store
@sp now points at address 0x04 relative to frame
ADD fp, sp, #4 @set fp to point at addres 0x00 relative to frame
SUB sp, sp, #16 @Make 16 bytes space for four local variables/parameters
STR r0, [fp, #-8] @store r0 to x in stack frame
STR r1, [fp, #-12] @store r1 to y in stack frame
@@@ Body --------------------------------------------
@int diff = x - y;
LDR r0, [fp, #-8] @r0 = x
LDR r1, [fp, #-12] @r1 = y
SUB r0, r0, r1 @r0 = x - y
STR r0, [fp, #-16] @store answer to diff in stack frame
@int diffMagnitude = abs(diff);
LDR r0, [fp, #-16] @get diff into r0
@save any r0-r3 I care about...none
BL abs @get abs of difference of x and y
@answer of abs(x - y) is in r0
@restore any r0-r3 I saved...none
STR r0, [fp, #-20] @store answer to diffMagnitude in stack frame
@return (diffMagnitude <= 1);
LDR r0, [fp, #-20] @get diffMagnitude into r0
CMP r0, #1 @compare diffMagnitude with 1
MOVLE r0, #1 @set r0 to true/false based on result
MOVGT r0, #0 @ 1 if diff is <= 1; 0 if diff is > 1
@@@ Epilog --------------------------------------------
ADD sp, sp, #16 @Remove 16 bytes for local variables
POP {fp, lr} @Restore my return address and saved registers
BX lr @return
@----------------------------------------------------------------------
@----------------------------------------------------------------------
/* AbsoluteValue
Does not call another function
int abs(int x) {
if (x < 0)
x = -x;
return x;
}
Params:
r0 = number
Return:
r0 = |number|
Stack Frame:
-------------------------------
FramePointer
Relative
Address Contents
-------------------------------
-8 x
-4 old fp
0 my lr
*/
abs:
@@@ Prologue ----------------------------------------
PUSH {fp, lr} @store previous fp and our lr
@If we were going to use r4+ would need to store
ADD fp, sp, #4 @set fp to point at addres 0x00 relative to frame
SUB sp, sp, #4 @Make 4 bytes space for one local variable/param
STR r0, [fp, #-8] @store r0 to x in stack frame
@@@ Body --------------------------------------------
@if (x < 0)
LDR r0, [fp, #-8] @r0 = x
CMP r0, #0 @check against 0
BGE end_absIf @if >= 0, skip ahead
@ x = -x;
MVN r0, r0 @was negative, so negate bitwise
ADD r0, r0, #1 @add one to get 2's complement negation
STR r0, [fp, #-8] @store back to x in stack frame
end_absIf:
@@@ Epilog --------------------------------------------
LDR r0, [fp, #-8] @get x into r0
ADD sp, sp, #4 @Remove 4 bytes for local variables
POP {fp, lr} @Restore old fp and lr
BX lr @return
@----------------------------------------------------------------------
|
You have attempted of activities on this page