ARM Programming Advanced 1-ARM Assembly Pseudo Instructions

Publisher:数字驿站Latest update time:2015-09-23 Source: eefocusKeywords:ARM Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
So far, we have the ability to write relatively complex ARM assembly programs, but to write more complex and practical programs, we have to master the pseudo-instructions of ARM assembly. Do not confuse assembly pseudo-operations (directives) with assembly pseudo-instructions (pseudo-instructions). Directives will not be compiled into machine instructions by the compiler, but pseudo-instructions will. The difference between pseudo-instructions and instructions is that one instruction corresponds to one machine instruction, and the compiler will compile one pseudo-instruction into one or more machine instructions.

There are 4 ARM assembly pseudo instructions: ldr, adr, adrl, nop

1.ldr

First, let's answer the question in the article "Basic Addressing Modes and Basic Instructions". "What should we do if we need an instruction like mov r0, #10000? (The constant 10000 cannot be represented in the lower 12 bits of the 32-bit machine instruction)". When you compile, the error "Error: All70E" will appear, as shown below.

image

In fact, this problem is easy to solve. We just need to replace mov r0, #10000 with ldr r0, =10000. Why is this possible? Because the ldr r0, =10000 here is not the ldr instruction we have learned, but a pseudo-instruction. The compiler will replace this pseudo-instruction with:

ldr r0, [pc, #-4]
DCD 10000

The integer 10000 is stored in the memory space allocated by DCD. This memory space is called the literal pool. Since the entire program is compiled by the compiler (including the allocation of the literal pool), it is obvious that the compiler knows the offset between the address of the ldr instruction in memory and the location of the literal pool in memory. Therefore, the compiler can correctly use the ldr instruction with relative addressing based on pc to load the number in the literal pool into register r0. It can be seen that the compiler's processing of the pseudo-instruction ldr r0, =10000 is actually:

When assembling the source program, the LDR pseudo-instruction is replaced by the compiler with a suitable instruction and a literal pool for storing constants. The assembler puts the constant into the literal pool and uses a program-relative offset LDR instruction to read the constant from the literal pool. 

Since 4 bytes can store any int type integer, the constant can be any int type integer, and is no longer restricted by the 12-bit limit. Of course, the constant is stored in memory instead of in the 32-bit code of the machine instruction.

Additional Notes:

a) The value in ldr r0, [pc, #-4] is -4 instead of +4 because of the pipeline (see the article "The Effect of Pipeline on PC Value"). I will not explain this effect of pipeline in the future.

b) The offset from the instruction location to the literal pool must be less than 4KB

c) From a grammatical point of view, compared with the LDR of the ARM instruction, the parameter of the pseudo-instruction LDR has an "=" sign but no "#" sign.

d) If the constant can be represented by 12 bits, for example: ldr r0, =0x100, then the compiler will use the MOV (or MVN) instruction to replace the LDR pseudo-instruction, for example: mov r0, #0x100, instead of using the ldr instruction + literal pool method.

In addition to the form of ldr register, = constant, the form of ldr register, = label is also often used. Below I will explain this form of ldr pseudo-instruction.

image

As can be seen from the figure above: the function of the pseudo instruction ldr pc, =InitStack is to assign the address represented by the label InitStack to pc. This will cause us to have several questions:

a) Why not use bl InitStack but ldr pc, =InitStack?

This is because the jump range of the bl instruction is plus or minus 32M, and the location represented by InitStack may be more than 32M away from ldr pc, =InitStack, and bl can do nothing at this time. It seems to be very shocking that there is such a large jump range program (which seems to mean that the size of the compiled binary executable file will operate 32M). In fact: it is almost impossible for an executable program with a size of more than 32M to appear, but even a small binary program may have a large jump range (more than 32M), which is almost inevitable in the bootloader program. [page]

b) How does the compiler determine that the address represented by InitStack is 0x64?

The compiler knows that the offset of the instruction MOV R0, LR relative to the first instruction of the entire program is 0x64; at the same time, it also knows that the future running address of the program in memory is 0x0, so the compiler can determine that the address represented by InitStack is 0x64+0x0=0x64 when compiling (not when the program is running). So how does the compiler know "the future running address of the program in memory"? In fact, this "future running address of the program in memory" is usually called "the expected running address of the program", or "running address" for short, and I will call it that in the future. It is actually told to the compiler by the programmer before compiling the program.

Untitled-1

c) If the program does not run at its running address in the future, it is obvious that the program will have problems. How to solve it?

The reason for the problem is obviously due to the absolute address used by the ldr pseudo-instruction. Therefore, the solution is to use relative addresses for relative addressing. This requires the use of another pseudo-instruction adr that we will introduce below.

2. ADR

The function of the ADR pseudo-instruction is the same as that of the LDR pseudo-instruction, both of which assign the address represented by the label to the register, but the implementation mechanisms of the two are completely different: ldr uses absolute address, and adr uses relative address.

The ADR pseudo-instruction reads the address value based on the PC relative offset into the register. When assembling the source program, the ADR pseudo-instruction is replaced by a suitable instruction by the compiler. Usually, the compiler uses an ADD instruction or a SUB instruction to implement the function of the ADR pseudo-instruction.

image

Obviously, since ADR R0, Delay is replaced by ADD r0, pc, #0x3c, and it is calculated relative to the address of the current instruction (the value of pc), there will be no problem even if the program does not actually run at the running address in the future.

Of course, there are 2 more problems here:

a) Since adr and ldr perform similar functions, and adr can avoid the problem of absolute address, what is the use of the ldr pseudo-instruction?

