Professional Documents
Culture Documents
Lecture - 5 Introduction To Assembly Language ProgrammingLec5
Lecture - 5 Introduction To Assembly Language ProgrammingLec5
Introduction to Assembly
Language Programming
Assembly vs. High Level Language
Assembly is a low-level language. It is different from
other high-level languages.
High level languages are abstract. A single high level
instruction 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 level
languages.
Assembly Language program can be 20 times faster
than high level program.
Assembly gives direct access to hardware features.
Faster development time for high level programs.
Assembly vs. High Level Language
4(2adiw+2brne)*0xFFFF(looping) +
3(overflow 2adiw+1brne) + 2(clr) = 262145
cycles. This is still not enough:
2,000,000/262,145 ~ 7.63.
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 brne
didn’t 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 ; load r16 with 8
outer_loop: ; outer loop label
;
ldi r24, 0 ; clear register 24
ldi r25, 0 ; clear register 25
delay_loop: ; the loop label
adiw r24, 1 ; "add immediate to word": r24:r25 are incremented
brne delay_loop ; if no overflow ("branch if not equal"), go back to "delay_loop"
;
dec r16 ; decrement r16
brne outer_loop ; and loop if outer loop not finished
.org 0x0000 ; the next instruction has to be written to address 0x0000
rjmp main ; the reset vector: jump to "main"
;
main: ;
ldi r16, low(RAMEND) ; set up the stack
out SPL, r16 ;
ldi r16, high(RAMEND) ;
out SPH, r16 ;
;
ldi r16, 0xFF ; load register 16 with 0xFF (all bits are 1)
out DDRB, r16 ; write the value in r16 (0xFF) to Data Direction Register B
loop: ;
sbi PortB, 3 ; switch off the LED
rcall delay_05 ; wait for half a second
cbi PortB, 3 ; switch it on
rcall delay_05 ; wait for half a second
rjmp loop ; jump to loop
;
delay_05: ; the subroutine:
ldi r16, 8 ; load r16 with 8
outer_loop: ; outer loop label
;
ldi r24, low(3037) ; load registers r24:r25 with 3037, our new init value
ldi r25, high(3037) ;
delay_loop: ; the loop label
adiw r24, 1 ; "add immediate to word": r24:r25 are incremented
brne delay_loop ; if no overflow ("branch if not equal"), go back to "delay_loop"
;
dec r16 ; decrement r16
brne outer_loop ; and loop if outer loop not finished
ret ; return from subroutine
.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
Push/Pop
The stack can also be used to pass arguments to
subroutines using push and pop
push r16 ; push 16-but argument r16:r17
push r17 ;
rcall set_TCNT1 ; and call the subroutine
;
set_TCNT1: ; our subroutine writes its 16-bit argument to the Timer 1 counter
pop r17 ; register. It pops the argument from the stack
pop r16 ; (reversed order!)
out TCNT1H, r17 ; and uses it
out TCNT1L, r16 ;
ret ; now it returns.