Download as pdf or txt
Download as pdf or txt
You are on page 1of 38

Topic 8

CALL, Subroutine, RET & Stack


Ismail Ariffin
ECE,SKE,FE,UTM,Skudai,Johor
2019
CALL Instruction
• Call is program control instruction used to jump from an
instruction of a normal program to a subroutine (assembly) or
function (high level language).
• A subroutine is a modular program having RET instruction as
the last instruction code. The RET instruction is used to exit
the subroutine and make AVR return to the normal instruction
control sequence.
• All the operations as mentioned above will correctly work in
AVR only with the existing of a special memory area called
STACK.
• STACK is enabled by setting Stack Pointer with an AVR RAM
address.
STACK
o Stack is a small section of RAM used by the CPU to temporarily
store a data or an address.
o Usually, a stack is a Last In First Out (LIFO) buffer (memory)
temporarily storing data items in consecutive manner.
o Stack area is handled by a Stack Pointer (SP). Stack Pointer (SP)
always points to the address of the last data item placed onto the
stack.
o Application of stacks:
o Temporary storage for parameters (register’s data)
o Temporary storage for program counter’s return address after
subroutine operation
STACK area
How Stack Are Accessed In The AVR
o Since the stack is a section of RAM, so it needs a register inside the
CPU to point to it (the stack) called Stack Pointer (SP) register.
o The SP is 16-bit wide and is implemented as two registers that are
SPL (the low byte of SP) and SPH (the high byte of SP).

o The SP must be wide enough to address the RAM, thus:


o AVRs > 256 bytes of memory, the SP is made of two 8-bit registers
(SPL and SPH).
o AVRs < 256 bytes, the SP is only made of SPL.
Initializing The SP
o When AVR is powered up, the SP register contains the value 0,
which is the address of R0.
o Thus, need to initialize SP so that it points to somewhere in the
internal SRAM.
o Since in AVR, the stack grows from higher memory location to
lower memory location (i.e. push onto stack, the SP decreases), so
it is common to initialize SP to any uppermost memory location.
o Different AVRs have different amounts of RAM, thus in the AVR
assembler, RAMEND represents the address of the last RAM
location.
o Thus to initialize SP to the last memory location, simply load
RAMEND into SP.
Initializing The SP
o In AVR, Stack Pointer (SP) is made up of two registers to be loaded
with RAMEND address in which,
o SPH – load with high byte of RAMEND
o SPL – load with ow byte of RAMEND
o Thus, stack initialised assembly program:

.include “m32def.inc”
LDI R16,LOW(RAMEND) Note:
RAMEND = 0x85F
OUT SPL,R16 if ATMEGA32
LDI R16,HIGH(RAMEND)
OUT SPH,R16
SP Upper Limit
o As mentioned earlier, we can define the stack anywhere in the
general purpose memory.
o In AVR, the stack can as big as its RAM.
o Note that we must not define the stack in the register memory,
nor in the I/O memory.
o So, the SP must be set to point above 0x60.
o Stack content is important as it used to store information when
we calling a subroutine.
o Stack overflow will occur when the content of the stack is exceed
the upper limit.
Stack Instructions
o The are two types of stack operations involving SP:
o PUSH – the storing of CPU information on the stack such address
from program counter
o POP – the loading of stack contents back into a CPU register.
Pushing On The Stack
o The SP always points to the top of the
stack.
o As we push data to the stack, the data
are saved where SP points to, and the SP
is decremented by one.
o Other words, SP is decremented when
data is pushed onto the stack.
o To push a register onto stack we use PUSH instruction.

o Example: to store value of R10 onto stack pointed by SP and SP is


then decremented by 1.
Popping From The Stack
o Popping the contents of the stack back
into a given register is the opposite
process of pushing.
o When POP instruction is executed, the
SP is incremented and the top location
of the stack is copied back to register.
o This is due the stack is LIFO memory.
o To retrieve a byte of data from stack we use the POP instruction.