This is mainly because the adr pseudo-instruction requires that the label and the adr pseudo-instruction must be in the same segment (for the concept of segments, see the article "ARM Assembly Pseudo-Operation"), while the ldr pseudo-instruction does not have such a requirement.

b) The constant 0x3c in add r0, pc, #0x3c is an immediate value placed in the 12-bit machine instruction. This immediate value may not be represented by 12 bits. In this case, the compilation will produce an error. What should I do if this happens?

Use the pseudo instruction adrl described below

3.adrl

When assembling the source program, the ADRL pseudo-instruction is replaced by two appropriate instructions by the compiler. Its essence is: split the offset immediate value (which may not be represented by 12 bits) into two immediate values ​​that can be represented by 12 bits, and then replace the adrl pseudo-instruction with two add (or sub) instructions.

image

Of course, you may ask, what if the immediate value is very special and cannot be split into two immediate values ​​that can be represented by 12 bits (that is, it needs to be split into three or even more numbers), then what should we do? I will not answer this question here, but you have to remember one sentence, if the machine is smart enough to do everything, you as a programmer will be unemployed! Haha!

4. nop

NOP means no operation, which means the CPU does not do anything. It is important to understand that once the CPU is powered on, it will never stop running. There is no way that an instruction can make the CPU do nothing. Therefore, this pseudo instruction will be replaced by the "MOV R0, R0" instruction during assembly.

NOP is mainly used for short-delay operations. I would like to say a few more words about this. Unlike application programs, assemblers are usually used to control hardware. For example, you need to use an assembler to require a piece of hardware to perform a certain operation (for example, initializing nandflash), and the subsequent operation can only be performed after the operation is completed. However, it takes a while for the hardware to complete the operation after receiving the command (this time is very short, but it is longer for the CPU, usually requiring several instruction cycles). At this time, the programmer must delay the instruction that issues the command and the subsequent operation. The usual practice is to add several NOP pseudo-operations.

Appendix: 4 forms of ldr instruction and ldr pseudo-instruction (these 4 forms are extremely confusing to beginners, so they are listed in this collection)

ldr r0, [r1] Instruction, load the contents of the memory into r0
ldr r0, label Instruction, load the content stored at the memory address represented by label into r0
ldr r0, =10000 Pseudo instruction, assign the constant 10000 to r0 (implemented by ldr instruction + literal pool)
ldr r0, =lable Pseudo instruction, assign the memory address represented by label to r0

Keywords:ARM Reference address:ARM Programming Advanced 1-ARM Assembly Pseudo Instructions

Previous article:ARM Assembly Programming Basics VI - Other Addressing Modes and Other Instructions
Next article:STM32 PWM input mode

Recommended ReadingLatest update time:2024-11-16 13:48

Constants in ARM microprocessors
When I was studying the constants in the ARM microprocessor, I was always confused. After checking it online, I finally figured it out and wrote it down first. The original words in the book are: "A constant is an 8-bit constant obtained by circularly shifting right by an even number of bits (0, 2, 4, 8, ..., 26, 28,
[Microcontroller]
About CPSR_cxsf in ARM
msr cpsr_cxsf,r1               ; Here cxsf represents the 4 8-bit data fields from low to high. Sometimes there are cpsr_cf, cpsr_all, cpsr_c, etc. in the instructions. Here:                c refers to   the control field in CPSR (PSR )                f refers to   the flag field (PSR )                x
[Microcontroller]
【ARM bare board】Nand Flash basics and timing analysis
1. Hardware knowledge 1.1 How to transmit address signals? DATA0 ~ DATA7 transmits both data and address (multiplexing) ALE (Address Lock Enable) address latch enable signal When ALE = 1, the address is transmitted When ALE = 0, data is transmitted 1.2 How to transmit commands? Command table According to the NAN
[Microcontroller]
【ARM bare board】Nand Flash basics and timing analysis
Interrupt service routine jump of ARM embedded system
In a 32-bit ARM system, a branch instruction or a PC register load instruction is generally placed in the interrupt vector table to implement the function of the program jumping to the interrupt service routine. For example: IRQEntry B HandleIRQ ; jump range is smaller B HandleFIQ Or IRQEntry LDR PC, = HandleIRQ; th
[Microcontroller]
Azure ARM (18) Migrate traditional ASM VM to ARM VM (1)
  Please make sure not to save the persistent file in   -Windows drive D   - Linux /dev/sdb1   The drive letter above is not a persistent drive letter, and the database may be lost.     Currently, many customers are migrating traditional ASM VMs to ARM VMs. Let me briefly introduce it here.     The entire migration pr
[Microcontroller]
Azure ARM (18) Migrate traditional ASM VM to ARM VM (1)
ARM external Flash memory IAP solution
Embedded application systems with ARM chips as processor cores have gained more and more popularity due to their small size, low power consumption, low cost, high performance, rich on-chip resources and wide support for operating systems. In-Application Programming (IAP ) is such a self-modify
[Power Management]
ARM external Flash memory IAP solution
Design of RFID middleware system based on ARM
Introduction RFID middleware acts as a bridge between RFID readers and applications. The application side uses a set of common application program interfaces (APIs) provided by the middleware to connect to the RFID reader and collect RFID tag data. Even if the database software or back-end application that store
[Microcontroller]
Design of RFID middleware system based on ARM
s3c2410(ARM9) startup code analysis
C language entry method and ROM image file generation under ADS This section introduces how to generate a runnable ROM image file under ADS. We know that when the program is downloaded to the flash and run, there are two environments for RW and ZI data, one is the load environment, and the other is the exec enviro
[Microcontroller]
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components
Guess you like

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号