subroutines - clemson universityrlowe/cs2310/notes/ln_arm_subrouti… · subroutines three main...

40
Subroutines reasons for subroutines repeat same code, or similar code with slightly different parameters hide design decisions or design complexity partition off code likely to change provide for separate compilation provide for reuse

Upload: others

Post on 03-Apr-2020

23 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Subroutines

reasons for subroutines

− repeat same code, or similar code with slightly different parameters

− hide design decisions or design complexity

− partition off code likely to change

− provide for separate compilation

− provide for reuse

Page 2: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Subroutines

"open" subroutine = macro− resolved before assembly by textual substitution,− body of routine is placed in-line at call site with

parameter substitution

"closed" subroutine = standard notion− branch/execute/return at run time− one copy of body which accesses its formal

parameters

Page 3: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Subroutines

Three main concepts involved:

• Transferring control from calling program to a subroutine and back

• Passing parameter values to a subroutine and results back from the subroutine

• Writing subroutine code that is independent of the calling program

In addition, sometimes a subroutine must allocate space for local variables.

Page 4: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Subroutines

Transferring control from calling program to a subroutine and back

• Necessary to save the return address, then branch to the subroutine.

• This can be accomplished in ARM using the branch and link instruction bl

bl subr_name

• To transfer control back to the calling program, can use the branch and exchange instruction bx

bx lr

Alternatively, you can pop the lr register into the pc

Page 5: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Subroutines

• Placing a return address in a link register works as long as there are no nested subroutines.

• For nested subroutines, it is necessary to save the return address to the stack

• subroutine calls and returns are LIFO, and older processors typically save the return address of a caller by pushing it onto a memory stack

• older processors typically pass parameters by pushing them onto the same memory stack that holds the return addresses

Page 6: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Subroutines

Parameters:− actual parameters - values or addresses passed to

subroutine− formal parameters - parameter names appearing in

subroutine

Page 7: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

General structure of a subroutine

bl subr // call subroutine

ret_addr: add r0, r1, r2

subr: … // body of the subroutine

bx lr // return to caller

// call

// return

main:

Page 8: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

C functions

main()

{int a,b,c;

...c = sum(a,b); // a, b, c: r0, r1, r2

}

/* really dumb sum function */

int sum(int x, int y)

{return x+y;

}

What information mustcompiler/programmer keep track of?

What instructions can accomplish the return?

Page 9: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Function Call Bookkeeping

• Registers play a major role in keeping track of information for function calls

• The stack is also used (more on this later)

Page 10: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage

r8

r9/sb

r10/sl

r11

r12

r13/sp

r14/lr

r15/pc

r0

r1

r2

r3

r4

r5

r6

r7Temporary register variables. Must be preserved

Arguments into function;Result(s) from function;otherwise corruptible(Additional parameters passed on stack)

Stack PointerLink Register

Program Counter

Register

- Stack base

- Stack limit if software stack checking selected

- R14 can be used as a temporary once value stacked- SP should always be 8-byte (2 word) aligned

Page 11: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage

Temporary Variables

• Functions should first try to use registers r0 - r3 for any required temporary variables, since they do not have to be preserved

• Registers r4 - r11 are the second choice, but they must be saved at function entry and restored prior to the function return

• When more space for temporaries is required, allocate space on the stack.

Page 12: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage

Reasons for using registers or stack space for temporary variables instead of creating fixed locations with labels:

1. Memory conservation: the stack space will be released when the function returns so that it can be reused for other needs

2. Reentrancy: every entry of the function allocates a unique set of memory locations for its temporary variables; therefore, if the function is interrupted, and the interrupting code calls (or reenters) the same function, it is ensured that each invocation will modify only its own set of temporary

Page 13: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage: Preserving Registers

• Functions that modify registers r4 - r11 are required to preserve and restore their original content.

• The best way to preserve and restore the registers is to push the registers onto the stack immediately upon entering the function, and to pop them back just before the function returns.

• However, since the stack is stored in memory, and since memory cycles are the primary performance bottleneck, it is important to preserve as few registers as possible.

Page 14: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage: Preserving Registers

• For nested function calls, e.g function A calls function B, the call to function B will overwrite the current return address in lr; thus, function A must push the content of lr at its entry and pop it back just before it returns. In this case, the function can pop lr into the pc, thus eliminating the bx lr instruction.

Page 15: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage: Preserving Registers

Function f1 modifies only registers r0 – r3, and does not

call any other functions. Does f1 need to preserve any

registers? If so, which ones? How does the function

return to the caller?

f1:

bx lr

Page 16: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage: Preserving Registers

Function f2 does not call any functions; it modifies one or

more registers other than r0 – r3; their original content must

be preserved.

f2:

push {r4, … }

