Accessing Atmega32 SRAM data memory Addressing Modes Load and Store Instructions CS-280 Dr. Mark L. Hornick 1 Atmega32 Memory Address bus (16-bit in Atmega32) A unique 16-bit address references each memory byte. Data bus (8-bit) Volatile – RAM (fast RW) Nonvolatile – ROM (fast R – slow W) SRAM (no refresh req’d) DRAM (refresh needed, but cheaper; none on Atmega32, but typical on PC’s) CS-280 Dr. Mark L. Hornick EEPROM (data store) Flash ROM (program store) ROM (none on Atmega32) PROM (none on Atmega32) EPROM (none on Atmega32) 2 Addressing Modes So far, we’ve been loading immediate values into Registers LDI R20, 123 ; load 123 into R20 The operand 123 is an Immediate value This is called Immediate Addressing Note: LDI cannot be used with R0-R15 Note: Only 4 bits are used for dddd LDI rD, N is assembled to: 1110 nnnn dddd nnnn In general, an operand of an instruction may be specified by An Immediate value Direct addressing Indexed addressing Address modes specify how and where the values specified by the operand(s) are located CS-280 Dr. Mark L. Hornick 3 Direct Addressing accesses a 8-bit (byte) value from SRAM data memory at the address specified directly within the instruction Example: LDS R20, 0x60 ; LoaD value at SRAM addr 0x0060 to R20 STS 0x60, R20 ; STore value in R20 to SRAM addr 0x0060 Note data address values are 16-bit since data memory addresses can range from 0x0 - 0xFFFF (0 - 65535) Even though Atmega32 only has 2KB SRAM It may help to keep in mind that 0x60 is the same as 0x0060 Each byte (8 bits) of data memory has a unique address As opposed to each word (2 bytes) of program flash memory having a unique address CS-280 Dr. Mark L. Hornick 4 Memory Map: Data memory Actual SRAM data memory starts at address 0x0060! GP Registers are assigned the first 32 data memory addresses And ends at 0x085F .EQU SRAM_START=0x60 is found in m32def.inc LDS R20, 0x0 loads the value of R0 into R20 (same as MOV R20, R0) IO Registers are assigned the next 64 addresses Add 0x20 to convert an IO memory address to it’s corresponding data memory address STS PORTB+0x20, R20 same as OUT PORTB, R20 2048 (0x800) bytes of SRAM in the Atmega32 CS-280 Dr. Mark L. Hornick 5 Referring to raw memory addresses is not ideal We can explicitly define constant symbols to refer to addresses using the .EQU directive Example: .EQU x1=0x0060 ; define a symbol “x1” LDS R20, x1 ; data load addr is referred to by x1 STS x1, R20 ; data store addr is x1 CS-280 Dr. Mark L. Hornick 6 An even better way to specify addresses is to use labels We defined labels to identify addresses in program memory to be used as jump/branch targets loop: RJMP loop The address assigned to a label is determined automatically by the Assembler Similarly, we can define labels to identify addresses in data memory to be used as load/store targets CS-280 Dr. Mark L. Hornick 7 Using labels to refer to data memory locations: .DSEG ; subsequent directives refer to data segment .ORG SRAM_START ; address where Data Memory starts (0x60) x1: .byte 1 ; reserve 1 byte of SRAM, assign label x1=0x60 x2: .byte 2 ; reserve 2 bytes of SRAM, assign label x2=0x61 x3: .byte 1 ; reserve 1 byte of SRAM, assign label x3=0x63 .CSEG ; switch further directives to code segment .ORG 0x2A ; set addr for start of program instructions LDS R20, x1 ; load value at data addr specified by x1 STS x2, R20 ; store value in R20 to data addr x2 The addresses are assigned automatically by the Assembler The .byte n directive tells the assembler to allocation n bytes Be very careful about using .ORG for addresses < 0x60 CS-280 Dr. Mark L. Hornick 8 The X, Y, and Z Registers The X, Y, and Z 16-bit registers overlap the last six 8-bit registers R26 through R31 CS-280 Dr. Mark L. Hornick 9 Indirect Addressing Accesses a 8-bit (byte) value from SRAM data memory at the address specified indirectly via the 16-bit X, Y, or Z index-registers Example: LD R20, X ; load value at data addr held in X to R20 ST Y, R20 ; store value in R20 to data addr held in Y Note X, Y, Z hold data address values that are 16-bits CS-280 Dr. Mark L. Hornick 10 How do you load an address value into X, Y, or Z? We can’t use a single instruction like LDI But we could potentially use two LDI instructions… .DSEG .ORG x1: .CSEG .ORG LDI LDI LD Because LDI loads values into 8-bit registers Consider X: overlaps R26 and R27 The first 8 bits of X are R26; the second 8 bits are R27 To set X to hold the 16-bit address: 0x60 .byte 1 0x2A R26, LOW(x1) R27, HIGH(x1) R20, X ; subsequent directives refer to data segment ; set SRAM address where label assignments start ; reserve 1 byte of SRAM, assign label x1=0x0060 ; switch further directives to code segment ; set addr for start of program instructions ; load R26 with the low 8 bits of the address (0x0060) ; load R27 with the high 8 bits of the address (0x0060) ; load value at data addr contained in register X LOW() and HIGH() are Assembler functions or macros i.e. functions that are executed by the Assembler during assembly They are NOT functions that execute on the Atmega32 CS-280 Dr. Mark L. Hornick 11 How do you remember that the low 8-bits of X is R26 and the high 8-bits are R27? You don’t have to; m32def.inc helps with some definitions: .DEF XL=R26 .DEF XH=R27 .DSEG .ORG x1: .CSEG .ORG LDI LDI LD ; subsequent directives refer to data segment 0x60 ; set SRAM address where label assignments start .byte 1 ; reserve 1 byte of SRAM, assign label x1=0x0060 ; switch further directives to code segment 0x2A ; set addr for start of program instructions XL, LOW(x1) ; load R26 with the low 8 bits of the addr assigned to x1 XH, HIGH(x1) ; load R27 with the high 8 bits of x1 R20, X ; load value at data addr contained in register X CS-280 Dr. Mark L. Hornick 12 Addresses contained within the X, Y, and Z registers can be automatically indexed via pre- and post-decrement syntax Syntax is somewhat similar to the C++/Java increment/decrement syntax: Ex: int a=3; b=4; a = b++; // assigns b to a and then increments b; result is a=7 a = b--; // assigns b to a and then decrements b; result is a=7 a = ++b; // increments b BEFORE assigning b to a; result is a=8 a = --b; // decrements b before assigning b to a; result is a=6 .DSEG .ORG 0x60 x1: .byte 1 .CSEG .ORG 0x2A LDI XL, LOW(x1) LDI XH, HIGH(x1) LD R20, X+ LD R21, +X LD R22, XLD R21, -X ; subsequent directives refer to data segment ; set SRAM address where label assignments start ; reserve 1 byte of SRAM, assign label x1=0x0060 ; switch further directives to code segment ; set addr for start of program instructions ; load R26 with the low 8 bits of the addr assigned to x1 ; load R27 with the high 8 bits of x1 ; load value from addr in register X; then increment X (to 0x0061) ; incr X (to 0x0062), then load value from addr in register X ; load value from addr in register X; then decrement X (to 0x0061) ; decr X (to 0x0060), then load value from addr in register X CS-280 Dr. Mark L. Hornick 13 An offset from the address contained in an index register can be specified with the LDD instruction .EQU offset=10 .DSEG .ORG 0x60 x1: .byte 1 .CSEG .ORG 0x2A LDI XL, LOW(x1) LDI XH, HIGH(x1) LDD R20, X+2 LDD R20, X+offset ; subsequent directives refer to data segment ; set SRAM address where label assignments start ; reserve 1 byte of SRAM, assign label x1=0x0060 ; switch further directives to code segment ; set addr for start of program instructions ; load R26 with the low 8 bits of the addr assigned to x1 ; load R27 with the high 8 bits of x1 ; load value from offset addr (X+2 = 0x62); does NOT increment X ; load value from offset addr (X+10=0x6A); does NOT increment X The maximum value that an index register may be offset in this way is 64 CS-280 Dr. Mark L. Hornick 14 Note that instructions such as INC and ADD cannot use X, Y, or Z as operands INC ADD LDI X ; illegal X, Y ; illegal Z, 0x1234 ; illegal However, the following is a valid Atmega32 instruction: ADIW r31:r30, 0x1 ; add immediate value (to Z) The value may be 0-63 (decimal) CS-280 Dr. Mark L. Hornick 15 FYI: There are a number of Assembler functions besides LOW() and HIGH() LOW(0xabcd) HIGH(0xabcd) BYTE1(0xabcd) BYTE2(0xabcd) BYTE3(0x1234abcd) BYTE4(0x1234abcd) LWRD(0x1234abcd) HWRD(0x1234abcd) returns the low byte (0xcd) of an expression returns the second (0xab) byte of an expression is the same function as LOW is the same function as HIGH returns the third byte (0x34) of an expression returns the fourth byte (0x12) of an expression returns bits 0-15 of an expression (0xabcd) returns bits 16-31 of an expression (0x1234) CS-280 Dr. Mark L. Hornick 16 The Z Register can also be used to hold a jump target address Syntax: IJMP ; jump indirectly to the address contained in Z The Z register is implied and not a required operand Z can hold any address in the 0-65535 Similar in capacity to JMP CS-280 Dr. Mark L. Hornick 17
© Copyright 2026 Paperzz