o Example: to copy value of R10 from stack pointed by SP and the


SP is incremented by
Push & Pop Example
o Example: the example shows the stack and SP and the registers
used after the execution of each instruction.
Push & Pop Example
Push & Pop Example
Push & Pop Example
Address Code
ORG 0

0000 LDI R16,HIGH(RAMEND)

0001 OUT SPH,R16


R20: $10
$00 R22: $30
$00
LDI R16,LOW(RAMEND)
0002
R21: $00
$20 R0: $00 0003 OUT SPL,R16

0004 LDI R20,0x10

0005 LDI R21,0x20

0006 LDI R22,0x30


SP 0000 0007 PUSH $10
R20

0008 PUSH $20


R21

0009 PUSH $30


R22

000A POP R21

000B POP R0

000C POP R20

000D L1: RJMP L1

Memory
Subroutine
(Function)
Subroutine & Call
o In AVR, a software normally
comprises of a main program
and numbers of subroutines.
o Subroutine is a useful modular
program that appears many
times in a software program. A
subroutine code always ends
with a RET instruction.
o A reasonable name is given to
the subroutine.
o AVR program control operation
is conducted by Program
Counter (PC).
Subroutine
• Why use subroutines?
o Code re-use
o Easier to understand code (readability)
o Divide and conquer
 Complex tasks are easier when broken down into smaller tasks
o Simplify the code debugging process.
• How do we call a subroutine in assembly?
o Place the parameters somewhere known
o CALL instruction to jump to the subroutine
o RET instruction to return
• Examples of subroutines:
o Time Delay
o Perform output to 7-segment display
o Convert binary to ASCII
o Convert Fahrenheit to Celsius
Subroutine: Role of Stack
o Stack is used to temporarily store address when CPU execute the
CALL instruction.
o This is how the CPU know where to resume when it return from the
called subroutine.
o Hence, we must very careful when manipulating the stack contents.
o For AVRs whose program counter is not longer than 16 bits (e.g.
ATmega32), the value of the program counter is broken into 2 bytes.
o The higher byte is pushed onto the stack first, and then the lower byte
is pushed.
o For AVRs whose program counter is longer than 16 bit but shorter
than 24 bit, the value of the program counter is broken up into 3
bytes.
o The highest byte is pushed first, then the middle byte is pushed, and
finally the lowest byte is push.
CALL & Subroutine Operation
o Before Subroutine operation,
o PC is having the address of Call
instruction of normal program.
o Stack Pointer is at normal address and
Stack area is empty
o During Subroutine operation
o the AVR first saves the address of the
next instruction sequence after CALL of
the normal program onto the stack and
Stack Pointer is decremented
accordingly.
o PC get the address of subroutine and run
the subroutine.
o After Subroutine operation
o PC receives the saved address of the next
instruction sequence from STACK during
RET operation. Stack Pointer is
incremented accordingly and continue
normal program operation
Subroutine: CALL Instruction
o CALL is long call to subroutine.
o It calls to a subroutine within the entire Program memory.
o The return address (to the instruction after the CALL) will be
stored onto the Stack.

Flag affected : None


CPU cycle: 4, 5
Subroutine: RET Instruction
o CALL is return from subroutine.
o The return address is loaded from the Stack.

Flag affected : None


CPU cycle: 4, 5
Subroutine: RET Instruction
o When the execution of the
function is finishes, the RET
instruction at the end of the
subroutine is executed, the
address of the instruction below
the CALL is loaded into the PC,
and the instruction below the
CALL instruction is executed.
Subroutine: CALL Instruction
o Example:
MOV R16,R0 ;Copy r0 to r16
CALL check ;Call subroutine
NOP

check: CPI R16, $42 ;Check if r16 has a special value
BREQ error ;Branch if equal
RET ;Return from subroutine

