Memory Addressing Modes
Memory Addressing Modes
د/إعداد
Lecture 4
Memory Addressing Modes
Page 1
هــــدى جمعــــه. د/إعداد
The CPU can access data in various ways. The data could be in a register, or in
memory, or provided as an immediate value. These various ways of accessing data
are called addressing modes. So, memory addressing refers to the ways in which
a microcontroller accesses data to carry out an instruction. Memory addressing
modes are determined when a microcontroller is designed, and cannot be changed by
a programmer.
- Direct addressing occurs when the memory address is stored as part of the
instruction itself. Direct addressing is typically fast (the data to be operated on in
memory is pointed to directly), and has the flexibility of allowing variable data to
be manipulated, rather than constant data (which is used in immediate
addressing). Looping is not possible in direct addressing mode.
- Indirect addressing occurs when a pointer is used instead of the memory
address. Looping is possible in indirect addressing mode, and this is the
main difference between the data direct and data indirect addressing
modes. Indirect addressing is slower than direct addressing (first the pointer
must be loaded, then the contents of the memory address that the pointer points
to is operated on).
In the following we will discuss AVR addressing modes associated with some
examples.
=================================================================
1-1 Direct, single register addressing mode: Instructions with only a single register
(Rd) operand address memory in a way known as direct, single register
addressing, which is shown schematically in Figure 1.
GPRS
NEG instruction takes the two's complement value of register R18 and saves the
result back into that same register. It is capable of addressing all of the 32 GPRs
using 5 bits in the instruction. The remaining 11 bits are used for the opcode.
Examples:
COM R19 ; Complement the contents of R19 (1's comp. of R19)
INC R20 ; Increment R20
DEC R21 ; Decrement R21
ROR R22 ; Rotate right R22 through carry
=================================================================
2-2 Direct, two register addressing mode: Instructions with two general
purpose register operands (Rd and Rr) address memory in a way known as direct,
two register addressing, which is shown schematically in Figure 2. The result of
these instructions is always stored in Rd, the destination register.
GPRS
The AND and ANDI instructions demonstrate the difference between two-register
addressing and immediate addressing.
AND is a logical AND operation that occurs between two GPRs, Rd and Rr. The
data is fetched from each of the registers, routed to the ALU, and then stored the
result in the destination register. All of the GPRs can be addressed in this
instruction, leaving 6 bits for the opcode. The machine instruction is:
0010 00rd dddd rrrr
Where 001000 is the opcode, rrrrr indicates the binary value of the source
register, and ddddd indicates the binary value of the destination register.
ANDI is a logical AND operation with an immediate. This means that the
microcontrollers performs a logical AND between the contents of GPR (Rd) and
an immediate value, with the result stored in the destination register. 8 bits of the
instruction are used for the immediate; 4 bits are used for the GPR, leaving 4 bits
for the opcode. The machine instruction for ANDI is:
0111 KKKK dddd KKKK
Where 0111 is the opcode, dddd indicates the binary value of the destination
register (the instruction uses GPRs 16–31), and KKKKKKKK indicates the binary
value of the immediate data (0-255). For example:
ANDI R19, 0b01000000 ; R19 ← AND R19 with 0x40
Other examples of immediate addressing mode:
LDI R19, 0x25 ; Load immediate value (0x25) into R19
SUBI R19, 0x6 ; R19←Subtract immediate value (0x6) from R19
Example:
LDI R20, 230 ; Load immediate decimal value 230 into R20
LDI R22, 15 ; Load immediate decimal value 15 into R22
ADD R20, R22 ; R20 = R20 + R22
=================================================================
Page 4
هــــدى جمعــــه. د/إعداد
Some of the standard I/O registers are PIND, DDRD, PORTD, PINC, DDRC, and
PORTC...
I/O direct register addressing shown schematically in Figure 3 is used when the
instruction contains the address of the I/O register (A) to be operated on. As there are
64 I/O registers, each instruction requires 6 bits to indicate the I/O memory
location (can take values from 0x00 to 0x3F, which is from 0 to 63 in decimal).
In I/O direct addressing mode, instructions contain an I/O address (A) as well as a
destination general purpose register (Rd) and/or a source general purpose register
(Rr).
Notable instructions that use direct I/O addressing are IN and OUT:
- IN: loads data from an I/O register into a destination GPR (Rd).
- OUT stores the contents from a source GPR (Rr) into one of the I/O registers.
6 bits are used to address the I/O register, 5 bits are used to address the (source or
destination) GPR, and the remaining 5 bits are used for the opcode.
Example: The following assembly code loads data from PIN registers of port B and
port C into GPRs, perform a subtraction, and store the result in a destination register.
Page 5
هــــدى جمعــــه. د/إعداد
4-1 Data memory direct addressing mode: Data direct addressing occurs when an
instruction contains directly a 16-bit data address as an operand as shown in
Figure 4. In this mode:
- The least significant word of an instruction contains the 16-bit data address.
- The most significant word (16-bit) contains 5 bits to address the destination
or source GPR (Rd or Rr) and the 11 bits used for the opcode.
- Because there are two instruction words to decode, these instructions require at
least 2 clock cycles to execute.
16 bits available for the data memory address means that it is limited to addressing
the first 64 KB of data stored in SRAM. This is not a problem on the
ATmega328P which only has 2 KB of memory.
Where 10010000000 is the opcode, ddddd indicates the binary value of the
destination register ddddd= 10011= 19, and kkkkkkkkkkkkkkkk indicates the
address in SRAM to be accessed = 0000 0101 0110 0000= 0x560.
Another instruction that uses direct data memory addressing mode is STS
instruction:
STS 0x40, R19 ; Store R19 to data memory address location 0x40
=================================================================
Page 6
هــــدى جمعــــه. د/إعداد
Note: It must be noted that data memory does not support immediate addressing
mode. In other words, to move data into internal SRAM or to I/O registers, we
must first move it to a GPR, and then move it from the GPR to the data
memory space using the STS instruction.
For example, if we want to store 0x95 in memory location 0x520 we should write
the following program, as there is no instruction for storing immediate values in
memory locations:
LDI R19, 0x95 ; Load immediate value (0x95) into R19
STS 0x520, R19 ; Store R19 to data memory address location 0x520
=================================================================
4-2 Data memory Indirect addressing mode: Data indirect addressing occurs when
the operand address is the contents of the X, Y or Z pointer register. This
mode, shown schematically in Figure 5, is used to access extended I/O registers or
the internal SRAM.
In the data indirect addressing mode, a register is used as a pointer to the data
memory location. In the AVR, three registers are used for this purpose: X, Y,
and Z, these are 16-bit registers allowing access to the 65,536 bytes of data
memory space.
As shown in Figure 6, each of the registers is made by combining two specific
GPRs:
- Combining R26 and R27 makes the X register. In this case R26 is the lower byte
of X, and R27 is the higher byte.
- Combining R28 and R29 makes the Y register. R28 is the lower byte of Y, and
R29 is the higher byte.
- Combining R30 and R31 makes the Z register. R30 is the lower byte of Z, and
R31 is the higher byte.
The R26, R27, R28, R29, R30, and R31 GPRs can be referred to as XL, XH, YL,
YH, ZL, and ZH, respectively. For example, "LDI XL, 0x31" is the same as "LDI
R26, 0x31" since XL is another name for R26.
The 16-bit registers X, Y, and Z are widely used as pointers. We can use them with
the LD instruction to read the value of a location pointed to by these registers. For
example, the following instruction reads the value of the location pointed to by the
X pointer and loads it in R24:
LD R24, X ; Load into R24 from location pointed to by X
=================================================================
Example: The following program loads the contents of location 0x130 into R18.
LDI XL, 0x30 ; Load R26 (XL) with 0x30
LDI XH, 0x01 ; Load R27 (XH) with 0x01
LD R18, X ; Copy the contents of location 0x130 into R18
In this example the program loads 0x130 into the X register; this is done by loading
0x30 into R26 (the lower byte of X) and 0x01 into R27 (the higher byte of X). Then
it loads R18 with the contents of the location to which X points.
=================================================================
Another instruction that can be used with the pointer registers is ST instruction.
The ST instruction can be used to write a value to a location to which any of the X,
Y, and Z registers points.
Example: The following program stores the contents of R23 into location 0x039F.
LDI ZL, 0x9F ; Load 0x9F into the low byte of Z
LDI ZH, 0x03 ; Load 0x03 into the high byte of Z Z= 0x039F
ST Z, R23 ; Store the contents of R23 into location 0x039F
=================================================================
Note: One of the advantages of data indirect addressing mode is that it makes
accessing data dynamic rather than static, as with data direct addressing mode.
=================================================================
Example: Write a program to store the value 0x55 into memory locations 0x140
through 0x144 using:
(a) Data memory direct addressing mode.
(b) Data memory indirect addressing mode without a loop.
(c) A loop.
Solution:
a) Data direct addressing mode.
LDI R17, 0x55 ; Load R17 with value 0x55
STS 0x140, R17 ; Copy R17 to memory location 0x140
STS 0x141, R17 ; Copy R17 to memory location 0x141
STS 0x142, R17 ; Copy R17 to memory location 0x142
STS 0x143, R17 ; Copy R17 to memory location 0x143
STS 0x144, R17 ; Copy R17 to memory location 0x144
Page 8
هــــدى جمعــــه. د/إعداد
Page 9
هــــدى جمعــــه. د/إعداد
For example, if we want to read (load) from the location that is 5 bytes (q= 5) after the
location to which Z points, we can write the following instruction:
LDD R20, Z+5 ; Load from the address Z+5 into R20
Note that LDD instruction (Load with Displacement) can be used with the data
indirect with displacement mode. The general format of the instruction is as follows:
Another instruction that can be used with this mode is STD (Store with Displacement),
which is used to store a byte of data in a data memory location with displacement. The
general format of the instruction is as follows:
For example, the following instruction writes (stores) the contents of R20 into the
location that is five bytes away from where Z points to.
STD Z+5, R20 ; Store R20 into the address location Z+5
=================================================================
Note that data indirect with displacement is not available with pointer register X.
=================================================================
Page 10
هــــدى جمعــــه. د/إعداد
Example: Write instructions that initialize Y register to points to the data memory
location 300 (in decimal), and then:
- Load R5 with value stored in location 300 indirectly.
- Load R4 with value stored in location 315 indirectly.
Solution:
Since 300= 0x12D
LDI YL, 0x2D
LDI YH, 0x01 ; initialize Y register
; Y= 0x012D= 300 in decimal
LD R5, Y ; Load indirectly the value stored in address 300 into R5
LDD R4, Y+15 ; Load indirectly the value stored in address 315 (Y + 15) into R4
=================================================================
Example: Write assembly code that adds the contents of three continuous locations of
data space and stores the result in the first location. Firstly initialize the Z register to
point to the memory location 0x0200.
Solution:
LDI ZL, 0x00
LDI ZH, 0x02 ; initialize Z register Z= 0x0200
LDI R21, 0 ; R21= 0 (used to hold the upper byte of the summation)
LD R20, Z ; R20= contents of location pointed to by Z
; R20 used to hold lower byte of the summation
LDD R16, Z+1 ; R16= contents of location pointed to by Z+1
ADD R20, R16 ; R20= R20 + R16
BRCC L1 ; Branch if carry cleared
INC R21 ; Increment R21 if carry occurred
L1: LDD R16, Z+2 ; R16= contents of location pointed to by Z+2
ADD R20, R16 ; R20= R20 + R16
BRCC L2 ; Branch if carry cleared
INC R21 ; Increment R21 if carry occurred
L2: ST Z, R20 ; Store R20 into location pointed to by Z
STD Z+1, R21 ; Store R21 into location pointed to by Z+1
=================================================================
Page 11
هــــدى جمعــــه. د/إعداد
Using the "INC ZL" instruction to increment the pointer can cause a problem when an
address such as 0x5FF is incremented. The instruction "INC ZL" will not propagate the
carry into the ZH register. The Data indirect addressing with pre-decrement mode
and post-increment mode affect the entire 16 bits of the pointer register.
=================================================================
The syntax used for the LD instruction in such cases is shown below.
LD Rd, X ; after loading Rd from location pointed to by X, the X stays the same
; Load indirect: Rd ← (X)
LD Rd, X+ ; after loading Rd from location pointed to by X, the X is incremented
; Load indirect and post-inc.: Rd ← (X), X ← X+1
LD Rd, -X ; The X is decremented then the location pointed to by X is loaded into Rd
; Load indirect and pre-dec.: X ← X-1, Rd ← (X)
Page 12
هــــدى جمعــــه. د/إعداد
LD Rd, Y ; after loading Rd from location pointed to by Y, the Y stays the same
; Load indirect: Rd ← (Y)
LD Rd, Y+ ; after loading Rd from location pointed to by Y, the Y is incremented
; Load indirect and post-inc.: Rd ← (Y), Y ← Y+1
LD Rd, -Y ; The Y is decremented then the location pointed to by Y is loaded into Rd
; Load indirect and pre-dec.: Y ← Y-1, Rd ← (Y)
LDD Rd, Y+q ; after loading Rd from location pointed to by Y+q, the Y stays the same
; Load indirect with displacement: Rd ← (Y+q)
LD Rd, Z ; after loading Rd from location pointed to by Z, the Z stays the same
; Load indirect: Rd ← (Z)
LD Rd, Z+ ; after loading Rd from location pointed to by Z, the Z is incremented
; Load indirect and post-inc.: Rd ← (Z), Z ← Z+1
LD Rd, -Z ; The Z is decremented then the location pointed to by Z is loaded into Rd
; Load indirect and pre-dec.: Z ← Z-1, Rd ← (Z)
LDD Rd, Z+q ; after loading Rd from location pointed to by Z+q, the Z stays the same
; Load indirect with displacement: Rd ← (Z+q)
=================================================================
Note: The Data indirect addressing with pre-decrement mode and post-increment it
works for other instructions such as ST. For example:
Example: Assume that RAM locations 0x90 – 0x94 have a string of ASCII data, as
shown below.
0x90 = ('H') 0x91 = ('E') 0x92 = ('L') 0x93 = ('L') 0x94 = ('O')
Write assembly program to get each character and send it to PortD one byte at a
time. Show the program using:
a) Data direct addressing mode.
b) Data indirect addressing mode.
Solution:
a) Using data direct addressing mode.
LDI R20, 0xFF ; R20 = 0xFF = 11111111 in binary
OUT DDRD, R20 ; configure port D as an output port
LDS R20, 0x90 ; R20= contents of location 0x90
OUT PORTD, R20 ; PORTD= R20
Page 13
هــــدى جمعــــه. د/إعداد
Page 15