一: 汇编指令格式
ARM 汇编器
的基本语法,这与 GCC汇编器
的语法有所不同,整体编译的流程如下所示;
二: 汇编代码是怎么转换为二进制机器码的
很简单: 转换协议
例如
mov r1,#0xff
1110 00 1 1101 0 0000 0001 000011111111
11--0位
:操作数,若为立即数则填该立即数的二进制值,若为通用寄存器则填通用寄存器标号的二进制值15--12位
:标明目的寄存器19--16位
:标明第一个源操作数寄存器20
:表明该指令是否会影响程序状态字寄存器。是则置一,否则置零24~21
:标明指令的类型。mov
是1101
25
:标志shifter_operand
段存放的是立即数还是寄存器。若为寄存器则置零,若为立即数则置一。27~26
:保留位,恒定为0031~28
:条件段mov
后面没有跟条件,所以为1110
三: 汇编基本指令 - 方便查阅
英文的文档我这里就不贴了 回头大家自行去查阅
指令类型 | 指令宽度 | 指令 |
---|---|---|
Data operations |
16 | ADC, ADD, AND, ASR, BIC, CMN, CMP, CPY, EOR, LSL, LSR, MOV, MUL, MVN,NEG, ORR, ROR, SBC, SUB, TST, REV, REVH, REVSH, SXTB, SXTH, UXTB, and UXTH. |
Branches |
16 | B, B, BL, BX, and BLX. Note, no BLX with immediate. |
Load-store single |
16 | LDR, LDRB, LDRH, LDRSB, LDRSH, STR, STRB, STRH. |
Load-store multiple |
16 | LDMIA, POP, PUSH, and STMIA. |
Exception generating |
16 | BKPT stops in debug if debug enabled, fault if debug disabled. SVC faults to the SVCall handler. |
Data operations with immediate |
32 | ADC{S}. ADD{S}, CMN, RSB{S}, SBC{S}, SUB{S}, CMP, AND{S}, TST, BIC{S}, EOR{S}, TEQ, ORR{S}, MOV{S}, ORN{S}, and MVN{S}. |
Data operations with large immediate |
32 | MOVW, MOVT, ADDW, and SUBW. MOVW and MOVT have a 16-bit immediate. This means they can replace literal loads from memory. ADDW and SUBW have a 12-bit immediate. This means they can replace many from memory literal loads. |
Bit-field operations |
32 | BFI, BFC, UBFX, and SBFX. These are bitwise operations enabling control of position and size in bits. These both support C/C++ bit fields, in structs, in addition to many compare and some AND/OR assignment expressions. |
Data operations with three registers |
32 | ADC{S}. ADD{S}, CMN, RSB{S}, SBC{S}, SUB{S}, CMP, AND{S}, TST, BIC{S},EOR{S}, TEQ, ORR{S}, MOV{S}, ORN{S}, and MVN{S}. No PKxxx instructions. |
Shift operations |
32 | ASR{S}, LSL{S}, LSR{S}, RRX {S}, and ROR {S}. |
Miscellaneous |
32 | REV, REVH, REVSH, RBIT, CLZ, SXTB, SXTH, UXTB, and UXTH.Extension instructions same as corresponding v6 16-bit instructions. |
Table branch |
32 | TBB and TBH table branches for switch/case use. These are LDR with shifts and then branch. |
Multiply |
32 | MUL, MLA, and MLS. |
Multiply with 64-bit result |
32 | UMULL, SMULL, UMLAL, and SMLAL |
Load-store single |
32 | LDR, LDRB, LDRSB, LDRH, LDRSH, STR, STRB, STRH, and T variants. PLD and PLI are both hints and so act as a NOP. |
Load-store multiple |
32 | STM, LDM, LDRD, and STRD. |
Load-store exclusive |
32 | LDREX, STREX, LDREXB, LDREXH, STREXB, STREXH, CLREX. Fault if no local monitor. This is IMP DEF. LDREXD and STREXD are not included in this profile. |
Branches |
32 | B, BL, and B. No BLX (1) because always changes state. No BXJ. |
System |
32 | MSR(2) and MRS(2) replace MSR/MRS but also do more. These access the other stacks and also the status registers.CPSIE/CPSID 32-bit forms are not supported. No RFE or SRS. |
System |
16 | CPSIE and CPSID are quick versions of MSR(2) instructions and use the standard Thumb-2 encodings, but only permit use of i and f and not a. |
Extended32 |
32 | NOP (all forms), Coprocessor (MCR, MCR2, MCRR, MRC, MRC2, and MRRC), and YIELD (hinted NOP). Note, no MRS(1), MSR(1), or SUBS (PC return link). |
Combined branch |
16 | CBZ and CBNZ (Compare and Branch if register is Zero or Non-Zero). |
Extended |
16 | IT and NOP. This includes YIELD. |
Divide |
32 | SDIV and UDIV. 32/32 divides both signed and unsigned with 32-bit quotient result, no remainder, it can be derived by subtraction. Early out is permitted. |
Sleep |
16,32 | WFI, WFE, and SEV are in the class of hinted NOP instructions that control sleep behavior. |
Barriers |
32 | ISB, DSB, and DMB are barrier instructions that ensure certain actions have taken place before the next instruction is executed. |
Saturation |
32 | SSAT and USAT perform saturation on a register. They perform the following: Normalize the value using shift test for overflow from a selected bit position, the Q value. Set the xPSR Q bit if so, saturate the value if overflow detected. Saturation refers to the largest unsigned value or the largest/smallest signed value for the size selected. |
常见指令
b 指令
bl 指令
跳转到标号出执行b.le
:判断上面cmp的值是小于等于 执行标号,否则直接往下走b.ge
大于等于 执行地址 否则往下b.lt
判断上面camp的值是 小于 执行后面的地址中的方法 否则直接往下走b.gt
大于 执行地址 否则往下b.eq
等于 执行地址 否则往下b.hi
比较结果是无符号大于,执行地址中的方法,否则不跳转b.hs
指令是判断是否无符号小于b.ls
指令是判断是否无符号大于b.lo
指令是判断是否无符号大于等于
ret 返回
mov x0,#0x10 -> x0 = 0x10
str w10 ,[sp]
将w10寄存器的值存到 sp栈空间内存stp x0,x1,[sp.#0x10]*
: x0、x1 的值存入 sp + 0x10orr x0,wzr,#0x1
: x0 = wzr | 0x1stur w10 ,[sp]
将w10寄存器的值存到 sp栈空间内存ldr w10 ,[sp]
w10 = sp栈内存中的值ldp x0,x1,[sp]
x0、x1 = sp栈内存中的值
adrp
通过基地址 + 偏移 获得一个字符串(全局变量)
cbz
比较,为零则跳转;cbnz
: 比较,为非零则跳转。cmp: 比较功能
例如 :cmp OPR1 , OPR2. = (OPR1)-(OPR2)
16位数据操作指令
名字 | 功能 |
---|---|
ADC |
带进位加法(ADD with Carry) |
ADD |
加法 |
AND |
按位与。这里的按位与和C的”&”功能相同 |
ASR |
算术右移(Arithmetic Shift Right) |
BIC |
按位清零(把一个数跟另一个无符号数的反码按位与) |
CMN |
负向比较(把一个数跟另一个数据的二进制补码相比较) |
CMP |
比较(Compare,比较两个数并且更新标志) |
cmp(Compare) |
比较指令 |
CMP |
把一个寄存器的内容和另一个寄存器的内容或立即数进行比较。但不存储结果,只是正确的更改标志。一般CMP做完判断后会进行跳转,后面通常会跟上B指令! |
CPY |
把一个寄存器的值拷贝(COPY)到另一个寄存器中 |
EOR |
近位异或 |
LSL |
逻辑左移(Logic Shift Left) |
LSR |
逻辑右移(Logic Shift Right) |
MOV |
寄存器加载数据,既能用于寄存器间的传输,也能用于加载立即数 |
MUL |
乘法(Multiplication) |
MVN |
加载一个数的 NOT值(取到逻辑反的值) |
NEG |
取二进制补码 |
ORR |
按位或 |
ROR |
循环右移 |
SBC |
带借位的减法 |
SUB |
减法(Subtraction) |
TST |
测试(Test,执行按位与操作,并且根据结果更新Z) |
REV |
在一个32位寄存器中反转(Reverse)字节序 |
REVH |
把一个32位寄存器分成两个(Half)16位数,在每个16位数中反转字节序 |
REVSH |
把一个32位寄存器的低16位半字进行字节反转,然后带符号扩展到32位 |
SXTB |
带符号(Signed)扩展一个字节(Byte)到 32位 |
SXTH |
带符号(Signed)扩展一个半字(Half)到 32位 |
UXTB |
无符号(Unsigned)扩展一个字节(Byte)到 32位 |
UXTH |
无符号(Unsigned)扩展一个半字(Half)到 32位 |
16位转移指令
名字 | 功能 |
---|---|
B |
无条件转移(Branch) |
B |
有条件(Condition)转移 |
BL |
转移并连接(Link)。用于呼叫一个子程序,返回地址被存储在LR中 |
CBZ |
比较(Compare),如果结果为零(Zero)就转移(只能跳到后面的指令) |
CBNZ |
比较,如果结果非零(Non Zero)就转移(只能跳到后面的指令) |
IT |
If-Then |
16位存储器数据传送指令
名字 | 功能 | |
---|---|---|
LDR |
从存储器中加载(Load)字到一个寄存器(Register)中 | |
LDRH |
从存储器中加载半(Half)字到一个寄存器中 | |
LDRB |
从存储器中加载字节(Byte)到一个寄存器中 | |
LDRSH |
从存储器中加载半字,再经过带符号扩展后存储一个寄存器中 | |
LDRSB |
从存储器中加载字节,再经过带符号扩展后存储一个寄存器中 | |
STR |
把一个寄存器按字存储(Store)到存储器中 | |
STRH |
把一个寄存器存器的低半字存储到存储器中 | |
STRB |
把一个寄存器的低字节存储到存储器中 | |
LDMIA |
加载多个字,并且在加载后自增基址寄存器 | |
STMIA |
存储多个字,并且在存储后自增基址寄存器 | |
PUSH |
压入多个寄存器到栈中 | |
POP |
从栈中弹出多个值到寄存器中 |
其它16位指令
名字 | 功能 | |
---|---|---|
SVC |
系统服务调用(Service Call) | |
BKPT |
断点(Break Point)指令。如果调试被使能,则进入调试状态(停机)。 | |
NOP |
无操作(No Operation) | |
CPSIE |
使能 PRIMASK(CPSIE i)/FAULTMASK(CPSIE f)——清零相应的位 | |
CPSID |
除能 PRIMASK(CPSID i)/FAULTMASK(CPSID f)——置位相应的位 |
32位数据操作指令
名字 | 功能 | |
---|---|---|
ADC |
带进位加法 | |
ADD |
加法 | |
ADDW |
宽加法(可以加 12 位立即数) | |
AND |
按位与 | |
ASR |
算术右移 | |
BIC |
位清零(把一个数按位取反后,与另一个数逻辑与) | |
BFC |
位段清零 | |
BFI |
位段插入 | |
CMN |
负向比较(把一个数和另一个数的二进制补码比较,并更新标志位) | |
CMP |
比较两个数并更新标志位 | |
CLZ |
计算前导零的数目 | |
EOR |
按位异或 | |
LSL |
逻辑左移 | |
LSR |
逻辑右移 | |
MLA |
乘加 | |
MLS |
乘减 | |
MOVW |
把 16 位立即数放到寄存器的底16位,高16位清0 | |
MOV |
加载16位立即数到寄存器(其实汇编器会产生MOVW) | |
MOVT |
把 16 位立即数放到寄存器的高16位,低 16位不影响 | |
MVN |
移动一个数的补码 | |
MUL |
乘法 | |
ORR |
按位或 | |
ORN |
把源操作数按位取反后,再执行按位或 | |
RBIT |
位反转(把一个 32 位整数先用2 进制表达,再旋转180度) | |
REV |
对一个32 位整数做按字节反转 | |
REVH/REV16 |
对一个32 位整数的高低半字都执行字节反转 | |
REVSH |
对一个32 位整数的低半字执行字节反转,再带符号扩展成32位数 | |
ROR |
圆圈右移 | |
RRX |
带进位的逻辑右移一格(最高位用C 填充,且不影响C的值) | |
SFBX |
从一个32 位整数中提取任意的位段,并且带符号扩展成 32 位整数 | |
SDIV |
带符号除法 | |
SMLAL |
带符号长乘加(两个带符号的 32 位整数相乘得到 64 位的带符号积,再把积加到另一个带符号 64位整数中) | |
SMULL |
带符号长乘法(两个带符号的 32 位整数相乘得到 64位的带符号积) | |
SSAT |
带符号的饱和运算 | |
SBC |
带借位的减法 | |
SUB |
减法 | |
SUBW |
宽减法,可以减 12 位立即数 | |
SXTB |
字节带符号扩展到32位数 | |
TEQ |
测试是否相等(对两个数执行异或,更新标志但不存储结果) | |
TST |
测试(对两个数执行按位与,更新Z 标志但不存储结果) | |
UBFX |
无符号位段提取 | |
UDIV |
无符号除法 | |
UMLAL |
无符号长乘加(两个无符号的 32 位整数相乘得到 64 位的无符号积,再把积加到另一个无符号 64位整数中) | |
UMULL |
无符号长乘法(两个无符号的 32 位整数相乘得到 64位的无符号积) | |
USAT |
无符号饱和操作(但是源操作数是带符号的) | |
UXTB |
字节被无符号扩展到32 位(高24位清0) | |
UXTH |
半字被无符号扩展到32 位(高16位清0) |
32位存储器数据传送指令
名字 | 功能 | |
---|---|---|
LDR |
加载字到寄存器 | |
LDRB |
加载字节到寄存器 | |
LDRH |
加载半字到寄存器 | |
LDRSH |
加载半字到寄存器,再带符号扩展到 32位 | |
LDM |
从一片连续的地址空间中加载多个字到若干寄存器 | |
LDRD |
从连续的地址空间加载双字(64 位整数)到2 个寄存器 | |
STR |
存储寄存器中的字 | |
STRB |
存储寄存器中的低字节 | |
STRH |
存储寄存器中的低半字 | |
STM |
存储若干寄存器中的字到一片连续的地址空间中 | |
STRD |
存储2 个寄存器组成的双字到连续的地址空间中 | |
PUSH |
把若干寄存器的值压入堆栈中 | |
POP |
从堆栈中弹出若干的寄存器的值 |
32位转移指令
名字 | 功能 |
---|---|
B |
无条件转移 |
BL |
转移并连接(呼叫子程序) |
TBB |
以字节为单位的查表转移。从一个字节数组中选一个8位前向跳转地址并转移 |
TBH |
以半字为单位的查表转移。从一个半字数组中选一个16 位前向跳转的地址并转移 |
其它32位指令
名字 | 功能 |
---|---|
LDREX |
加载字到寄存器,并且在内核中标明一段地址进入了互斥访问状态 |
LDREXH |
加载半字到寄存器,并且在内核中标明一段地址进入了互斥访问状态 |
LDREXB |
加载字节到寄存器,并且在内核中标明一段地址进入了互斥访问状态 |
STREX |
检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的字 |
STREXH |
检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的半字 |
STREXB |
检查将要写入的地址是否已进入了互斥访问状态,如果是则存储寄存器的字节 |
CLREX |
在本地的处理上清除互斥访问状态的标记(先前由 LDREX/LDREXH/LDREXB做的标记) |
MRS |
加载特殊功能寄存器的值到通用寄存器 |
MSR |
存储通用寄存器的值到特殊功能寄存器 |
NOP |
无操作 |
SEV |
发送事件 |
WFE |
休眠并且在发生事件时被唤醒 |
WFI |
休眠并且在发生中断时被唤醒 |
ISB |
指令同步隔离(与流水线和 MPU等) |
DSB |
数据同步隔离(与流水线、MPU 和cache等) |
DMB |
数据存储隔离(与流水线、MPU 和cache等) |