lecture_5 introduction to assembly language programminglec5
TRANSCRIPT
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
1/25
Lecture 5
Introduction to Assembly
Language Programming
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
2/25
Assembly vs. High Level Language
Assembly is a low-level language. It is different fromother high-level languages.
High level languages are abstract. A single high levelinstruction is translated into several machine language
instructions. Over time the level of abstraction of high-level language
is increasing.
Assembly is harder to program than high levellanguages.
Assembly Language program can be 20 times fasterthan high level program.
Assembly gives direct access to hardware features.
Faster development time for high level programs.
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
3/25
Assembly vs. High Level Language
Unsigned int outdata=0;
For (outdata=0;outdata
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
4/25
Simplest program possible
main: ;this is the label main
rjmp main ;Relative Jump to main
Main is used a label.
This label replaces an address in FLASH.
rjmp main is places at exactly this address.
Upon execution CPU will jump to main.
Jump will be repeated over and over, resulting inan infinite loop.
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
5/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
6/25
Flashing LED program
We want to make an LED flash. LED will show active low behaviour After reset, all Data bits are set to zero, so the LED
should be ON when the program is executed
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
7/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
8/25
Flashing LED program
Basically we want to switch LED on and off in a loop.
We use cbi (clear bit in I/O) and sbi (set bit in I/O).
We will see LED being on all the time. I cycle for LED off then 1 cycle(0.00000025) later it is on again. Rjmp takes 2 cycles (0.0000005).
We naturally need delay.
.org 0x0000
rjmp main
main:
ldi r16, 0xFF
out DDRB, r16
loop:sbi PortB, 3
cbi PortB, 3
rjmp loop
; the next instruction has to be written to address 0x0000
; the reset vector: jump to "main"
;
; this is the label "main"
; load register 16 with 0xFF (all bits are 1)
; write the value in r16 (0xFF) to Data Direction Register B
;; switch off the LED
; switch it on
; jump to loop
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
9/25
Flashing LED program
For 0.5s delay at 4MHz equals 2,000,000 cycles.
An 8-bit register can only hold values 0 to 255 soit wont be enough. Registers can be used inpairs so we can work on values from 0 to 65535.
clr r24
clr r25
delay_loop:
adiw r24, 1
brne delay_loop
; clear register 24
; clear register 25
; the loop label
; "add immediate to word": r24:r25 are incremented
; if no overflow ("branch if not equal"), go back to "delay_loop"
4(2adiw+2brne)*0xFFFF(looping) +3(overflow 2adiw+1brne) + 2(clr) = 262145cycles. This is still not enough:
2,000,000/262,145 ~ 7.63.
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
10/25
Flashing LED program We will create a loop around the inner loop.
We change clr to ldi so that we can use different start value than 0.
The outer loop will down-count from 8 to 0.
The overall loop needs: 262,145 (inner loop) + 1 (dec) + 2 (brne) = 262148 *8 = 2097184 cycles plus the initial ldi = 2097185 minus one since last brnedidnt result in a branch. This is 97184 cycles too long. We will fine-tune with
initial value in r24:r25. Subtract : 97184 / 8 =12148 cycles per inner loop. Inner loop takes 4 cycles.
So 12148/4=3037 less iterations. This is initial value in r24:r25.
ldi r16, 8
outer_loop:
ldi r24, 0
ldi r25, 0delay_loop:
adiw r24, 1
brne delay_loop
dec r16
brne outer_loop
; load r16 with 8
; outer loop label
;
; clear register 24
; clear register 25; the loop label
; "add immediate to word": r24:r25 are incremented
; if no overflow ("branch if not equal"), go back to "delay_loop"
;
; decrement r16
; and loop if outer loop not finished
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
11/25
.org 0x0000
rjmp main
main:
ldi r16, low(RAMEND)
out SPL, r16
ldi r16, high(RAMEND)
out SPH, r16
ldi r16, 0xFF
out DDRB, r16
loop:
sbi PortB, 3
rcall delay_05cbi PortB, 3
rcall delay_05
rjmp loop
delay_05:
ldi r16, 8
outer_loop:
ldi r24, low(3037)
ldi r25, high(3037)delay_loop:
adiw r24, 1
brne delay_loop
dec r16
brne outer_loop
ret
; the next instruction has to be written to address 0x0000
; the reset vector: jump to "main"
;
;
; set up the stack
;
;
;
;
; load register 16 with 0xFF (all bits are 1)
; write the value in r16 (0xFF) to Data Direction Register B
;
; switch off the LED
; wait for half a second; switch it on
; wait for half a second
; jump to loop
;
; the subroutine:
; load r16 with 8
; outer loop label
;
; load registers r24:r25 with 3037, our new init value
;; the loop label
; "add immediate to word": r24:r25 are incremented
; if no overflow ("branch if not equal"), go back to "delay_loop"
;
; decrement r16
; and loop if outer loop not finished
; return from subroutine
Also add .include m16def.inc or any relevant file such as m8def.inc
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
12/25
The Stack
Stack is like a notepad to remind you where you just left in
case you are visiting several locations.
Stack pointer tells you where that stack is.
When a subroutine is called, it leaves the place in flash whereit was just working and saves the return address on the stack.
The stack needs a stack pointer (SP) and space in SRAM (the
stack pointer must point above the first SRAM address).
When a return address is stored, the SP is post-decremented.
i.e. the Stack is growing towards smallerSRAM addresses. Biggest stack possible is initialized to RAMEND till first SRAM
location.
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
13/25
The Stack
.include m16def.inc
.def temp = r16
.org 0x00
ldi temp, low(RAMEND)
out SPL,temp
ldi temp, high(RAMEND)
out SPH, temp
rcall subrtn_1
.org 0x100
subrtn_1:
rcall subrtn_2
ret
.org 0x140
subrtn_2:
ret
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
14/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
15/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
16/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
17/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
18/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
19/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
20/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
21/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
22/25
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
23/25
Push/Pop
The stack can also be used to pass arguments tosubroutines using push and pop
push r16
push r17
rcall set_TCNT1
set_TCNT1:
pop r17
pop r16
out TCNT1H, r17
out TCNT1L, r16
ret
; push 16-but argument r16:r17
;
; and call the subroutine;
; our subroutine writes its 16-bit argument to the Timer 1 counter
; register. It pops the argument from the stack
; (reversed order!)
; and uses it
;
; now it returns.
The stack can also be used to pass arguments tosubroutines using push and pop.
Balance Push and Pop. Missing a pop or too many popsabove can cause error on Subroutine return.
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
24/25
Stack Initialization forSubroutines
-
8/9/2019 Lecture_5 Introduction to Assembly Language ProgrammingLec5
25/25
Subroutines
RAMEND is defined in the micros include file you get with
AVRStudio and equal to the last available internal SRAM address.
A subroutine begins with a label which is the subroutine's name.
.include "m16def.inc"
ldi r16, low(RAMEND)
out SPL, r16
ldi r16, high(RAMEND)
out SPH, r16
main:
rcall out_PortA
rjmp main
out_portA:
out PortA, r16
ret
Rcall: This instruction jumps
to a relative address and is
2 bytes long and needs 3
cycles for execution. The
disadvantage is that the
subroutine has to belocated at +/- 2k words. Call
can be used for absolute
addressing (4bytes,
4cycles). The 8k AVRs only
need rjmp and rcall.