CPU uses registers to store data temporairly. Most AVRs have 8 bit registers. Two kinds of registers. The General Purpose Registers(GPRs) & I/O registers.
ARVs have 32 general purpose registers. They are R0 to R31. And located in the lowers location of memory address($0000 to $001F). They can be used by all arithmatic and logical instructions.
I/O registers are dedicated to special functions such as status register, timers, serial comunications, I/O port, ADC etc. For this reason they are called special functions registers(SFRs). The function of each I/O register is fixed by the CPU designer as they are used to controll the microcontroller or peripheral functions supported by the microcontroller.
Internal SRAM is used for storing data. Each loacation of the SRAM can be accessed directly by its address. Each location is 8 bit wide.
EEPROM stores data permanently. data stays if power is off. SRAM loses data if power is off.
;
is used for comment in assembly programming.
LDI
instruction is used to Load a data into a GPR
LDI Rd, k
Load Imidiate value. Load value k
into GPR Rd
where 16 <= d <= 32. k
can be any binary, hexadecimal or decimal number.
LDS
instruction is used to load data into GPRs from a memory address
LDS Rd, K
Load from data space. Load Rd
with data from a memory address K
where 0 <= d <= 32. K
is a memory address between $0000 to $FFFF
STS
instruction is used to store data to a memory address from GPRs
STS K, Rd
Store directly into memory address K
from GPR Rd
. Here K
is an address of a memory location
ADD
instruction is used to add the data of two GPRs
ADD Rd, Rr ; Rd = Rd + Rr`
Add register Rd
and Rr
. And store result in Rd
IN
instruction is used to store data into GPRs from I/O registers
IN Rd, A
Retrieve data from I/O register location A
and store into the GPR Rd
. A
is the memory location of the I/O register. 0<= d <= 32, 0<= A <= 63
OUT
instruction is used to store value in I/O registers from GPRs
OUT A, Rr
Store GPR Rr
's value to an I/O register who's location is A
MOV
instruction is used to copy data among GPRs
MOV Rd,Rr ; Rd = Rr
copy data from Rr
to Rd
.
INC
instruction is used to increment data of a register by 1
INC Rd ; Rd = Rd + 1
Increment the value of Rd
by 1.
SUB
instruction is used to substract one GPR's value from another GPR's value
SUB Rd, Rr ; Rd = Rd - Rr
substarct the value of Rr
from the value of Rd
and store the result into Rd
.
DEC
instruction is used to decrement the value of a GPR by 1
DEC Rd ; Rd = Rd - 1
COM
instruction is used to make 1's complement of a GPR
COM Rd
invert the bits of Rd
and then store the value into Rd
NOP
(No Operation) instruction wastes time by spending one CPU cycle without executing any operation.
NOP ; Spend 1 CPU cycle doing nothing
CLR
(Clear) instruction is used to clear a register's value or set to zero.
CLR R20 ; R20 = 0
.EQU
directive is used to define a constant value / Label for some value of address.
.EQU HEXNUM = 0xFF
define HEXNUM
as a constant hex value 0xFF
.SET
directive is same as .EQU
but value assigned by set can be re-assigned leter
.SET HEXNUM = 0xFF
define HEXNUM
as a hex value 0xFF
.ORG
directive is used to specify start of a ROM location. Where codes will be burnt.
.ORG $0 ; Burn From ROM location 0x0
Bits D7 D0
---------------------------------
SREG | I | T | H | S | V | N | Z | C |
---------------------------------
C
= Carry Flag, This flag is set whenever there is a carry out from the D7 bit after an arithmetic operation(Addition, subtraction, increment, decrement etc). This flag bit is affected after an 8 bit addition or substruction.
Z
= Zero Flag, This flag is affected after an arithmetic or logic operation. If the result is zero than Z = 1
, else Z = 0
.
N
= Negative Flag, It reflects the result of an arithmetic operation. If the D7 bit of the result is zero then N = 0
and the result is positive. Else N = 1
and the result is negative.
V
= Overflow Flag,
S
= Sign Flag,
H
= Half Carry Flag, This bit is set if there is a carry from D3 to D4 bit after ADD or SUB instruction.
T
= Bit Copy Storage. Used as a temporary storage for bit. It can be used to copy a bit from a GPR to another GPR.
I
= Global Inturrupt Enable
CLC
(CLear Carry) instruction is used to clear carry bit, C = 0
SEC
(SEt Carry) instruction is used to set carry bit, C = 1
BRNE
(Branch If Not Equal) instruction is used for looping. BRNE
instruction uses the zero or Z flag in the status register. CPU jumps to target address if zero flag is low. Z = 0.
LABEL: ; loop body
DEC Rn ; Z flag = 1 if Rn = 0. Decrement Rn untill it becomes zero
BRNE LABEL ; Goto LABEL if Rn != 0 that means zero flag = 0
Example: Add 10 times
LDI R16, 10
LDI R20, 0
LDI R21, 20
AGAIN:
ADD R20, R21
DEC R16
BRNE AGAIN
BREQ
(BRanch If EQual). CPU jumps to target address if zero flag is High.
AGAIN:
IN R20, PORTB ; Load R20 from PORTB
TST R20 ; Examine R20 and set Z & N flag accordingly
BREQ AGAIN ; if Z = 1, goto AGAIN
BRCC
(BRanch if Carry Cleared). Branch if C = 0
BRSH
(BRanch if Same or Higher) Branch if C = 0
BRLO
(BRanch if LOwer) Branch if C = 1
TO DO
TO DO
A powerful feature of AVR I/O ports is their capability of access individual bits of the port without altering the rest of the bits.
32 I/O register's name and their address: $ sign indicates hexadecimal value.
Mem Add | I/O Add | Name | Mem Add | I/O Add | Name |
---|---|---|---|---|---|
$20 | $00 | TWBR | $30 | $10 | PIND |
$21 | $01 | TWSR | $31 | $11 | DDRD |
$22 | $02 | TWAR | $32 | $12 | PORTD |
$23 | $03 | TWDR | $33 | $13 | PINC |
$24 | $04 | ADCL | $34 | $14 | DDRC |
$25 | $05 | ADCH | $35 | $15 | PORTC |
$26 | $06 | ADCSRA | $36 | $16 | PINB |
$27 | $07 | ADMUX | $37 | $17 | DDRB |
$28 | $08 | ACSR | $38 | $18 | PORTB |
$29 | $09 | UBRRL | $39 | $19 | PINA |
$2A | $0A | UCSRB | $3A | $1A | DDRA |
$2B | $0B | UCSRA | $3B | $1B | PORTA |
$2C | $0C | UDR | $3C | $1C | EECR |
$2D | $0D | SPCR | $3D | $1D | EEDR |
$2E | $0E | SPSR | $3E | $1E | EEARL |
$2F | $0F | SPDR | $3F | $1F | EEARH |
Following instructions are used to manipulate single bit:
SBI
(Set Bit in I/O register) instruction is used to set a bit in I/O register. To make a bit 1.
SBI ioReg, bitNumber ; ioReg is the name of I/O register, which is any
; lower 32 I/O register. bitNumber(0 - 7) is the
; position of the bit of the register to manipulate
Example:
SBI PORTB, 5 ; This will set the D5(6th) bit of the PORTB register
; to 1. As a result the PB4(5th) pin of Port B will
; output high
CBI
(Clear Bit in I/O register) instruction is used to clear a bit in I/O register. To make a bit 0.
CBI ioReg, bitNumber ; ioReg is the name of I/O register, which is any
; lower32 I/O register. bitNumber is the
; number of the bit of the register to manipulate
Following instructions are used for checking an input pin & make decisions based on the input pin's status.
SIBS
(Skip if Bit in I/O register is Set) instruction tests a bit and skip next instruction if it is HIGH.
SIBS ioReg, bitNumber ; Skip next instruction if bitNumber bit of ioReg
; register is HIGH
SIBC
(Skip if Bit in I/O register is cleared) instruction tests a bit and skip next instruction if it is LOW.
SIBC ioReg, bitNumber ; Skip next instruction if bitNumber bit of ioReg
; register is LOW
Unsigned Number Operations: In this case the sign bit(8th bit) is not taken into account. So numbers can be from 0 to 255.
ADD Rd, Rr
This instruction adds register Rd with Rr and store the number into Rd. Z(Zero), C(Carry), N(Negative), V(Overflow), H(Half Carry), S(Sign) bits of the status register can be affected after this operation.
ADC
(Add with carry) instruction is used to add with carry bit. As it add with carry bit, 16 bit addition is possible with ADC instruction. As when adding two 16 bit data operands we need to concerned about the carry out from lower byte to upper byte. Its is called multi byte addition.
Example: Add 0x3CE7 with 0x3B8D
LDI R16, 0x8D ; R16 = 8D
LDI R17, 0x3B ; R17 = 3B
LDI R18, 0xE7 ; R18 = E7
LDI R19, 0x3C ; R19 = 3C
ADD R18, R16 ; R18 = R18 + R16 = E7 + 8D = 74 with C = 1(Carry Out)
; ADD instruction is used for lower byte as carry is
; not a concern here
ADC R19, R17 ; R19 = R19 + R17 + C(Carry out from previous operation)
; = 3C + 3B + 1
; = 78
; ADC instruction is used as carry is a concern for upper
; byte
; Result: 7874. R19 = 78, R18 = 74
There are five instrtuctions for substraction in AVR.
SUB
(Subtract)SBC
(Subtruct with borrow)SBI
(Subtract immediate)SBCI
(Subtract immediate with borrow)SBIW
(Subtract a immediate value from register pair)
C flag is used for borrow.
Subtraction Instruction Summary:
SUB Rd, Rr ; Rd = Rd - Rr. Borrow is not a concern for this instruction
SBC Rd, Rr ; Subtract with Borrow. Rd = Rd - Rr - C . In this case
; C flag is checked for Borrow. This instruction is useful
; for 16 bit subtraction.
SUBI Rd, K ; Subtract a value K from Rd without borrow. Rd = Rd - K.
SBCI Rd, K ; Subtract a value K from Rd with borrow. Rd = Rd - K - C
; In this case C flag is checked for borrow.
SBIW Rd:Rd+1, K ; Subtract a value K from Rd+1:Rd register pair.
In AVR(And most other CPUs) subtraction is done using 2's complement. Separate circuitry isn't used for subtraction as it takes too many transistors. Assuming that the AVR is executing a simple subtractions and C = 0 prior to this execution. The steps of SUB instruction for unsigned numbers are following:
- Take 2's complement of the righthand operator
- Add it with the lefthand operator.
- Invert the carry. Notice that carry is inverted after above operations.
Example: Subtract 0x23 from 0x3F
LDI R20, 0x23 ; R20 = 0x23
LDI R21, 0x3F ; R21 = 0x3F
SUB R21, R20 ; R21 = R21 - R20
There are 3 Multiplication instruction in AVR.
MUL Rd, Rr ; Multiply two unsigned numbers
MULS Rd, Rr ; Multiply two signed numbers
MULSU Rd, Rr ; Multiply signed number with unsigned number
Result is stored in R1(Higher byte) and R2(Lower byte) registers.
LDI R23, 0x25 ; R23 = 0x25
LDI R24, 0x65 ; R24 = 0x65
MUL R24, R23 ; R24 * R23 = 0x65 * 0x25 = 0xE99
; R1 = 0x0E, R2 = 0x99
There is no division instruction. But division can be done by repeated subtraction. To divide 95 with 10. Subtract 10 from 95, 9 times. The result is 05. So the quotient is 9 and remainder is 5.
So to divide in this method numerator is kept in a register. And the denuminator is subtracted repeatedly. So the quotient is the number of times subtracted. And the remainder is in the register.
Example: devide 95 by 10
.DEF NUM = R20 ; Define R20 as NUM
.DEF DENUM = R21 ; Define R21 as DENUM
.DEF QUOTIENT = R22 ; Define R22 as QUOTIENT
LDI NUM, 90
LDI DENUM, 10
CLR QUOTIENT
L1:
INC QUOTIENT ; Increment QUOTIENT
SUB NUM, DENUM ; Subtact DENUM from NUM
BRCC L1 ; Branch if Carry is Cleared. C = 0. After repeated
; subtraction if the result is negative C = 1. And the
; branching / looping will be stopped.
DEC QUOTIENT ; As once too many
ADD NUM, DENUM ; add back to it
Signed Numbers: For signed numbers the most significant bit(D7 bit for 8 bit number) is reserved for sign. And number is represented by other bits. 0 in the D7 bit indicates positive number & 1 indicates negative number.
Positive Number: for positive number D7 = 0. So the range of positive number is from +1 to +127.
Negative Number: For negative number D7 = 1. Negative numbers are represented using 2's complement. To find the binary representation of a negative number first write the magnitude of the number in the 8 bit format. Now take 2's complete of that. It will be the binary of the negative number of that magnitude. ; For example binary of -5 is 11111011. Binary of 5 in 8 bit format is 00000101. Take 2's complement. Its 11111011. So its the binary of -5. Notice that the D7 bit is 1. its indicating that the number is negative.
Overflow & V flag: TO DO
Difference between N & S flag: TO DO
Logic AND
operator:
AND Rd, Rr ; Rd = Rd & Rr
ANDI Rd, K ; Rd = Rd & K
AND
effects N, Z, S flags. N is the D7 bit of the result. Z = 1 if the result is zero.
AND
is often use to mask(Set to zero) bit. For example say I want to mask the D5 & D6 bits of 01100011. I can AND it with 10011111.
LDI R16, 0x63 ; R16 = 0x63 = 0b01100011
ANDI R16, 0x9F ; 0x63 & 0x9F = 01100011 & 10011111 = 00000011 = 0x03
; R16 = 0x03
Logic OR
operator:
OR Rd, Rr ; Rd = Rd | Rr
ORI Rd, K ; Rd = Rd | K
OR
effects N, Z, S flags. N is the D7 bit of the result. Z = 1 if the result
is zero.
OR is often used to set certain bits to 1. For example say I want to set the D3 & D4 bit of the 01100101 to 1. I can OR it with 00011000.
LDI R16, 0x65 ; R16 = 0x65 = 0b01100101
ORI R16, 0x18 ; 0x65 | 0x18 = 01100101 | 00011000 = 01111101 = 0x7D
; R16 = 0x7D
Logic exclusive or XOR
:
XOR Rd, Rr ; Rd = Rd XOR Rr
XOR effects N, Z, S flags. N is the D7 bit of the result. Z = 1 if the result is zero.
XOR can be used to check equality of two registers. If two registers are equal then the result of XOR of them will be zero. So Z will be set to 1. And we can take decision based on that.
another application of XOR can be toggling the bits. 10101010 XOR 11111111 = 01010101
Logic Inverter / Complement COM
:
LDI R20, 0xAA ; R20 = 0xAA = 10101010
COM R20 ; R20 = 0x55 = 01010101
Negation / 2's complement NEG
:
LDI R20, 0x56 ; R20 = 0x56 = 01010110 = 86 in decimal
NEG R20 ; R20 = 2's complement of 0x56 = 10101001 + 1 = 10101010 = 0xAA = -86 in decimal
Compare Instruction CP:
CP Rd, Rr ; Compare Rd with Rr
CPI Rd, K ; Compare Rd with imediate value K
compare instruction is really a subtraction except it doesn't change the left hand operator.
Compare instruction affects Z, C & S flags. Different branching instruction can be used based on this.
After CP instruction Z = 0 means operands are not equal. Z = 1 means operands are equal.
After CP instruction for unsigned numbers C = 0 means left hand operand is same or higher than the right hand operator. C = 1 means left hand operator is lower
After CP instruction for signed numbers S = 0 means left hand operand is greater than or equal. S = 1 means left hand operand is less than the right hand operand.
Branching Instructions: There are several branching instructions in AVR. Here is most frequently used instructions
BREQ LABEL ; BRanch if EQual zero. Branch to LABEL if the result
; of the previous
; instruction is zero( Z = 1 ). For example if the two
; operands are equal in CP instruction.
BRNE LABEL ; BRanch if Not Equal zero. Branch to LABEL if the result
; of the previous
; instruction is not zero( Z = 0 ). For example if the two
; operands are not equal in CP instruction.
BRSH LABEL ; BRanch if Same or Higher. Branch to LABEL if C = 0
; after previous instruction. For example if the left hand
; operand is same or higher in CP instruction. Can be used for
; unsigned numbers
BRLO LABEL ; BRanch if LOwer. Branch to LABEL if C = 1
; after previous instruction. For example if the left hand
; operand is lower in CP instruction. Can be used for
; unsigned numbers
BRGE LABEL ; BRanch if Greater than or Equal. Branch to LABEL if S = 0
; after previous instruction. For example if the left hand
; operand is greater than or equal in CP instruction. Used
; for signed numbers
BRLT LABEL ; BRanch if Less Than. Branch to LABEL if S = 1
; after previous instruction. For example if the left hand
; operand is less than right hand operand in CP instruction.
; Used for signed numbers.
BRCS LABEL ; BRanch to LABEL if Carry is Set. C = 1
BRCC LABEL ; BRanch to LABEL if Carry is Cleared. C = 0
BRVS LABEL ; BRanch if V flag is Set. Branch to LABEL if overflow
; happens(V = 1)
BRVC LABEL ; BRanch if V flag is Cleared. Branch to LABEL if overflow
; does not happen(V = 0)
Some example of branch instructions: TO DO
Rotational & Shift Instruction:
ROR
(Rotate right) instruction rotate 1 bit from left to right through carry. As rotate from left to right after rotate command the carry flag enters to MSB and LSB exits to carry.
ROR Rd ; Rotate Rd right through carry
Example
CLC ; Clear carry C = 0
LDI R20, 0x26 ; R20 = 0x26 = 0b00100110
ROR R20 ; R20 = 00010011 C = 0
ROR R20 ; R20 = 00001001 C = 1
ROR R20 ; R20 = 10000100 C = 1
ROL
(Rotate Left) instruction rotate 1 bit from right to left through carry. As rotate from right to left after rotate command the carry flag enters to LSB and MSB exits to carry.
ROL Rd ; Rotate Rd left through carry
; Example
SEC ; Set carry C = 1
LDI R20, 0x15 ; R20 = 0x15 = 00010101
ROL R20 ; R20 = 00101011 C = 0
ROL R20 ; R20 = 01010110 C = 0
ROL R20 ; R20 = 10101100 C = 0
ROL R20 ; R20 = 01011000 C = 1
There are three logical shift operator in AVR:
LSL
(Logical Shift Left) instruction shifts bits from right to left. After shift instruction 0 is entered into LSB and MSB exits to carry. Notice shift instruction multiply the content of the register by 2.
CLC ; Clear carry C = 0
LDI R20, 0x26 ; R20 = 0x26 = 00100110 = 38
LSL R20 ; R20 = 01001100 = 76 C = 0
LSL R20 ; R20 = 10011000 = 152 C = 0
LSL R20 ; R20 = 00110000 = 48 C = 1
; Notice not multiplied as C = 1, overflow
LSR
(Logical Shift Right) instruction shifts bits from left to right. After shift instruction 0 is entered into MSB and LSB exits to carry. Notice shift instruction devides the content of the register by 2.
CLC ; Clear carry C = 0
LDI R20, 0x26 ; R20 = 0x26 = 00100110 = 38
LSR R20 ; R20 = 00010011 = 19 C = 0
LSR R20 ; R20 = 00001001 = 9 C = 1
LSR R20 ; R20 = 00000100 = 4 C = 1
ASR
(Arithmetic shift right) istruction can devide signed numbers by two. As ASR can shift bits to right without altering MSB. LSB exits to carry.
CLC ; C = 0
LDI R20, 0xD0 ; R20 = 11010000 = -48
ASR R20 ; R20 = 11101000 = -24 C = 0
ASR R20 ; R20 = 11110100 = -12 C = 0
ASR R20 ; R20 = 11111010 = -6 C = 0
ASR R20 ; R20 = 11111101 = -3 C = 0
ASR R20 ; R20 = 11111110 = -1 C = 1
SWAP
instruction swaps the nibble of a byte.
SWAP Rd ; Swaps nibble of Rd register where 0 <= d <= 31
Before: |D7|D6|D5|D4|D3|D2|D1|D0|
After: |D3|D2|D1|D0|D7|D6|D5|D4|
CPU can access data in various ways. The data could be in registers, in memory or provided as a direct value. These various ways of accessing data is called addressing modes. AVR supports 13 distinct address modes. They can be catagorized into following groups:
- Single Register or Immediate address mode(Only single register is involved)
- Two Register addressing mode
- Direct address mode(Memory is accessed by their direct addresses)
- Indirect address mode(Memory is accessed by using registers as pointers pointing to memory)
- Flash Direct address mode(Direct access to flash rom by flash memory addresses)
- Flash Indirect address mode (Accessed using pointers)
Single register address mode: In this address mode operand is single register. imediate values can be used in this address mode. So its called immediate address mode too. Registers from R16 to R31 can be used in this address mode.
Example:
NEG R16 ; Negate R16 contents
COM R16 ; Take complement
DEC R16 ; Decrement R16's content by 1
INC R16 ; Increment R16's content by 1
LDI R16, 0xFF ; Load R16 with immediate value
ADI R16, 0x05 ; Add R16 with an immediate value
ANDI R16, 0b00100101 ; AND R16 with 0x25
- These are 16 bit instructions.
- In instructions involving only register: 12 bit for opcode & 4 bit for register's address.
- In insstructions with immediate values: 4 bits for opcode, 8 bits for immediate value & 4 bits for register's address.
Two register address mode: Instructions involving two registers.
Example:
ADD R16, R17 ; R16 = R16 + R17
MOV R16, R17 ; Move content of R17 to R16
- 16 bits instructions.
- 6 bits for opcode, 5 bits for left hand register & 5 bits for right hand register.
Direct address mode: In this address mode content of RAM memory or I/O registers are accessed by their direct addresses.
Example:
LDS R16, 0x200 ; Load R16 with the contents of location $200
STS 0x305, R20 ; Save R20's contents is RAM location $305
I/O registers can be accessed by their direct memory address or their direct I/O address. Direct memory address is used in direct memory instructions & I/O addressing is used in I/O instructions. For example following two instructions are same:
OUT 0x18, R16 ; 0x18 is the I/O address of port B.
; This instruction is sending content of R16 to port B.
STS 0x38, R16 ; 0x38 is the memory address of port B.
; This instruction also sending content of R16 to port B.
I/O instructions are faster than memory instructions. also I/O registers name can be used instead of address. These names are defined in .INCLUDE file. Its safer and portable. As I/O addresses can be different in different AVR.
OUT PORTB, R16 ; Send contents of R16 to port B
In memory instructions 16 bit is reserved for memory location. So from $0000 to $FFFF locations of memory can be addressed. So 65536 bytes of data from RAM can be accessed. In I/O instructions address field is 6 bits. So from $00 to $3F addresses can be accessed. So total 64(0 to 63) I/O registers can be accessed. These are standard I/O register memory space.
In some AVRs there is more than 64 I/O registers. These extra I/O registers are called extended I/O registers. As in I/O direct addressing mode address space is 6 bits, extended I/O registers can't be accessed via I/O direct addressing mode. For these direct memory addressing mode have to be used.
STS 0x62, R20 ; Save content of R20 in PORT F, which is an extended I/O
; register in ATmega128
Indirect memory addressing:
X
pointer is mapped toR26(low byte, XL)
&R27(hight byte, XH)
Y
pointer is mapped toR28(low byte, YL)
&R29(hight byte, YH)
Z
pointer is mapped toR30(low byte, ZL)
&R31(high byte, ZH)
LD
instruction is used to read from the location pointed to by pointer. For example to read from location pointed by X:
LD R16, X ; Load R16 with the content of data memory location
; pointed to by X
Load the content of data memory location 0x302 into R20:
LDI XL, 0x02 ; Load R26(Lower byte of X) with 0x02
LDI XH, 0x03 ; Load R27(Higher byte of X) with 0x03.
; So, Now X is pointing to 0x302
LD R20, X ; Load R20 with content of location 0x302
; which is pointed to by X
ST
instruction is used to store a value into a location pointed to by a pointer.
Example: Store the content of R20 into location 0x139F
LDI XL, 0x9F ; Load XL with lower byte of the address
LDI XH, 0x13 ; Load XH with higher byte of the address
ST X, R20 ; Store the content of R20 into location
; pointed to by X, 0x139F
Auto increment: Incrementing pointer's lower byte with INC instruction has a problem. If the address is 0x1FF, if we increment XL, carry will not propagate into XH. In this case we can use auto increment feature:
LD Rn, X+ ; Load Rn with the content of memory location pointed to
; by X and then increment X to point to the next location.
; In this case if there is a carry from lower byte of
; the address, carry will be propagate to higher byte.
Indirect addressing with displacement: Suppose we want to read / write from a few bytes higher than where Z is pointing. In that case we can use indirect addressing with displacement. LDD
& STD
instruction is used for indirect addresing with displacement.
LDD Rn, Z+q ; Load Rn with the contents of memory location pointed to by Z+q
STD Z+q, Rn ; Store content of Rn into location pointed to by Z+q
Example: Store 0x55 into location 0x401 & 0x405
LDI R20, 0x55
LDI ZL, 0x01
LDI ZH, 0x04
ST Z, R20
STD Z+4, R20
Look up table: TO DO
Setting & Clearing Bit: To set and clear lower 32 I/O register(I/O address 0 to 31) we can use SBI
( Set Bit in I/O Register ) and CBI
( Clear Bit in I/O Register ) instruction.
SBI PORTA, 1 ; Set bit 1 of PORTA
CBI PORTB, 5 ; Clear bit 5 of PORTB
Example: Toggle PB2 200 times
SBI DDRB, 2 ; PB2 is output
LDI R16, 200
LOOP:
SBI PORTB, 2 ; PB2 is HIGH
CBI PORTB, 2 ; PB2 is LOW
DEC R16
BRNE LOOP
HERE: RJMP HERE ; Infinite Loop
Checking the bits of I/O Registers: To check if the bit of a I/O register is set or cleared we can use SBIS
(Skip next instruction if Bit in I/O register is Set) andSBIC
(Skip next instruction if Bit in I/O register is Cleared).
Example: A switch is connected to pin PC7. Check the status of switch. If switch is HIGH send 'Y' to Port D. Else send 'N' to Port D.
CBI DDRC, 7 ; PC7 is input pin
LDI R16, 0xFF
OUT DDRD, R16 ; Port D is output
LOOP:
SBIS PINC, 7 ; Skip next if PC7 is HIGH
RJMP SHOWN
LDI R16, 'Y'
OUT PORTD, R16
RJMP LOOP
SHOWN:
LDI R16, 'N'
OUT PORTD, R16
RJMP LOOP
Status Reguster:
Bit: D7 D0
---------------------------------
SREG: | I | T | H | S | V | N | Z | C |
---------------------------------
I = Global Interrupt V = Overflow Flag
T = Bit Copy N = Negative Flag
H = Half Carry Z = Zero Flag
S = Sign Flag C = Carry Flag
Manipulating Status Register's Bits: BSET
and BCLR
instruction can be used to set and clear the bit of a status register.
BSET s ; Set the bit s of status register
BCLR s ; Clear the bit s of status register
Example:
BSET 0 ; Set carry flag, C = 1
BCLR 1 ; Clear Zero flag Z = 0
There are also dedicated instructions for setting and clearing each flags. Shown in the following table:
Instruction | Action | Instruction | Action |
---|---|---|---|
SEC | Set Carry, C = 1 | CLC | Clear Carry, C = 0 |
SEZ | Set Zero, Z = 1 | CLZ | Clear Zero, Z = 0 |
SEN | Set Negative, N = 1 | CLN | Clear Negative, N = 0 |
SEV | Set Overflow, V = 1 | CLV | Clear Overflow, V = 0 |
SEH | Set Half Carry, H = 1 | CLH | Clear Half Carry, H = 0 |
SES | Set Sign, S = 1 | CLS | Clear sign, S = 0 |
SET | Set Temporary, T = 1 | CLT | Clear Temporary, T = 0 |
SEI | Set Global Interrupt, I = 1 | CLI | Clear Global Interrupt, I = 0 |
Checking Status Register Bits: BRBS
(Branch if status register Bit is Set) and BRBC
(Branch if status register Bit is Cleared) instruction can be used to examine status register flags and take decisions according to their value.
BRBS s,k ; Branch if bit s is set and go to relative address k
BRBC s,k ; Branch if bit s is cleared and go to relative address k
Example:
BRBS 0, L1 ; Branch if bit 0 of SREG is set and goto L1
LDI R17, 0xFF ; Otherwise insert 0xFF into R17
L1: ; address L1