error: RJMP error ;Infinite loop
Subroutine: RCALL Instruction
o RCALL is Relative call to subroutine.
o In which, it relatively call to an address within PC-2K+1 and PC+2K
(words).
o The return address (the instruction after RCALL) is stored on Stack.

Flag affected : None


CPU cycle: 3, 4
Subroutine: RCALL Instruction
o Not much different between CALL and RCALL. It just address CALL
can be anywhere within 4M address ($0 - $3FFFFF), while RCALL
must be within 4K range.
o Example:
RCALL routine ;Call subroutine

routine: PUSH R14 ;save r14 on the stack

POP R14 ;Restore r14
RET ;Return from subroutine
Subroutine: ICALL Instruction
o ICALL is Indirect call to subroutine.
o In which, it call to a subroutine within entire 4M (words) Program
memory that specifies by the Z register.
o The return address (to the instruction after the ICALL) is stored on
Stack.

Flag affected : None


CPU cycle: 3, 4
Subroutine: ICALL Instruction
o Example:
MOV R30, R0 ;Set offset to call table
ICALL ;Call routine pointed to by r31:r30
Time delay subroutine
Function:
To generate a software time delay required by input/ouput (I/0) devices such as
to control on-off Light Emitting Diode (LED), Seven-Segment Display and running
of DC Motor (Speed).
40 PIN DIP
(XCK/T0) PB0 1 40 PA0 (ADC0)
(T1) PB1 2 39 PA1 (ADC1)
(INT2/AIN0) PB2 3 38 PA2 (ADC2)
(OC0/AIN1) PB3 4 MEGA32 37 PA3 (ADC3)
(SS) PB4 5 36 PA4 (ADC4) RAM EEPROM Timers
(MOSI) PB5 6 35 PA5 (ADC5)
(MISO) PB6 7 34 PA6 (ADC6) PROGRAM
Flash ROM
(SCK) PB7 8 33 PA7 (ADC7)
RESET 9 32 AREF Program Data
VCC 10 31 AGND Bus Bus
GND 11 30 AVCC CPU
XTAL2 12 29 PC7 (TOSC2)
XTAL1 13 28 PC6 (TOSC1)
(RXD) PD0 14 27 PC5 (TDI)
(TXD) PD1 15 26 PC4 (TDO)
(INT0) PD2 16 25 PC3 (TMS) Other
Interrupt
(INT1) PD3 17 24 PC2 (TCK) OSC Ports
Unit Peripherals
(OC1B) PD4 18 23 PC1 (SDA)
(OC1A) PD5 19 22 PC0 (SCL)
(ICP) PD6 20 21 PD7 (OC2) I/O
PINS
Time delay subroutine using
loop (do .. while)
machine cycle*(MC) Note :
LDI R16, 50
1 Check AVR
AGAIN: NOP 1 *50 clock cycle
NOP 1 *50 from data
sheet
DEC R16 1 *50

BRNE AGAIN 1(or 2) *50 * 2 (if taken)


251

Calculate delay time in second,


If fclock = 1 MHz. Tclock = 1 us

Tdelay = Total MC x Tclock = 0.251 ms


Time delay nested loop
machine cycle
LDI R17, 20
1
L1: LDI R16, 50
1 *20
L2: NOP
1 *20 * 50
NOP 1 *20 * 50
DEC R16 1 *20 * 50
BRNE L2 1 or 2 *20 * 2 * 50
DEC R17 1 *20
BRNE L1 1 or 2 *20 * 2
5081

Calculate delay time,


Let fclock = 1 MHz. Tclock = 1 us

Tdelay = Total MC x Tclock = 5.081 ms


