|
|
|
|
Applying this principle is the most challenging part in assembler programming because:
|
It's very easy to make programming mistakes in accessing data in memory when you write assembler programs...
|
Notice that moving (= copying) instruction only need to know how many bytes it needs to move (= copy) to perform correctly.
So you can use the same move instruction on data types that contains the same number of bytes
|
The Load Register instruction has (too) many different formats, and we will only learn 3 formats to save time for other more important material.
The ARM processor has 3 different load register instructions:
ldr (load register (full)): moves 4 (consecutive) bytes from memory into a register ldrsh (load register half): moves 2 (consecutive) bytes from memory into a register and sign extends the 16 bits (= 2 bytes) representation into a 32 bits (int) representation ldrsb (load register byte): moves 1 byte from memory into a register and sign extends the 8 bits representation into a 32 bits (int) representation |
I will now present the most basic format of the load register instruction that will be used (discussed soon) to move values stored in simple variables into a register in the CPU.
Syntax and meaning of the basic form of the load register instruction is:
Syntax Meaning of the instruction ---------------- -------------------------------------------------- ldr rN, [rM] Load 4 bytes from memory at the address given in rM into the (destination) register rN The 4 bytes are stored in the register as follows: ldrsh rN, [rM] Load 2 bytes from memory at the address given in rM into the (destination) register rN AND fill the left half of register with the sign bit The 2 bytes are stored at the right and then sign extended to 32 bits: ldrsb rN, [rM] Load 1 byte from memory at the address given in rM into the (destination) register rN AND fill the left 3/4 of register with the sign bit The byte is stored at the right and then sign extended to 32 bits: |
The reason that we sign-extend a byte and a short is obvious:
|
Example:
|
|
Note:
|
1. Move the address of the memory variable into a (free) register rX 2. Then use: ldr destreg, [rX] for an int/float typed variable ldrsh destreg, [rX] for a short typed variable ldrsb destreg, [rX] for a byte typed variable |
.data i: .4byte 444444 // int typed variable s: .2byte 2222 // short typed variable b: .byte 111 // byte typed variable |
The following instructions will move the int typed (4 bytes) in variable i into the register r1:
// Move i into r1 movw r0, #:lower16:i // Moves the address of memory movt r0, #:upper16:i // variable i into register r0 ldr r1,[r0] // Move int representation in var into r1 |
The following instructions will move the short typed (2 bytes) in variable s into the register r2:
// Move s into r2 movw r0, #:lower16:s // Moves the address of memory movt r0, #:upper16:s // variable s into register r0 ldrsh r2,[r0] // Move short representation in var into r2 // and sign-extend into an int representation |
And the following instructions will move the byte typed (1 byte) in variable b into the register r3:
// Move b into r3 movw r0, #:lower16:b // Moves the address of memory movt r0, #:upper16:b // variable b into register r0 ldrsb r3,[r0] // Move byte representation in var into r3 // and sign-extend into an int representation |
How to run the program:
|