pop {r4, …}

bx lr

Page 17: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage: Preserving Registers

Function f3 contains a call to a second function, f4. The bl instruction

used to call f4 modifies lr, which contains f3's return address, so we

must preserve lr on the stack. That value is then pop'd into the PC to

cause a return. Also, since f4 may modify r0 – r3,

f3's parameters should be moved to r4 – r7 for use, r4 – r11 should be used for any temporary variables, and if f3 uses any of r4 – r11, then they should be preserved on entry

to f3 and restored just prior to return.

f3:

push {r4, …, lr }

mov r4, r0 // preserve parameter in r4

bl f4 // may modify r0 - r3

pop {r4, …, pc}

Page 18: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Usage

• The compiler has a set of rules known as a Procedure Call Standard that determines how to pass parameters to a function (see AAPCS)

• CPSR flags may be corrupted by function calls. Assembler code which links with compiled code must follow the AAPCS at external interfaces

• The AAPCS is part of the new Application Binary Interface (ABI) for the ARM Architecture

Page 19: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Register Conventions

• CalleR: the calling function

• CalleE: the function being called

• When callee returns from executing, the caller needs to know which registers may have changed and which are guaranteed to be unchanged.

• Register Conventions: A set of generally accepted rules as to which registers will be unchanged after a procedure call (bl) and which may be changed.

• caller/callee need to save only volatile/saved registers they are using, not all registers.

Page 20: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Saved Register Conventions

• r4-r11 (v1-v8): Restore if you change. Very important. If the callee changes these in any way, it must restore the original values before returning.

• sp: Restore if you change. The stack pointer must point to the same place before and after the bl call, or else the caller will not be able to restore values from the stack.

Page 21: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Volatile Register Conventions

• lr: Can Change. The bx call itself will change this register. Caller needs to save on stack if nested call.

• r0-r3 (a1-a4): Can change. These are volatile argument registers. Caller needs to save if they’ll need them after the call. e.g., r0 will change if there is a return value

• r12 (ip) may be used by a linker as a scratch register between a routine and any subroutine it calls. It can also be used within a routine to hold intermediate values between subroutine calls.

Page 22: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Instruction Support for Functions

bx - performs a branch by copying the contents of a general register, Rn, into the program counter, PC. The branch causes a pipeline flush and refill from the address specified by Rn.

• Instead of providing a label to jump to, the BX instruction provides a register which contains an address to jump to

• Only useful if we know the exact address to jump

• Very useful for function calls:

– bl stores return address in register (lr)

– bx lr jumps back to that address

Page 23: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Example:

main()

{

...

sum(a,b); // a,b:r4,r5

... }

int sum(int x, int y) {

return x + y;}

address1000 mov r0, r4 // x = a1004 mov r1, r5 // y = b 1008 bl sum // lr = 1012 branch to sum1012 ...

2000 sum: add r0, r0, r12004 bx lr // mov pc, lr i.e., return

Note: returns to address 1012

C

ARM

Page 24: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

C functions

.text.global main.type main, %function

main:push {lr}mov r0, #37 // put x in r0mov r1, #55 // put y in r1

bl sum

. . .

mov r0, #0pop {pc}

.global sum

.type main, %function

sum:

push {lr}

add r0, r0, r1

pop {pc}

Page 25: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Nested Procedures

int sumSquare(int x, int y)

{return mult(x,x)+ y;

}

• Some subroutine called sumSquare, and now sumSquareis calling mult.

• There’s a value in lr that sumSquare wants to jump back to, but this will be overwritten by the call to mult.

• Need to save sumSquare’s return address before the call to mult.

Page 26: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Nested Procedures

• In general, it may be necessary to save some other info in addition to lr.

• When a C program is run, there are 3 important memory areas allocated:

– Static: Variables declared once per program, cease to exist only after execution completes. e.g., C globals

– Heap: Variables declared dynamically

– Stack: Space to be used by subroutines during execution; this is where we can save register values

Page 27: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Using the Stack

• We have a register sp which always points to the last used space in the stack.

• To use the stack, we decrement this pointer by the amount of space we need and then fill it with info.

• Consider the following C function:

int sumSquare(int x, int y)

{return mult(x, x) + y;

}

Page 28: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Using the Stack

sumSquare: add sp,sp,#-8 // space on stackstr lr, [sp,#4] // save ret addrstr r1, [sp] // save y

mov r1, r0 // mult(x,x)bl mult // call mult

ldr r1, [sp] // restore y

add r0,r0,r1 // mult()+yldr lr, [sp, #4] // get ret addradd sp, sp, #8 // restore stack

bx lrmult: ...

int sumSquare(int x, int y) {

return mult(x, x)+ y; }

"push"

"pop"

Page 29: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

