Load-Store Worksheet

As you work through the following questions, please have at hand your reference pages provided along with Midterm 1.

Computers at the most fundamental level manipulate data. This may be as simple as transferring the data from one place to another or executing an add operation. In a RISC architecture the data to be manipulated is contained in one or more general purpose registers within the central processing unit (CPU) of the microcontroller. These registers go by a number of names including temporary and scratch-pad. How many general purpose registers does our AVR processor have and how many bits wide is each?

Answer #1: The AVR processor has 32 8-bit registers.

Loading Data

Another way of saying this is that all operations on the data are register-register. To get the data into the CPU we will need to "Load" it from somewhere. That somewhere can be from SRAM Data memory, Flash Program memory, an Input/Output register, or Extended Input/Output register.


I want to multiply a number in one of our registers by the constant 3310. Where would you expect to find the number 3310?
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory

Answer #2: Constants are encoded with the program instruction, so the answer is Flash Program memory.

Looking at the "Register Summary" you can see that each of our three general purpose I/O ports (B, C and D) are defined by three registers (PORT, DD, and PIN). Notice that all of these registers have two addresses. The first number in the "Address" column, is the I/O address, the second (in parenthesis) is its duplicate address within the data memory address space. For now we will simply use the I/O address.

I want to read a temperature sensor, whose digital value is wired to one of our three general purpose digital I/O Ports.  In what "address space" can you find this data?
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory
Hint: Look at the "Register Summary" pages in the handout.

Answer #3: All of our general purpose digital I/O ports are located in the I/O register address space. Specifically, I/O address 0x00 to 0x3F.

When the AVR processor was originally designed, the architects assumed that 64 I/O addresses (0x00 to 0x3F) would be sufficient for accessing all the peripheral devices co-located with the processor. When Atmel adopted the AVR processor as its core for the ATmega line of microcontrollers, they quickly discovered that they would need more than 64 I/O addresses. To accommodate the additional space they mapped these new "Extended" I/O registers into the SRAM address space of the ATmega and named it the Extended I/O address space. Looking at the register summary you can find these extended I/O registers starting at memory location 0x60 to 0xFF. This means that our actual SRAM data memory begins at address 0x0100.

With respect to the "Register Summary" table where would you find the registers used by the ATmega Analog-to-Digital Converter (ADC Data Registers).
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory

Answer #4: The result of an analog-to-digital conversion are located in registers ADC Data Register Low byte and ADC Data Register High byte. These registers are located at Extended I/O address 0x78 and 0x79 respectively.

I want to load a variable named X, where would you expect to find this variable?
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory

Answer #5: Variables which are located in SRAM data memory.

Where would I find an Array?
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory

Answer #6: An array is simply an indexed set of variables, so they would be located in SRAM data memory.

I want to add an offset of 10010 to each value in an array. Where would you expect to find the number 10010 in my program?
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory

Answer #7: Because I know I always want to add 100 - this is a constant that I would save in Flash Program memory. This number would be encoded with the instruction.

I want to load the value of the Watchdog Timer Control Register (WDTCSR). Where can I find this register?
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory

Answer #8: Looking at the Register Summary, you will find WDTCSR in the Extended I/O address space of the ATmega. In this example, extended I/O address 0x60.

When the AVR processor executes an arithmetic instruction, like add, we often want to know more than simply the answer. For example; is the answer correct? Is the answer zero? These are some of the answers located in the Status Register (SREG). Where would you find this data?
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory

Answer #9: The status register is located in the I/O address space of the AVR processor at location 0x3F. Once again, if we are presented with both an I/O address 0x3F and a memory address (0x5F) we will classify the register as being within the I/O address space of the processor.

I always want to multiply a variable by ninety seven (9710). Where would you find the number 9710?
a) SRAM Data b) I/O Register c) Extended I/O Register d) Flash Program Memory

Answer #10: I always want to multiply by 9710, so the number would be encoded with the load instruction. Consequently, the data would be saved in Flash Program memory.

Once we know where the data is located we also know the addressing mode. In fact, "addressing mode" is just technical speak for saying where is the data?

If the data is located in Flash Program Memory you would use the immediate addressing mode to load it into one of our general purpose registers. Specifically, you would use the "load immediate" ldi  Rd, K  assembly instruction. Where ldi is a short hand way "mnemonic" of saying LoaD Immediate. The source operand is constant K (upper case K) and destination operand address Rd is the register we want to contain the constant after the instruction executes. The word "operand" is again just technical speak and based on the context may be read as the "address of the data" or simply the "data" itself. For our load immediate instruction would our constant K operand be read as "the address of the data" or simply as "data"?

Answer #11: The constant is encoded with the instruction so the operand is the "data."

If the data is located in SRAM data memory, you would use the direct addressing mode. You would also use the direct addressing mode if the data is located in the extended I/O address space. There are other addressing modes that can access, these locations within the memory address space; However, we will leave them for now. The instruction you use to load data "directly" from SRAM data memory is lds  Rd, k.  Where lds is a short hand way of saying LoaD from SRAM data memory. The source operand is the address k (lower case K) in data memory containing the data, and destination operand addres Rd is the register we want to contain the data after the instruction executes. For our load from SRAM data memory instruction would our constant k operand be read as "the address of the data" or simply as "data"?

Answer #12: The source operand field encoded with the instruction contains the "address of the data."

You might be surprised to learn that you use the same instruction to access SRAM data and Extended I/O registers. The only thing that is different is the address. What assembly instruction would I use to load the contents of the low order byte of the ADC register (ADCL) into general purpose register r20, and at what Extended I/O address would I find this ADC register?

