AVR Stack and Subroutine Calls - PowerPoint PPT Presentation

1 / 57
About This Presentation
Title:

AVR Stack and Subroutine Calls

Description:

The stack is an area of SRAM that grows downward from a fixed reference point ... the stack into PC effectively resuming execution at the statement following the ... – PowerPoint PPT presentation

Number of Views:565
Avg rating:3.0/5.0
Slides: 58
Provided by: timma87
Category:

less

Transcript and Presenter's Notes

Title: AVR Stack and Subroutine Calls


1
AVR Stack and Subroutine Calls
  • Assembly Language Programming
  • University of Akron
  • Dr. Tim Margush

2
Stack
  • The stack is an area of SRAM that grows downward
    from a fixed reference point
  • Special instructions and I/O register support
    stack access
  • RET, CALL, PUSH, POP,
  • SP (Stack Pointer)
  • The stack requires initialization
  • Set SP to an appropriate address (empty stack)
  • The stack is managed by application and is used
    by the processor interrupt system

3
Stack Initialization
  • Typically, the stack starts at the highest SRAM
    address and grows downward through memory
  • SP points to the next available byte of stack
    storage (top of stack after a push)
  • ldi R16, high(RAMEND)
  • out SPH, R16
  • ldi R16, low(RAMEND)
  • out SPL, R16

4
PUSH and POP
  • push Rr
  • Register data copied to byte at address in SP
  • SP is decremented
  • pop Rd
  • SP is incremented
  • Byte at address in SP is copied to Rd

5
PUSH
push R5
A2
SP45D
Top of stack
6
PUSH
push R5
SP--
SP45D
SP45C
Top of stack
7
POP
pop R4
SP
SP45C
SP45D
Top of stack
8
POP
pop R4
SP45D
A2
Top of stack
9
Stack Usage
  • Temporary storage of information
  • Storage of return addresses for procedure calls
    and interrupts
  • Storage for local variables during execution of a
    procedure

10
Temporary Storage
  • push R16 save register
  • ldi R16, FF use register
  • out PORTB, R16
  • pop R16 restore register

11
Procedure Call
  • Syntax rcall label (relative call)
  • This instruction pushes a return address onto the
    stack, then executes a jump to the indicated
    address
  • The return address is pushed low byte first
  • The procedure should use RET to return to the
    statement following the call

12
Return
  • Syntax ret
  • This pops bytes from the stack into PC
    effectively resuming execution at the statement
    following the call that pushed the bytes onto the
    stack

13
PC-Relative Addressing
  • The rcall instruction (along with some others)
    uses PC-relative addressing mode
  • rjmp k (-2048 lt k lt 2047)
  • This range indicates a 12-bit two's complement
    code is used for k which is encoded in the
    instruction
  • Opcode 1101 kkkk kkkk kkkk
  • The assembler calculates k from the destination
    address using the current PC value as a reference
  • rjmp destlabel
  • k destlabel PC 1

14
PC-Relative Example
  • 03C rcall sub
  • 03D ldi r16, 0
  • 06F sub out A, r16
  • 067
  • 08E ret
  • Displacement is calculated by assembler
  • PC is 3C
  • k 6F-3C-1
  • So k 32
  • 1101 0000 0011 0010

15
PC-Relative Example
  • 024 adder adi r16, FF
  • 025 adc r10
  • 02F ret
  • 0AF push r10
  • 0B0 rcall adder
  • 0B1 pop r10
  • Displacement is calculated by assembler
  • PC is B0
  • k 24-B0-1
  • So k F73 (-141)
  • 1101 1111 0111 0011

16
Why PC-Relative?
Saves space, executes faster
  • The AVR uses PC-relative because the displacement
    fits in a 16-bit instruction
  • If direct addressing is used, a second word would
    need to hold the address
  • The AVR call instruction uses direct addressing
  • call label (long call)
  • 1001 010k kkkk 111k kkkk kkkk kkkk kkkk
  • Supports 22-bit addresses (8MB memory)
  • The ATMega16 has only 16KB, max address is 1FFF
    (13 bits), and PC-Relative addressing can access
    ½ of its program space

17
Why PC-Relative?
  • Many operating systems allow program relocation
  • The program may be placed in a different memory
    area each time it is executed
  • This creates problems when programs use direct
    addressing
  • The loader will need to adjust addresses in the
    program at load time
  • PC-relative addresses however, do not have to be
    modified

