High-level Language Programmer's View
main: | CalculatePowers(In: integer numLimit, integer powerLimit) |
integer Power( In: integer n, integer e) |
maxNum = 3 | integer result | |
maxPower = 4 | integer num, pow | if e = 0 then |
  |   | result = 1 |
CalculatePowers(maxNum, maxPower) | for num := 1 to numLimit do | else if e = 1 then |
(*) | for pow := 1 to powerLimit do | result = n |
. . . | else | |
end main | print num " raised to " pow " power is " | result = Power(n, e - 1)* n |
  | Power(num, pow) | end if |
  | end for pow | return result |
  | end for num | end Power |
  |   |   |
  | end CalculatePowers |   |
Compiler uses registers to avoid accessing memory as much as possible. Registers can be used for local variables, parameters, return address, function return value.
When subprogram is called, some of the register values might need to be saves ("spilled") on the stack to free up some registers for subprogram to use.
Standard conventions for spilling registers:
1) caller save - before the call, caller saves the register values it needs after the subprogram
2) callee save - subprogram saves and restores any register it uses in its code
3) some combination of caller and callee saved AL code for subprogram "caller"
<code using some registers
call subprogram
<want used registers to be unchanged>
Reg. # |
APCS Name |
APCS Role |   |
R0 | a1 | Argument 1/integer result/scratch register | Caller-saved registers - subprogram can use them as scratch registers, but it must also save any needed values before calling another subprogram. |
R1 | a2 | Argument 2/scratch register | |
R2 | a3 | Argument 3/scratch register | |
R3 | a4 | Argument 4/scratch register | |
R4 | v1 | Register variable 1 | Callee-saved registers - subprogram must save them if it wishes to use these registers, but it can rely on an subprogram it calls not to change them. |
R5 | v2 | Register variable 2 | |
R6 | v3 | Register variable 3 | |
R7 | v4 | Register variable 4 | |
R8 | v5 | Register variable 5 | |
R9 | v6/sb | Register variable 6 | Reentrant code is position-independent and addresses all data indirectly through the static base (sb) register |
R10 | v7/sl | Register variable 7 | Stack limit register used to check for stack overflow |
R11 | fp | Frame pointer |   |
R12 | ip | Scratch register / new static base in inter-link-unit calls |   |
R13 | sp | stack pointer | Points to lower end of current call-frame |
R14 | lr | link register/scratch register | Receives return addr. on BL call to subprogram |
R15 | pc | program counter | Points to next instruction to execute |
1) For the Power function, which value(s) are needed after the (recursive) function call?
2) Write the assembly language code for the Power function.
EXTERN CalculatePowers AREA MAIN, CODE, READONLY ENTRY ; mark the first instruction to call MOV a1, #3 ; maxNum MOV a2, #4 ; maxPower BL CalculatePowers SWI 0x11 ; terminate END |
EXTERN Power AREA CalcPowers_subpgm, CODE, READONLY ; r4/v1 is numLimit ; r5/v2 is powerLimit ; r6/v3 is num ; r7/v4 is pow ; r0/a1 is result CalculatePowers STMFD sp!, {v1-v4, lr} MOV v1, a1 MOV v2, a2 MOV v3, #1 FOR_1 CMP v3, v1 BGT END_FOR_1 MOV v4, #1 FOR_2 CMP v4, v2 BGT END_FOR_2 MOV a1, v3 MOV a2, v4 BL Power ADD v4, v4, #1 B FOR_2 END_FOR_2 ADD v3, v3, #1 B FOR_1 END_FOR_1 LDMFD sp!, {v1-v4, pc} B FOR_1 END_FOR_1 EXPORT CalculatePowers END |
|