Loads and Stores: The Instructions

Một phần của tài liệu ARM assembly language (Trang 109 - 114)

Chapter 5 Loads, Stores, and Addressing

5.3 Loads and Stores: The Instructions

Now that we have some idea of how memory is described in the system, the next step is to consider getting data out of memory and into a register, and vice versa. Recall that RISC architectures are considered to be load/store architectures, meaning that data in external memory must be brought into the processor using an instruction.

Operations that take a value in memory, multiply it by a coefficient, add it to another TABLE 5.1 (continued)

Memory Map of the Tiva TM4C123GH6ZRB

Start End Description

For Details, See Page…a

0x4006.4000 0x4006.4FFF GPIO Port N (AHB aperture) 675

0x4006.5000 0x4006.5FFF GPIO Port P (AHB aperture) 675

0x4006.6000 0x4006.6FFF GPIO Port Q (AHB aperture) 675

0x4006.7000 0x400A.EFFF Reserved —

0x400A.F000 0x400A.FFFF EEPROM and Key Locker 571

0x400B.0000 0x400B.FFFF Reserved —

0x400C.0000 0x400C.0FFF I2C 4 1044

0x400C.1000 0x400C.1FFF I2C 5 1044

0x400C.2000 0x400F.8FFF Reserved —

0x400F.9000 0x400F.9FFF System Exception Module 497

0x400F.A000 0x400F.BFFF Reserved —

0x400F.C000 0x400F.CFFF Hibernation Module 518

0x400F.D000 0x400F.DFFF Flash memory control 553

0x400F.E000 0x400F.EFFF System control 237

0x400F.F000 0x400F.FFFF àDMA 618

0x4010.0000 0x41FF.FFFF Reserved —

0x4200.0000 0x43FF.FFFF Bit-banded alias of 0x4000.0000 through 0x400F.FFFF

0x4400.0000 0xDFFF.FFFF Reserved —

Private Peripheral Bus

0xE000.0000 0xE000.0FFF Instrumentation Trace Macrocell (ITM) 70 0xE000.1000 0xE000.1FFF Data Watchpoint and Trace (DWT) 70 0xE000.2000 0xE000.2FFF Flash Patch and Breakpoint (FPS) 70

0xE000.3000 0xE000.DFFF Reserved —

0xE000.E000 0xE000.EFFF Cortex-M4F Peripherals (SysTick, NVIC, MPU, FPU and SCB)

134

0xE000.F000 0xE003.FFFF Reserved —

0xE004.0000 0xE004.0FFF Trace Port Interface Unit (TPIU) 71 0xE004.1000 0xE004.1FFF Embedded Trace Macrocell (ETM) 70

0xE004.2000 0xFFFF.FFFF Reserved —

a See Tiva TM4C123GH6ZRB Microcontroller Data Sheet.

register, and then store the result back to memory with only a single instruction do not exist. For hardware designers, this is considered to be a very good thing, since some older architectures had so many options and modes for loading and storing data that it became nearly impossible to build the processors without introducing errors in the logic. Without listing every combination, Table 5.2 describes the most common instructions for dedicated load and store operations in the version 4T and version 7-M instruction sets.

Load instructions take a single value from memory and write it to a general- purpose register. Store instructions read a value from a general-purpose register and store it to memory. Load and store instructions have a single instruction format:

LDR|STR{<size>}{<cond>} <Rd>, <addressing_mode>

where <size> is an optional size such as byte or halfword (word is the default size),

<cond> is an optional condition to be discussed in Chapter 8, and <Rd> is the source or destination register. Most registers can be used for both load and store instruc- tions; however, there are register restrictions in the v7-M instructions, and for ver- sion 4T instructions, loads to register r15 (the PC) must be used with caution, as this could result in changing the flow of instruction execution. The addressing modes allowed are actually quite flexible, as we’ll see in the next section, and they have two things in common: a base register and an (optional) offset. For example, the instruction