18
Indirect Call
  • The AVR processor also supports a call
    instruction that uses indirect addressing
  • Syntax icall (indirect call)
  • The address of the procedure must be preset in Z
  • This can only access procedures in the first
    128KB of program memory
  • Not a problem for the ATMega16!

19
Warning
  • add word procedure
  • addit
  • add r17, r15
  • adc r16, r14
  • subtract word procedure
  • subbit
  • sub r17, r15
  • sbc r16, r14
  • ret
  • Do not forget the RET
  • If you do forget, the processor will likely fall
    through into another part of your program (or
    even into a data area of the code segment) with
    potentially disastrous results!

Missing RET?
20
Procedures
  • Use procedures to organize code into logical
    groups of statements
  • Abstraction a good design technique
  • Use procedures to reduce duplicate code
  • Call the procedure instead of duplicating the
    same sequence of steps
  • Use procedures to create reusable code
  • Place useful procedures in include files for easy
    reuse in other programs

21
Arguments and Parameters
  • Assembly language usually does not support
    arguments and parameters as part of the procedure
    call-return mechanism
  • The programmer is left to decide how
    communication between procedures will be
    implemented
  • Many techniques are possible

22
Call By ?
  • Call by value
  • The caller copies the value of the argument into
    storage made available to the function
    (parameter)
  • Function has no access to original argument
  • Call by reference
  • The caller copies the address of the argument
    into storage made available to the function
    (parameter)
  • Function can directly modify the argument via the
    pointer

23
Call By ?
argument
.dsegb .byte 1
Call by reference
Call by value
  • //f1(b)
  • lds r16, b
  • call f1
  • //void f1(int a)
  • f1
  • out PORTB, r16
  • //f2(b)
  • ldi XH, high(b)
  • ldi XL, low(b)
  • call f2
  • //void f2(int a)
  • ld R23, X
  • inc R23
  • st X, R23

Address of argument
argument copied into register
Indirect addressing provides R/W access to
argument
function accesses parameter
24
Register Parameters
  • The procedure assumes specific data will already
    be in certain registers when it is called
  • The caller is responsible for setting up the
    registers with the arguments
  • The procedure may use parameter names to refer to
    the registers

25
procedure ledOut(a)
  • ledOut
  • a (R16) is byte to be displayed
  • on LEDs (PORTB)
  • .def aR16
  • com a
  • out PORTB, a
  • com a
  • ret
  • .undef a

The argument will be loaded into R16 before the
procedure is called ledOut uses the parameter
name a to refer to the argument The parameter is
undefined at the end of the procedure so it is
not inadvertently used elsewhere in the program
(scopes a to this procedure)
26
procedure ledOut(a)
  • ledOut
  • a (R16) is byte to be displayed
  • on LEDs (PORTB)
  • .def aR16
  • com a
  • out PORTB, a
  • com a
  • ret
  • .undef a

Illustrate passing an argument to a procedure
using a register high-level call ledOut
(AA) ldi R16, AA setup argument rcall ledOut
27
Ad/Disad - vantages
  • Arguments will be in registers for immediate
    access by procedure
  • Simple, fast, and effective, especially for
    byte-sized arguments
  • The specific register used for the parameter may
    be in use by the caller, requiring data shuffling
  • Too many parameters will tie up too many
    registers
  • Argument may not fit in a register

28
Alternatives?
  • Put the arguments in RAM where?
  • On the stack
  • At an agreed upon address
  • At an address specified in a register
  • Just use global variables
  • In some cases, the arguments are placed inline
    with the program
  • Perhaps immediately after the call statement?
  • This technique requires some return address
    adjustment to prevent a disaster

29
Stack Parameters
  • The caller pushes arguments before the call

outChar('a',2) ldi R16, 2 push R16 ldi R16,
'a' push R16 rcall outChar
02
SP45E
Arguments must be pushed on stack before call
Top before call
30
Stack Parameters
  • The caller pushes arguments before the call

outChar('a',2) ldi R16, 2 push R16 ldi R16,
'a' push R16 rcall outChar
SP45D
61
Argument 1 now on top
Push argument 2
31
Stack Parameters
  • The caller pushes arguments before the call

outChar('a',2) ldi R16, 2 push R16 ldi R16,
'a' push R16 rcall outChar
SP45C
Arguments now on stack
063C
Execute rcall
32
Stack Parameters
  • The return address is on the top of stack when
    the procedure begins