Call delay example
.include “m32def.inc"
.org 0
LDI R16,HIGH(RAMEND)
OUT SPH,R16
LDI R16,LOW(RAMEND)
OUT SPL,R16
LDI R16,0X55
BACK: COM R16
OUT PORTB,R16
CALL DELAY_1S
RJMP BACK
DELAY_1S: LDI R20,32 -
L1: LDI R21,110
L2: LDI R22,5 ;The modification is needed so that we the get
; an almost 1 sec delay on AVR
L3: NOP
NOP
DEC R22
BRNE L3
DEC R21
BRNE L2
DEC R20
BRNE L1
RET
Calculation of about 1 sec delay
DELAY_1S: Machine cycle
LDI R20,32 1 *1
L1: LDI R21,200 1 * 32
L2: LDI R22,5 1 * 200 * 32
L3: NOP 1 * 5 * 200 * 32
NOP 1 * 5 * 200 * 32
DEC R22 1 * 5 * 200 * 32
BRNE L3 1 or 2 * 5 * 200 * 32
DEC R21 1 * 200 * 32
BRNE L2 1 or 2 * 200 * 32
DEC R20 1 * 32
BRNE L1 1 or 2 * 32
RET ----------------------
4 185729

Calculate delay time,


Let fclock =1 MHz. Tclock = 1 us
MC = 1 + (4+ 4(120)+5(5*120))32 = 111489
Tdelay = Total MC x Tclock = 1.11 s
Subroutine Example
o Example: Write a program to count up from $00 to $FF and send the
count to Port B. Use one CALL subroutine for sending the data to Port
B and another one for time delay. Put time delay between each
issuing of data to Port B.
o Solution:
; Program Step
.include “m32def.inc”
main:
Initialise SP
Set count to 0
back: call display
repeat back
display: Send count at portB
Call delay
Increment count
return
delay: set dcount
dloop: Decrement dcount
Repeat at decrement dcount if dcount not 0
return
Subroutine Assembled Code
Subroutine Operation
---- subrutin_week8ex.asm --------------------------------------------------------
-----------
+00000000: E008 LDI R16,HIGH(RAMEND) Load
immediate
+00000001: BF0E OUT SPH,R16 Out to I/O location
+00000002: E50F LDI R16,LOW(RAMEND) Load
immediate
+00000003: BF0D OUT OUT SPL,,R16 Out to I/O location • What happen to PC, STACK and SP?
+00000004: E040 LDI COUNT,0x00 Load immediate
@00000005: BACK
+00000005: 940E0008 CALL DISPLAY Call subroutine
+00000007: CFFD RJMP BACK Relative jump
@00000008: DISPLAY
+00000008: 9543 INC COUNT Increment
+00000009: BB48 OUT PORTB,COUNT Out to I/O location
+0000000A: 940E000D CALL DELAY Call subroutine
+0000000C: 9508 RET Subroutine return
@0000000D: DELAY
+0000000D: EF0F LDI R16,0XFF Set Register
@0000000E: AGAIN
+0000000E: 0000 NOP No operation PC=0x0005 PC=0x0008 PC=0x000D PC=0x000C PC=0x0007
+0000000F: 0000 NOP No operation
+00000010: 0000 NOP No operation
+00000011: 950A DEC R16 Decrement
+00000012: F7D9 BRNE AGAIN Branch if not equal
+00000013: 9508 RET Subroutine return
Exercise
Answer the following questions with assembly program below:

Address Code
.INCLUDE "M32DEF.INC"
.ORG 0
0000 LDI R16, HIGH(RAMEND)
0001 OUT SPH, R16
0002 LDI R16, LOW(RAMEND)
0003 OUT SPL, R16
0004 LDI R16, 0x01
0005 LDI R17, 0x02
0006 LDI R18, 0x03
0007 PUSH R16
0008 PUSH R17
0009 PUSH R18
000A CALL COMPUTE
000C POP R16
000D POP R17
000E POP R18
000F EXIT: JMP EXIT
0011 COMPUTE:
0011 ADD R16,R17
0012 ADD R16,R18
0013 RET
Exercise
State the contents of the following after this code is executed right after the
instruction Exit: JMP EXIT. The uppermost memory location is 0x085F.

R16 R17 R18 SP 0x085B 0x085C 0x085D 0x085E 0x085F

You might also like