yaboPP电子
Technical Article

How to Write Assembly Language: Basic Assembly Instructions in the ARM Instruction Set

February 08, 2019经过斯蒂芬·圣迈克尔

Learn some basic instructions used in the ARM instruction set used for programming ARM cores.

Learn some basic instructions used in the ARM instruction set used for programming ARM cores.

This article is intended to help you learn about basic assembly instructions for ARM core programming.

We will pick up from a previous post onARM寄存器文件- 请考虑在继续之前审查该信息,因为我们将在下面的说明中引用注册表示和注册标志。

This information will be used in the next article to program a Raspberry Pi, which uses a 32-bit ARM core. In this article, we will focus our attention on 32-bit ARMv7 instructions and 32-bit registers.

Note: Later versions of the Raspberry Pi, running Raspbian, use a 64-bit ARMv8 processor, but run it in 32-bit mode just like the older v7 versions. We may cover ARMv8 in a future article.

Supporting Information:

Machine Code

处理器使用说明 - LOT一看指令代表的机器代码。Since most of the instructions we'll go over are for data operations, I've grabbed the data-processing instruction out of theARMV7 manual

图1。ARM data-processing instruction

图1显示了在ARM数据处理指令中发现的32位;每个位具有单独或作为组的一部分的特定目的。

这Condition field is 4 bits wide, as there are roughly fifteen conditional codes. The opcode is 4 bits wide and sits between the immediate flag, which signals that operand 2 holds an immediate value, and the condition-set flag, which we can use to update the status register during an operation (more on these later). Notice it's the opcode that determines the operation—such as addition, subtraction, or exclusive OR—that the processor will perform.

As you go through the instructions below, we'll reference Figure 1 and try to see how the assembly instruction gets encoded into binary. And don't be afraid to dig through the ARM manual for more information.

How to Read Assembly Instructions: Mnemonics and Operands

每个指示都以一个mnemonic这代表一个操作。助记符之后是将要操作的操作数。这些通常是目的地和源操作数,如下所示。

MNEMONIC DEST, SRC1, SRC2

添加指令(下面的部分涵盖)将R2添加到R1并将结果放入寄存器R0中(请参阅previous articlefor an explanation of these denotations). This is the typical way to read an assembly instruction. Add R2 to R1 and put it (the result) in R0. The equivalent machine code that will execute on the processor is shown alongside the ADD instruction.

始终执行的“ cond”字段包含“ 1110”。当使用附加到添加操作的条件后缀时,这些位会发挥作用。下一个字段未使用并将其设置为零。“ I”字段为零,因为“ OP2”是寄存器,而不是直接值。“ S”字段为零,因为我们没有将s附加到添加操作,即,我们不希望此说明更新状态寄存器标志(N,Z,C和V,上面讨论过)。

If you refer back to Figure 1, notice the opcode for addition. It's 0100b. This tells the processor to set the datapath for an ADD operation. The last three fields are R1 (0001b), R0 (0000b), and R2 ( ….0010b).

Cond I OpCd S Rn Rd Op2

ADD R0, R1, R2 @ 1110|00|0|0100|0|0001|0000|000000000010

operandsin an instruction are typically registers, but they can also be memory addresses or immediate values. An immediate value is an exact number to be used. These are prefixed with a # symbol. For instance, instead of using R2, above, we can use the immediate value 42. This instruction is shown below:

Cond I OpCd S Rn Rd Op2

ADDS R4, R6, #42 @ 1110|00|1|0100|1|0110|0100|000000101010

该指令将42增加到R6,并将结果添加到R4中。这次围绕“ i”设置为1,因为我们使用的是操作数2的即时值2。opcode保持不变,因为我们仍在进行添加。注意“ S”字段是1;因此,我们希望此添加操作在执行过程中更新状态寄存器标志。

这next instruction can use the 'Cond' field to check the status flags and conditionally execute based on the result. 'Rn' is 0110b, representing R6, and 'Rd' is 0100b for R4. The immediate value in 'Op2' is the 12-bit binary representation of the number 42. The rest of this section lists a subset of the most basic ARM instructions, with a short description and example.

Instructions for Data Processing

这following instructions manipulate data. This can be arithmetic operations that perform math functions, comparison operations, or data movement.

加法(添加)

加法(添加)adds R2 to R1 and puts the result in R0. Addition with Carry (ADC) adds R2 to R1, along with the carry flag. This is used when dealing with numbers larger than a single 32 bit word.

ADD R0, R1, R2