outChar('a',2) ldi R16, 2 push R16 ldi R16,
'a' push R16 rcall outChar
SP45A
Return address now on top of the stack Procedure
starts execution
outChar(char x, int n) outChar
33
Stack Parameters
  • The stack pointer (SP) is a reference point to
    access the arguments

outChar(char x, int n) outChar pointer to
stack frame in YH, SPH in YL, SPL access
arguments ldd R0, Y4 ldd R1, Y3
SP45A
3
4
x is at SP3 n is at SP4
34
Stack Parameters
  • After return, the caller needs to remove the
    parameters from the stack

outChar('a',2) rcall outChar remove
parameters pop r16 pop r16
outChar ret
35
Auto Parameter Removal
  • What we just did
  • The caller allocates parameters on the stack
  • The caller removes parameters from the stack
  • What we can do
  • Let the function remove the parameters before
    returning
  • This eliminates duplicate removal code if there
    are calls at many locations

36
Stack Cleanup Code
Y45A
  • Copy return address into Z
  • Add stack frame size to Y
  • Copy Y to SP
  • Use IJMP to cause return
  • ldd ZH,Y1
  • ldd ZL,Y2
  • adiw Y,4
  • out SPH,YH
  • out SPL,YL
  • ijmp

Z063C
37
Inline Parameters
  • plus(2987,9873,sum)
  • rcall plus
  • parameter frame
  • .dw 2987
  • .dw 9873
  • .dw sum address
  • we need to return here!
  • nop or other instruction
  • In this call, the parameters are stored inline
    with the program, immediately after the call
  • If this was read/write storage, the code before
    the call could store different info into this
    memory allowing the arguments to change on each
    call

38
Inline Parameters
  • When the function starts, the return address is
    on the top of the stack. This is the address of
    the parameters!
  • Establish pointer to parameters
  • Convert to byte addresses
  • void plus(int, int, int)
  • plus
  • pop ZH pop return addr
  • pop ZL
  • lsl ZL convert to byte
  • rol ZH address
  • Z now points to params in program memory

rcall
2987
9873
60
nop
39
Inline Parameters
  • Z is used to copy parameters into registers
  • The addition is completed in R25R24 using R26 as
    a temporary register
  • load params to registers
  • lpm R24, Z
  • lpm R25, Z
  • lpm R26, Zadd R24, R26
  • lpm R26, Z
  • adc R25, R26 sum done
  • Z now points to address of sum

rcall
2987
9873
60
nop
40
Inline Parameters
  • The last parameter (address where result will be
    stored) is brought into X
  • Indirect addressing allows the result to be
    stored in sram.
  • Z now points to the return location!
  • store result
  • lpm XL, Z
  • lpm XH, Z
  • st X, R24
  • st X, R25task complete
  • Z now points to return loc

rcall
2987
9873
60
nop
41
Inline Parameters
  • The indirect jump works well to complete the
    return.
  • The return address must be converted back to a
    word address before using ijmp
  • Work registers could have been saved and restored
    easily inside the function
  • return using ijmp
  • lsr ZH word address
  • ror ZL
  • ijmp
  • Execution resumes at nop

rcall
2987
9873
60
nop
42
Procedure Etiquette
  • Procedures should not change registers unless it
    is an intended effect of the procedure
  • The stack is a convenient temporary storage area
    for registers needed by a procedure to carry out
    its task
  • Procedures usually start with a bunch of pushes
    (to save registers) and end with corresponding
    pops (to restore registers)

43
Complications
  • The use of the stack for arguments, parameters,
    the return address, temporary storage, and (not
    yet mentioned) local variables, really gets
    complicated
  • For greatest flexibility, a second stack may be
    created in RAM to support procedure data needs

44
Data Stack
  • Uses Y as stack pointer
  • Y points to top item (if present)
  • Uses indirect addressing with pre-decrement for
    push and post-increment for pop
  • Occupies another part of SRAM
  • Used for arguments and local storage

45
Data Stack Initialization
.equ HSTACK_SIZE 64 ldi YH, high(RAMEND-HSTACK_S
IZE1) ldi YL, low(RAMEND-HSTACK_SIZE1)
  • Data stack willlive just below the hardware
    stack
  • Set Y to point to the last byte of the hardware
    stack
  • A constant should be used to set the intended
    size of the hardware stack
  • Y will be decremented before storing the first
    item into the stack