C functions

x86 example of swap routine in C

void main() { main:

void swap(); pushl %ebp ! save old bp

int a,b; movl %esp,%ebp ! set new bp as ! current sp

a = 5; b = 44; subl $8,%esp ! sub for a and b

swap(&a,&b); movl $5,-4(%ebp) ! initialize a

} movl $44,-8(%ebp) ! initialize b

leal -8(%ebp),%eax ! form addr of b

pushl %eax ! push onto stack

leal -4(%ebp),%eax ! form addr of a

pushl %eax ! push onto stack

call swap ! call

addl $8,%esp ! clean parms off ! stack

leave

ret

Page 30: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

C functions

x86 example output for swap routine in C (sp called esp, fp called ebp)

void swap(x,y) swap:

int *x,*y; pushl %ebp ! save old bp

{ movl %esp,%ebp ! set new bp as current sp

int temp; subl $4,%esp ! sub for temp

temp = *x; movl 8(%ebp),%eax ! move addr x into eax

*x = *y; movl (%eax),%edx ! indirectly get value in a

*y = temp; movl %edx,-4(%ebp) ! store into temp

return; movl 8(%ebp),%eax ! move addr x into eax

} movl 12(%ebp),%edx ! move addr y into edx

movl (%edx),%ecx ! indirectly get value in b

movl %ecx,(%eax) ! store indirectly into a

movl 12(%ebp),%eax ! move addr y into eax

movl -4(%ebp),%edx ! move temp into edx

movl %edx,(%eax) ! store indirectly into b

leave

ret

Page 31: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

C functions

ARM code for swap()

void swap(int *x, int *y)

{ swap: // addr of x is in r0

int temp; // addr of y is in r1

temp = *x; push {lr} // save return address

*x = *y; ldr r2, [r0] // move x into r2

*y = temp; ldr r3, [r1] // move y into r3

return; str r3, [r0] // store indirectly into x

} str r2, [r1] // store into y

mov r0, #0

pop {pc}

Page 32: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Basic Generic Structure of a Function

entry_label: add sp,sp, -framesizestr lr, [sp, #framesize-4] // save lr

// save other regs if necessary

...

restore other regs if necessaryldr lr, [sp, framesize-4] // restore lradd sp,sp, #framesizebx lr

Epilogue

Prologue

Body (call other functions…)

Page 33: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Basic Structure of a Subroutine in ARM

entry_label: push {// registers necessary registers, including lr}

add sp,sp, -framesize // if space needed for temp vars

...

pop { // registers that were pushed}add sp, sp, #framesizebx lr // alternatively, if lr was pushed, can pop lr into pc

Epilogue

Prologue

Body (call other functions…)

Page 34: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Example

main() {int x, y; /* x: r0, y: r1 */...m = mult(y,y);

...

}

int mult (int multiplicand, int multiplier)

{int product;

product = 0;while (multiplier > 0)

{product += multiplicand;multiplier -= 1;

}return product;

}

Page 35: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Example.global main

.type main, %function

x .req r4 // rename register r4

y .req r5 // rename register r5

prod .req r3 // rename register r3

main:

push {r4, r5, lr} // save registers

mov x, #7 // put x in r4

mov y, #5 // put y in r5

/* set up registers for call to mult */

mov r0, x

mov r1, y

bl mult // call mult

mov r3,r0 // m = mult(x, y)

done:

mov r0, #0

pop {r4, r5, pc}

Page 36: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Example.global mult

.type mult, %function

mult:push {lr}product .req r2multiplicand .req r0multiplier .req r1

mov product, #0cmp multiplier, #0ble finished

loop:add product, product, multiplicandsub multiplier, multiplier, #1cmp multiplier, #0bgt loop

finished:mov r0, productpop {pc}

Page 37: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Techniques for passing parameters in ARM

In ARM, parameters can be passed to subroutines in three ways:

• Through registers

• Through memory

• Via the stack

Page 38: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Passing Parameters in registers

• This is what we have done so far

• Fast way of transferring data

Page 39: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Passing Parameters by Reference

• Parameters can easily be stored in program memory and then loaded as they are used

• Send the address of the data to the subroutine

• More efficient in terms of register usage for some types of data, e.g. a long string of characters or an array of int values

Page 40: Subroutines - Clemson Universityrlowe/cs2310/notes/ln_arm_subrouti… · Subroutines Three main concepts involved: • Transferring control from calling program to a subroutine and

Passing Parameters on the stack

• Similar to passing parameters in memory

• The subroutine uses a dedicated register for a pointer into memory – the stack pointer, register r13.

• Data is pushed onto the stack before the subroutine call

• The subroutine gets the data off the stack.

• The results are then stored back onto the stack to be retrieved by the calling routine.