汇编指令-收藏方便查阅

28891

一: 汇编指令格式

ARM 汇编器的基本语法,这与 GCC汇编器 的语法有所不同,整体编译的流程如下所示;

二: 汇编代码是怎么转换为二进制机器码的

很简单: 转换协议

例如 🌰🌰🌰

mov r1,#0xff

1110 00 1 1101 0 0000 0001 000011111111
  • 11--0位:操作数,若为立即数则填该立即数的二进制值,若为通用寄存器则填通用寄存器标号的二进制值

  • 15--12位:标明目的寄存器

  • 19--16位:标明第一个源操作数寄存器

  • 20:表明该指令是否会影响程序状态字寄存器。是则置一,否则置零

  • 24~21:标明指令的类型。mov1101

  • 25:标志 shifter_operand 段存放的是立即数还是寄存器。若为寄存器则置零,若为立即数则置一。

  • 27~26:保留位,恒定为00

  • 31~28:条件段 mov 后面没有跟条件,所以为 1110

三: 汇编基本指令 - 方便查阅

英文的文档我这里就不贴了 回头大家自行去查阅

指令类型指令宽度指令
Data operations16ADC, 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.
Branches16B, B, BL, BX, and BLX. Note, no BLX with immediate.
Load-store single16LDR, LDRB, LDRH, LDRSB, LDRSH, STR, STRB, STRH.
Load-store multiple16LDMIA, POP, PUSH, and STMIA.
Exception generating16BKPT stops in debug if debug enabled, fault if debug disabled. SVC faults to the SVCall handler.
Data operations with immediate32ADC{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 immediate32MOVW, 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 operations32BFI, 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 registers32ADC{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 operations32ASR{S}, LSL{S}, LSR{S}, RRX {S}, and ROR {S}.
Miscellaneous32REV, REVH, REVSH, RBIT, CLZ, SXTB, SXTH, UXTB, and UXTH.Extension instructions same as corresponding v6 16-bit instructions.
Table branch32TBB and TBH table branches for switch/case use. These are LDR with shifts and then branch.
Multiply32MUL, MLA, and MLS.
Multiply with 64-bit result32UMULL, SMULL, UMLAL, and SMLAL
Load-store single32LDR, LDRB, LDRSB, LDRH, LDRSH, STR, STRB, STRH, and T variants. PLD and PLI are both hints and so act as a NOP.
Load-store multiple32STM, LDM, LDRD, and STRD.
Load-store exclusive32LDREX, STREX, LDREXB, LDREXH, STREXB, STREXH, CLREX. Fault if no local monitor. This is IMP DEF. LDREXD and STREXD are not included in this profile.
Branches32B, BL, and B. No BLX (1) because always changes state. No BXJ.
System32MSR(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.
System16CPSIE 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.
Extended3232NOP (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 branch16CBZ and CBNZ (Compare and Branch if register is Zero or Non-Zero).
Extended16IT and NOP. This includes YIELD.
Divide32SDIV 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.
Sleep16,32WFI, WFE, and SEV are in the class of hinted NOP instructions that control sleep behavior.
Barriers32ISB, DSB, and DMB are barrier instructions that ensure certain actions have taken place before the next instruction is executed.
Saturation32SSAT 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 + 0x10

  • orr x0,wzr,#0x1 : x0 = wzr | 0x1

  • stur 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)

  • ccmp : 双重比较. ccmp x13, x12, #0x0, ne 判断x13 和 x12 同时存在

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)就转移(只能跳到后面的指令)
ITIf-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等)