Arm Assembly languages include LDR commands, LDR commands, and ADR pseudo commands. They can all use label expressions as operands. The differences are as follows:
The difference between LDR commands and ADR and LDR pseudo commands: LDR commands are load-store commands used to read the value in the label address. ADR and LDR pseudo commands are used to obtain the label address.
What is the difference between ADR and LDR pseudoinstructions: ADR is the address for obtaining the relative PC, which is related to the current running position of the program. It is a small range of addresses for reading pseudoinstructions; LDR is the absolute address for obtaining, the absolute address is determined during the link process. It has nothing to do with the current running position of the program. It is a pseudo command for reading a large range of addresses.
Next we will analyze a piece of code and the corresponding disassembly to explain their differences.
LDR r0, _ start
ADR r0, _ start
LDR r0, = _ start
_ Start:
B _ start
Set R0 to 0x30000000 during compilation. The following is the result of disassembly:
0x00000000: e59f0004 LDR r0, [PC, #4]; 0xc
0x00000004: e28f0000 add r0, PC, #0; 0x0
0x00000008: e59f0000 LDR r0, [PC, #0]; 0x10
0x0000000c: eafffffe B 0xc
0x00000010: 300366c andcc r0, R0, IP
1. LDR r0, _ start
This is an instruction to load the data stored at this address from the memory address _ start.
Here _ start is a label (a relative program expression). The assembler calculates the offset relative to the PC and generates the command relative to the pre-index of the PC: LDR
R0, [PC, #4]. After the command is executed, R0 = 0 xeafffffe (Calculation Method: R0
= [PC (0x00000000 + 8) + 4] = [0x0000000c] = 0 xeafffffe ).
LDR r0, _ start is the value of the address where the current PC is located based on _ start. Therefore, the data value can be obtained without changing the relative position of the _ start label.
2. ADR r0, _ start
This is a pseudo command, which is always changed into an instruction by the assembler. The assembler tries to generate a single add or sub command to load the address. If the address cannot be constructed in a command, an error is generated and the Assembly fails.
Here we get the address number _ start to R0. Because the address is relative to the program, the generated code of ADR depends on the location. In this example, It is compiled into: add
R0, PC, #0. Therefore, the code can be moved without changing the relative position of the label.
If this code runs at 0x30000000, then the ADR
R0, _ start get R0 = 0x30020.c; if it is run at address 0, it is 0x0000000c.
This can be used to determine where the program is running. The relocate code in U-boot is to use ADR to implement whether the current program is in Ram or flash.
3. LDR r0, = _ start
This is a pseudo command, and _ start is an absolute address (that is, the running address ). This absolute address is determined during the link. It occupies 2 32bit space, one is the instruction, and the other is the absolute address for storing _ start in the text pool. In this example, the command is LDR.
R0, [PC, #0], corresponding address and value in the text pool: 0x00000010: 30020.c. Therefore, after the pseudo command is executed, the R0 value is 0x30020.c. Therefore, no matter where the code runs in the future, the result is R0 = 0x30020.c.
Because LDR R0 and = _ start obtain the absolute address of _ start, this code can be moved without changing the absolute position of the _ start label, for example, you can use the register PC to implement absolute transfer in the program.