Answer #13: You would use the lds r20, ADCL assembly instruction, where the assembler would replace ADCL with the address 0x78.
 
If the data is located in our I/O address space, not the extended I/O address space, you would again use the direct addressing mode; however, this time you would use the "in" instruction. The "in" instruction is the only instruction used to directly load data from the I/O address space. Consequently, if you know the data is located in the I/O address space, you know the addressing mode (direct) and the instruction to use.

What assembly instruction would I use to read the contents of PORT D's data direction register DDRD into general purpose register r12?

Answer #14: Looking at the Register Summary, we find register DDRD is located at address 0x0A, so we would use the in instruction.
in  r12, DDRD  // Where the assembler would replace DDRD with the I/O address 0x0A.

What assembly instruction would I use to load the contents of variable A into general purpose register r20, and within what SRAM address range would variable A be located? Hint: the top of SRAM data memory is located at address 0x8FF.

Answer #15: You would use the lds   r20, A assembly instruction, where the assembler would replace A with the SRAM address assigned to variable A by the assembler. Because the assembler will assign variable A when the program is assembled, we only know that it will be somewhere in our SRAM memory; address space 0x0100 to 0x08FF. See Figure 7-2 Program Memory Map ATmega88PA, ATmega168PA, and ATmega328P to see why the top of memory is 0x08FF.

How much real SRAM data memory does the ATmega328P contain?

Answer #16: SRAM memory is located from address 0x8FF down to 0x0100. If our memory had a base address of 0x0000 then the last address would be o0x08FF - 0x0100 = 0x07FF. Which corrsponds to a 2 K byte (where K = 210 = 1024) or 204810 byte SRAM memory address space.

What assembly instruction would I use to load constant 0x80 into general purpose register r24?

Answer #17: ldi  r24, 0x80

As mentioned earlier, constants are encoded with the instruction itself. Because immediate instruction are encoded into one 16-bit Flash Program word there are some restrictions. First, the constant must fit within a byte (8-bits). If you are working with a number; unsigned numbers must be between 0 to 255 and signed numbers between -128 to 127. Second, to fit the 8 bit constant into the 16-bit instruction, Atmel had to limit the registers which could be used to r16 to r31. How can you work with a 16-bit constant? For example; how would you load the 16-bit constant 123416 into the r17:r16 register pair?

Answer #18: Break the constant into a high-byte and a low-byte, assigning each to its own general purpose register. For example;
ldi  r17, 0x12
ldi  r16, 0x34

Looking at the Instruction Set Summary and specifically Data Transfer Instructions, how could you load constant 0x33 into register r8?

Answer #19: Temporarily Load the constant into one of the registers from r16 to r31 and then use the move instruction mov to copu it into the desired register. For example;
ldi  r16, 0x33
mov  r8, r16

What assembly instruction would I use to move Status Register SREG into general purpose register r27?

Answer #20: Looking at the Register Summary, we find that SREG is located at address 0x3F, so we would use the in instruction.
in    r27, SREG  // Where the assembler would replace SREG with the I/O address 0x3F.

What assembly instruction would I use to read the PINs on PORT B into general purpose register r12?

Answer #21: Looking at the Register Summary, we find that PINB is located at address 0x03, so we would use the in instruction.
in    r12, PINB  // Where the assembler would replace PINB with the I/O address 0x03.

Register - Register Instructions

After we have loaded the date into the general purpose registers of the AVR processor, technically known as the register file, we manipulate the data as required by the problem to be solved. This often is the easiest part of the problem within the context of a load-store architecture. This is because, RISC machines offer a wide selection of register-register instructions for solving most any problem. In addition, the names of the instructions typically provide you enough information to know which one(s) to employ to solve your problem.  Later in the semester we will solve more complex problems; but, for now lets look at a few simple examples.

Variables A and B have been loaded into register r2 and r3 respectively. How would you add these two numbers together putting the sum into register r2.

Answer #22: add  r2, r3  
 
Some modern RISC computers have register-register instructions containing three operand fields, with the third operand field providing the processor with the address of where the answer is to be saved. Our RISC architecture only supports up to two operand fields. This means for arithmetic or logical operations requiring two operands (A plus B), the destination operand also provides one of the numbers to be operated on. Consequently, all instructions of this type destroy one of the source registers (by writing the result to it).  In the problem above the source/destination register was r2. How can you perform an arithmetic or logincal operation without destroying the value in one of your source registers?

Answer #23: Use the mov instruction to make a copy of one of your variables.


Write the code needed to add r2 and r3 placing the answer in register r4.


Answer #24:

mov  r4, r2

add  r4, r3


Write the code needed to take the logical or of register r2 and r3 placing the answer in register r4.

Answer #25:

mov  r4, r2

or   r4, r3

Write the code needed to take the logical and of register r2 and r3 placing the answer in register r2.


Answer #26:

and  r2, r3


As you can see often it is simply a matter of looking up the required arithmetic or logical instruction in the "Instruction Set Summary" and plugging it into your program.

We have a 16-bit unsigned number. The most significant 8-bits are located in register r5 and the least significant 8-bits in register r4. Another way of saying the same thing is that the register pair r5:r4 contains a 16-bit unsigned number. Given that the register pair r7:r6 holds a second 16-bit number, write the code needed to add these two 16-bit numbers together placing the result back into the register pair r5:r4. Hint: do not forget the carry from the least significant byte.

Answer #27:

add  r4, r6

adc  r5, r7

Storing the Answer

To be continued...