0% found this document useful (0 votes)
58 views11 pages

Assembly Language Programming

Microprocessor's Interfacing These are the class Lectures Of COMSATS INSITUTE OF INFORMATION TECHNOLOGY ISLAMABAD, PAKISTAN delievered by sir Shehryar Khalid to Sp08-bet batch in spring 2010 semester

Uploaded by

Usman Ullah Asif
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
58 views11 pages

Assembly Language Programming

Microprocessor's Interfacing These are the class Lectures Of COMSATS INSITUTE OF INFORMATION TECHNOLOGY ISLAMABAD, PAKISTAN delievered by sir Shehryar Khalid to Sp08-bet batch in spring 2010 semester

Uploaded by

Usman Ullah Asif
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 11

Lecture 6

Assembly Language
Programming
The different jumps
• Rjmp: +/- 2k words. It can reach 4k words or 8k bytes of
program memory. Example:rjmp go_here
• Ijmp: "Indirect Jump" to (Z). jump to the address pointed
to by the Z index register pair. . Example:
ldi ZL, low(go_there)
ldi ZH, high(go_there)
ijmp
• Jmp: "Jump". While rjmp is limited to +/- 2k words, jmp
can be used to jump anywhere within the code space.
The disadvantage over rjmp is that jmp needs 2 words of
code space, while rjmp needs just one word.
Example: jmp go_far
Subroutine Calls
• Rcall "Relative Call Subroutine“. +/- 2k words. . When
rcall is executed, the return address is pushed onto the
stack. . It needs 1 word of program space.
Example: rcall my_subroutine
• Icall "Indirect Call to (Z)“The return address is pushed
onto the stack. icall needs two words of code space.
Example: ldi ZL, low(my_subroutine)
ldi ZH, high(my_subroutine)
icall
• Call It works just like rcall (regarding the stack) and
needs 2 words of code space.
Example: call my_subroutine
Return Instructions
• Ret and reti: These instructions have to placed
at the end of any subroutine or Interrupt Service
Routine (ISR).
• The return address is popped from the stack and
program execution goes on from there. reti is
used after ISRs. Basically it works like ret, but it
also sets the I Flag (Global Interrupt Enable
Flag) in the status register. When an ISR is
entered, this bit is cleared by hardware.
Indirect Calls/Jumps
ldi ZL, low(led_on) ; load Z with address to call
ldi ZH, high(led_on) ;
icall ; call led_on
  ;
led_on: ;this is where Z points at and therefore the address to call
ldi r16, 0b11111110  
out PortA, r16  
ret  
Indirect Calls/Jumps
• Indirect jumps/calls can also be used to make big case
structures faster. The value we want to process is
multiplied by the number of words a jmp needs (which is
two) and then added to the base address of our table.

in r16, UDR ; get data from UDR


lsl r16 ; multiply by two
clr r17 ; zero reg for 16-bit addition
ldi ZL, low(case_table) ;load jump table base address
ldi ZH, high(case_table) ;
add ZL, r16 ; add UDR*(jmp size) to Z
adc ZH, r17 ;
icall ; call table cell
reti ; and return
  ;
case_table: ; these are jumps to subroutines which in turn handle the
jmp UDR_is_zero ; case that occured.
jmp UDR_is_one ; when returning, the ALU will jump to the reti of the ISR above again.
jmp UDR_is_two ;
Case Structures
in r16, UDR ; get UART data
cpi r16, 0 ; compare with case_0 value (0)
breq case_0 ; if case_0, jump there
cpi r16, 1 ; compare with case_1 value (1)
breq case_1 ; if case_1, jump there
cpi r16, 2 ; ...and so on
breq case_2
For Loops
Counts a required number of iterations
ldi r16, 0 ; clear counting register
loop:
out PortB, r16 ; write counting register to PortB
inc r16 ; increase counter
cpi r16, 10 ; compare counter with 10
brne loop ; if <>10, repeat

ldi r16, 0 ; basically this loop acts like


loop1: ; the first one, with one exception.
inc r16 ; Find it.
out PortB, r16
cpi r16, 10
brne loop1

Decrement version:
ldi r16, 10 ; load r16 with desired number of iterations
loop2:
(insert loop code) ; do whatever the loop does...

dec r16 ; decrement loop counter


brne loop2 ; if not zero, repeat loop
While Loops
• The while()...do{}-loop checks if a certain test result is true and performs the
loop instructions.
while1: ; while(PinD = 1) rcall port_is_1
in R16, PinD ; perform check by reading pin value and
cpi r16, 1 ; comparing it to 1
brne while1_end ; if not true, end the loop
rcall port_is_1 ; rcall port_is_1
rjmp while1 ; and repeat loop
while1_end:

• The do{}...while()-loop executes the loop instruction at least once:


while2: ; Do rcall port_is_1 while(PinD = 1)
rcall port_is_1 ; rcall port_is_1
in r16, PinD ; check, see above
cpi r16, 1
breq while2 ; if true, repeat
while2_end: ; not true; proceed with following code
Macros
• Macros are a good way to make code more readable, for
example if it contains code that is often reused or if a lot
of 16-bit calculations are done.
• Macros in AVR assembler can be defined everywhere in
the code as long as they're not used at a location before
the macro definition.
• The arguments can only be used in the form @0 or @1.
• The arguments can be almost everything the assembler
can handle: integers, characters, registers, I/O
addresses, 16 or 32-bit integers, binary expressions...
Macros
This works:

; lets make a macro for loading two registers


.macro ldi16
; with a 16-bit immediate
 
; load the first argument (@0) with the low byte of @2
ldi @0, low(@2)
; same with second arg (@1) and high byte of @2
ldi @1, high(@2)
; end the macro definition
.endmacro
 
 
; r16 = 0x00 r17 = 0x04
ldi16 r16, r17, 1024

While this does not:

; r16 = 0x00 r17 = 0x04


ldi16 r16, r17, 1024
 
 
.macro ldi16
 
ldi @0, low(@2)
 
ldi @1, high(@2)
 
.endmacro

ldi16 r16, r17, 1024 ; in the macro, this was: 


; is assembled to:  
ldi r16, 0 ; ldi @0, low(@2)
ldi r17, 0x04 ; ldi @1, high(@2)

You might also like