46
Data Stack Push
  • Push requires decrementing Y and storing a
    register via indirect addressing
  • Think dpush Rn
  • Write st Y, Rn
  • Later we will learn how to create a macro to do
    this

47
Data Stack Pop
  • Copy the top of stack value to a register and
    increment Y
  • Think dpop Rd
  • Write ld Rd, Y
  • The built-in pre-decrement and post-increment
    work well when Y points to the top item, unlike
    the hardware stack which uses post-decrement and
    pre-increment (not available to the user) of SP
    (SP points to the byte below the top item)

48
Macro
  • A Macro is an assembly feature that allows the
    programmer to define new instructions
  • A macro invocation stands for a sequence of
    assembly language instructions
  • We want a new dpush and dpop instruction

.macro dpush st Y, _at_0 .endm
Macros have names and may use parameters (_at_0, _at_1,
etc)
49
Using a Macro
  • Invocation dpush R7
  • _at_0 is R7
  • Expansion is simply
  • st Y, R7
  • The argument is substituted for the formal
    parameter
  • Macro definitions must appear before they are
    used
  • An include file is a good choice for macros

50
Local Storage
  • Additional space in the data stack is reserved
    for local variables by subtracting the space
    required from Y
  • If a function has a byte and a word of local
    storage, we need 3 bytes
  • sbiw YHYL, 3
  • Y now points at the last of these bytes, Each may
    be accessed using indirect addressing with
    displacement
  • ldd R4, Y1 the second byte of the 3 byte area

51
Function Call
  • Caller push arguments onto data stack
  • Remember how many bytes this is for later (j)
  • Function is called
  • Return address placed on hardware stack
  • Function allocates local storage
  • Subtract k from Y (k bytes needed)
  • Function executes
  • Uses hardware stack to save and restore registers
  • Function adds kj to Y
  • The number j is the size of the argument list
  • Function returns to caller
  • Removes return address from hardware stack

52
Example Fibonacci
  • The Fibonacci numbers are fun to compute
  • fibo(0) fibo(1) 1
  • For ngt1 fibo(n) fibo(n-1) fibo(n-2)
  • We will write a function that illustrates the use
    of the data stack for arguments and local storage
  • Strictly speaking, we could do all this with just
    registers don't laugh at the inefficiency of the
    example

53
Function Fibo
  • int fibo(char n)
  • if (nlt1) return 1
  • int a fibo(n-1)
  • int b fibo(n-2)
  • return ab
  • sample call
  • int f fibo(5)
  • The stack frame will include a byte for n, and
    two words for a and b
  • Total of 5 bytes
  • The byte for n is allocated when the caller
    pushes the argument on the stack

54
Calling Sequence
  • .dseg
  • f .byte 2 storage for f
  • .cseg
  • ldi r16, 5 literal argument
  • dpush r16
  • rcall fibo return value in R25R24
  • sts f1, r25 high byte of result
  • sts f, r24 low byte of result

55
Function Fibo
  • fibo
  • sbiw YHYL,4 local storage
  • define offsets to
  • locals and
  • name registers used
  • .equ fibo_a0
  • .equ fibo_b2
  • .equ fibo_n4
  • .def retH r25
  • .def retL r24
  • .def temp r16
  • push temp
  • if (nlt2)
  • ldd temp,Yfibo_n
  • cpi temp, 2
  • brlo fibo_return_1
  • int a fibo(n-1)
  • dec temp
  • dpush temp
  • rcall fibo
  • std Yfibo_a, retL
  • std Yfibo_a1, retH

56
Function Fibo
  • int b fibo(n-2)
  • dec temp
  • dpush temp
  • rcall fibo
  • std Yfibo_b, retL
  • std Yfibo_b1, retH
  • return ab
  • ldd retL, Yfibo_a
  • ldd retH, Yfibo_a1
  • ldd temp, Yfibo_b
  • add retL, temp
  • ldd temp, Yfibo_b1
  • adc retH, temp
  • rjmp fibo_exit
  • fibo_return_1
  • ldi retL, 1
  • ldi retH, 0

57
Function Fibo
  • fibo_exit
  • pop temp
  • adiw YHYL,41
  • ret
  • .undef retH
  • .undef retL
  • .undef temp
  • The exit section restores temporary registers
    from hardware stack then releases local storage
    and the argument space from the data stack before
    returning
Write a Comment
User Comments (0)
About PowerShow.com