ADC R0, R1, R2

Subtraction (SUB)

Subtraction (SUB) subtracts R2 from R1 and puts the result in R0. Subtraction with Carry (SBC) subtracts R2 from R1 and, if the carry flag is cleared, subtracts one from the result. This is equivalent to borrowing in arithmetic and ensures that multi-word subtraction works correctly.

SUB R0,R1,R2

SBC R0, R1, R2

比较(CMP)并比较负(CMN)

比较(CMP)并比较负(CMN)Compare two operands. CMP subtracts R1 from R0 and CMN adds R2 to R1, and then the status flags are updated according to the result of the addition or subtraction.

CMP R0,R1

CMN R1,R2

Move (MOV)

MOVE(MOV)操作完全可以做到的声音。它将数据从一个地方移至另一个地方。下面,R1复制到R0中。第二行将即时值8放入R0中。

MOV R0,R1

MOV R0, # 8

Move Negative (MVN)

Move negative (MVN) performs a similar operation, but complements (inverts) the data first. This is useful when performing operations with negative numbers, in particular with two's complement notation. The instruction below puts NOT 8, better known as –9, into R0. Add one to that result and you have performed the two's complement and obtained -8.

MVN R0, #8

并执行R2和R1的位,并将结果放入R0中。可以使用直接值代替R2。

和R0,R1,R2

ORR和EOR

ORR和EOR分别执行R2和R1的位或XOR。

ORR R0, R1, R2

EOR R0, R1, R2

Bit Clear (BIC)

Bit Clear (BIC) performs a bitwise AND of R2 and R1, but first complements the bits in R2. This operation is often used with immediate values, as in the second line, where the immediate value, 0xFF, is inverted and subsequently ANDed with R1. ANDing eight zeros with the first byte of R1 will clear those bits, i.e., set them equal to zero, and the result will be put in R0.

BIC R0, R1, R2

BIC R0, R1, #0xFF

Test Bits (TST) and Test Equivalence (TEQ)

存在测试位(TST)和测试等效性(TEQ),以测试位于寄存器中的位。这些说明不使用目标寄存器,而只需根据结果更新状态寄存器即可。TST实质上是在表和两个操作数中执行的。通过将掩码用于操作数二,我们可以测试是否设置了R0中的单个位。

In this case, we check bit 3 (bitmask = 1000b = 8) and set the Z flag based on the outcome. TEQ performs a similar function to exclusive or and is great for checking whether two registers are equal. This updates the N and Z flag, therefore it also works on signed numbers; N is set to one if their signs are different.

TST R0, #8

TEQ R1, R2

Multiplication (MUL)

Multiplication (MUL) multiplies R1 by R2 and puts the result in R0. Multiplication cannot be used with an immediate value.

MUL R0, R1, R2

Instructions for Shifting and Rotating

Logical Shift Left (LSL)

Logical Shift Left (LSL) shifts the bits in R1 by a shift value. In this case, the immediate value 3, and drops the most significant bits. The last bit that was shifted out is put into the carry flag, and the least significant bits are filled with zeros. Below, R1 gets shifted left by the immediate value 3, or a value between 0 and 31 in R2, and put in R0. One logical left shift multiplies a value by two. This is an inexpensive way to do simple multiplication.

LSL R0, R1, #3

LSL R0, R1, R2

Logical Shift Right (LSR)

Logical Shift Right (LSR) works in the reverse fashion as LSL and effectively divides a value by two. The most significant bits are filled with zeros, and the last least significant bit is put into the carry flag.

LSR R0, R1, #2

算术转移右(ASR)

算术转移右(ASR)performs the same work as LSR but is designed for signed numbers. It copies the sign bit back into the last position on the left.

ASR R0,R1,#4

向右旋转(ROR)

向右旋转(ROR)rotates all the bits in a word by some value. Instead of filling the bits on the left with zeros, the bits shifted out are simply put back into the other end.


ROR R0, R1, #5

Instructions for Branching Operations

处理器的一个重要功能是能够基于一组输入的两个代码路径在两个代码路径之间进行选择。这正是分支机构操作所做的。处理器通常通过将R15(PC)的R15递增四个字节(即单个指令的长度)来执行一项指令。分支将PC更改为另一个位置,该位置由代表装配代码的部分的标签表示。

Branch (B)

分支(b)将PC移至标签指定的地址。标签(下面的示例中的“循环”)表示您希望处理器下一步执行的代码部分。标签只是文字,通常是一个有意义的词。