LDR r9, [r12, r8, LSL #2]

would have a base register of r12 and an offset value created by shifting register r8 left by two bits. We’ll get to the details of shift operations in Chapter 7, but for now just recognize LSL as a logical shift left by a certain number of bits. The offset is added to the base register to create the effective address for the load in this case.

It may be helpful at this point to introduce some nomenclature for the address—

the term effective address is often used to describe the final address created from values in the various registers, with offsets and/or shifts. For example, in the instruc- tion above, if the base register r12 contained the value 0x4000 and we added register r8, the offset, which contained 0x20, to it, we would have an effective address of 0x4080 (remember the offset is shifted). This is the address used to access memory.

TABLE 5.2

Most Often Used Load/Store Instructions

Loads Stores Size and Type

LDR STR Word (32 bits)

LDRB STRB Byte (8 bits)

LDRH STRH Halfword (16 bits)

LDRSB Signed byte

LDRSH Signed halfword

LDM STM Multiple words

A shorthand notation for this is ea<operands>, so if we said ea<r12 + r8*4>, the effective address is the value obtained from summing the contents of register r12 and 4 times the contents of register r8.

Sifting through all of the options for loads and stores, there are basically two main types of addressing modes available with variations, both of which are covered in the next section:

• Pre-indexed addressing

• Post-indexed addressing

If you allow for the fact that a simple load such as LDR r2, [r3]

can be viewed as special case of pre-indexed addressing with a zero offset, then loads and stores for the ARM7TDMI and Cortex-M4 processors take the form of an instruc- tion with one of the two indexing schemes. Referring back to Table 5.2, the first three types of instructions simply transfer a word, halfword, or byte to memory from a reg- ister, or from memory to a register. For halfword loads, the data is placed in the least significant halfword (bits [15:0]) of the register with zeros in the upper 16 bits. For halfword stores, the data is taken from the least significant halfword. For byte loads, the data is placed in the least significant byte (bits [7:0]) of the register with zeros in the upper 24 bits. For byte stores, the data is taken from the least significant byte.

EXAMPLE 5.1 Consider the instruction

LDRH r11, [r0]; load a halfword into r11

Assuming the address in register r0 is 0x8000, before and after the instruction is executed, the data appears as follows:

Memory Address

r11 before load 0xEE 0x8000

0x12345678 0xFF 0x8001

r11 after load 0x90 0x8002

0x0000FFEE 0xA7 0x8003

Notice that 0xEE, the least significant byte at address 0x8000, is moved to the least significant byte in register r11, the second least significant byte, 0xFF, is moved to second least significant byte of register r11, etc. We’ll have much more to say about this ordering shortly.

Signed halfword and signed byte load instructions deserve a little more explana- tion. The operation itself is quite easy—a byte or a halfword is read from memory, sign extended to 32 bits, then stored in a register. Here the programmer is specifically branding the data as signed data.

EXAMPLE 5.2 The instruction

LDRSH r11, [r0]; load signed halfword into r11

would produce the following scenario, again assuming register r0 contains the address 0x8000:

Memory Address

r11 before load 0xEE 0x8000

0x12345678 0x8C 0x8001

r11 after load 0x90 0x8002

0xFFFF8CEE 0xA7 0x8003

As in Example 5.1, the two bytes from memory are moved into register r11, except the most significant bit of the value at address 0x8001, 0x8C, is set, meaning that in a two’s complement representation, this is a negative number.

Therefore, the sign bit should be extended, which produces the value 0xFFFF8CEE in register r11.

You may not have noticed the absence of signed stores of halfwords or bytes into memory. After a little thinking, you might come to the conclusion that data stored to memory never needs to be sign extended. Computers simply treat data as a sequence of bit patterns and must be told how to interpret numbers. The value 0xEE could be a small, positive number, or it could be an 8-bit, two’s complement representa- tion of the number -18. The LDRSB and LDRSH instructions provide a way for the programmer to tell the machine that we are treating the values read from memory as signed numbers. This subject will be brought up again in Chapter 7 when we deal with fractional notations.

There are some very minor differences in the two broad classes of loads and stores, for both the ARM7TDMI and the Cortex-M4. For example, those instruc- tions transferring words and unsigned bytes have more addressing mode options than instructions transferring halfwords and signed bytes, as shown in Table 5.3 and Table 5.4. These are not critical to understanding the instructions, so we’ll proceed to see how they are used first.

TABLE 5.3

Addressing Options for Loads and Stores on the ARM7TDMI

Imm

Offset Reg Offset

Scaled Reg

Offset Examples

Word 12 bits Supported Supported LDR r0, [r8, r2, LSL #28]

Unsigned byte LDRB r4, [r8, #0xF1A]

Halfword 8 bits Supported Not supported STRH r9, [r10, #0xF4]

Signed halfword LDRSB r9, [r2, r1]

Signed byte

EXAMPLE 5.3

Storing data to memory requires only an address. If the value 0xFEEDBABE is held in register r3, and we wanted to store it to address 0x8000, a simple STR instruc- tion would suffice.

STR r3, [r8]; store data to 0x8000 The registers and memory would appear as:

Memory Address

r8 before store 0xBE 0x8000

0x00008000 0xBA 0x8001

r8 after store 0xED 0x8002

0x00008000 0xFE 0x8003

However, we can perform a store operation and also increment our address auto- matically for further stores by using a post-increment addressing mode:

STR r3, [r8], #4; store data to 0x8000 The registers and memory would appear as:

Memory Address

r8 before store 0xBE 0x8000

0x00008000 0xBA 0x8001

r8 after store 0xED 0x8002

0x00008004 0xFE 0x8003

Other examples of single-operand loads and stores are below. We’ll study the two types of addressing and their uses in the next sections.

TABLE 5.4

Addressing Options for Loads and Stores on the Cortex-M4

Imm Offset Reg Offset

Scaled Reg

Offset Examples

Unsigned byte Signed byte

Depending on instruction, index can range from −255 to 4095a

LDRSB r3, [r6, r7, LSL #2]

LDRSH r10, [r2, #0x42]

STRH r3, [r6, r8]

Halfword Supported Supported

Signed halfword Word

a Due to the way the instructions are encoded, there are actually different instructions for LDRSB r3, [r4, #0] and LDRSB r3, [r4, #-0]! Consult the v7-M ARM for other dubious behavior.

LDR r5, [r3] ; load r5 with data from ea < r3 >

STRB r0, [r9] ; store data in r0 to ea < r9 >

STR r3, [r0, r5, LSL #3] ; store data in r3 to ea < r0 + (r5<<3) >

LDR r1, [r0, #4]! ; load r1 from ea < r0+4 > ,r0 = r0+4 STRB r7, [r6, #-1]! ; store byte to ea < r6-1 > ,r6 = r6-1 LDR r3, [r9], #4 ; load r3 from ea < r9 > ,r9 = r9 + 4 STR r2, [r5], #8 ; store word to ea < r5 > ,r5 = r5+8

Load Multiple instructions load a subset (or possibly all) of the general-purpose registers from memory. Store Multiple instructions store a subset (or possibly all) of the general-purpose registers to memory. Because Load and Store Multiple instruc- tions are used more for stack operations, we’ll come back to these in Chapter 13, where we discuss parameter passing and stacks in detail. Additionally, the Cortex-M4 can load and store two words using a single instruction, but for now, we’ll concen- trate on the basic loads and stores.

Một phần của tài liệu ARM assembly language (Trang 109 - 114)

Tải bản đầy đủ (PDF)

(448 trang)