B loop

分支链接(BL)

分支链接(BL)performs a similar operation, but it copies the address of the next instruction into R14, the link register (LR). This works great when performing subroutine/procedure calls, because as soon as the section of code at the label is finished we can use the LR to get back to where we branched. Below, we branch to the label “subroutine” and then use the link register to get back to the next instruction.

BL子例程

subroutine:

MOV PC, LR

我们使用MOV指令将链接寄存器放回程序计数器中。这将程序在我们的子例程呼叫后立即返回现场,此处标记为 。Notice the use of LR and PC above. ARM assemblers recognize these as R14 and R15, respectively. This provides a convenient reminder to the programmer about the operation being performed.

Instructions for Load and Store

计算机的内存存储所需要的数据the processor. This data is accessed by using an address. By first putting an address into a register, we can then access the data at that address. This is why we use load and store operations.

加载寄存器(LDR)

Load register (LDR) loads the data located at an address into the destination register. The brackets around R1 signify that the register contains an address. By using the brackets we put the data at that address into R0, instead of the address itself. We can also use this notation to locate data offset from a certain address, as shown on the second line. R0 would contain the data two words away from whatever address R1 contains.

LDR R0, [R1]

LDR R0, [R1, #8]

We can also use labels to represent an address, and the corresponding data can then be loaded into a register. The first line below loads the address of the label “info” into R0. The value stored at that address is then accessed and put into R1 in the second line.

LDR R0, =info

LDR R1, [R0]

Store (STR)

Store (STR) performs the complementary operation to load. STR puts the contents of a register into a memory location. The code below stores the data in R1 at the address in R0. Again, the brackets signify that R0 holds an address, and we want to modify the data at that address.

STR R1, [R0]

负载和存储类型:字节(b),半字(h),word(省略),签名(SB),unsigned(b)

Both load and store can be written with a type appended to them. This type signifies whether the instruction will manipulate a byte (B), halfword (H), or word (omitted) and whether the data is signed (SB) or unsigned (B).

一个地方人这可能派上用场的字符串ipulation, as ASCII characters have a length of one byte. These operations also allow for the use of offsets when loading or storing, as seen in the last line.

ldr r0,= text @加载32位地址到R0

STRB R1, [R0] @ store byte at address in memory

STRB R1, [R0, + R2] @ store byte at address + offset R2

Instructions for Conditionals

As mentioned earlier, the mnemonics used in an instruction can have optional condition codes appended to them. This allows for conditional execution.

Remember, the flags (as laid out in the previous article) are Z (zero), C (Carry), N (negative), and V (overflow).

To force instructions to update the status register, an optional S can be appended to most mnemonics mentioned thus far. Once the status register is updated, a number of conditional suffixes, shown below, can be used to control whether the instruction executes. The binary codes for these suffixes correspond to the first four bits of the data-processing instruction shown above (see Figure 1).


图2。Condition suffixes

这se suffixes are appended to the mnemonic when writing assembly. The listing below shows a few of the conditional suffixes used with instructions mentioned earlier.

Since we'll be assembling with the GNU assembler in the next article, we need to use the @ symbol to represent a comment.

.global _start

start:

MOV R0, #3 @ Put the value 3 into R0

MOV R1, #0 @ Put the value 0 into R1

环形:

CMP R0,R1 @比较R1与R0(有效R0减去R1)

BEQ done @ If they are equal (Z=1) branch to done label

ADDGT R1, #1 @ If R0 is greater than R1 add 1 to R1

SUBLT R1, #1 @ If R0 is less than R1 subtract 1 from R1

B循环 @分支向后和重新运行循环

done:

@ do other stuff


Hopefully this article gives you a foundational understanding of the basic instructions used to program an ARM core. In the next article, we'll use this knowledge in a simple example of programming a core using a Raspberry Pi.

3条评论
  • John Długosz February 09, 2019

    您应该通过指出此遗产编码不是我们现在使用的,并且在64位代码中完全无法使用。Thumb2编码是紧凑且可变长度,并且没有每个指令的条件代码谓词。

    Like. 回复
  • redrooster01 February 16, 2019

    Thank you for pointing that out John but how many people read the comments first? The article is misleading by omission and should be amended or rewritten.

    Like. 回复
  • RK37 2019年2月19日

    Thanks for the comments. The author’s original article did refer to different Arm versions, but this information was lost when the article was reorganized prior to publication. The introductory section has been modified in an attempt to avoid the confusion that you’re referring to.

    Like. 回复