学习 Linux 系统启动流程,必须熟悉几个汇编指令,总结给大家。
这里不是最全的,只列出一些最常用的汇编指令。
一.数据处理指令
1.数据传送指令
【MOV指令】
把一个寄存器的值(立即数)赋给另一个寄存器,或者将一个常量赋给寄存器。
MOV指令的格式为:
代码语言:javascript复制MOV 目的寄存器,源操作数
代码语言:javascript复制MOV R1,R0 ;将寄存器R0的值传送到寄存器R1
2.算术运算指令
(1)【加法指令】:ADD
代码语言:javascript复制ADD 目的寄存器,操作数1,操作数2
ADD指令用于把两个操作数相加,并将结果存放到目的寄存器中。
代码语言:javascript复制ADD R0,R1,R2 ;R0 = R1 R2
ADD R0,R1,#256 ;R0 = R1 256
(2)【带进位的加法指令】:ADC
代码语言:javascript复制ADC 目的寄存器,操作数1,操作数2
ADC指令用于把两个操作数相加,再加上CPSR中的C条件标志位的值,并将结果存放到目的寄存器中。
(3)【减法指令】:SUB
代码语言:javascript复制SUB 目的寄存器,操作数1,操作数2
把操作数1减去操作数2,并将结果存放到目的寄存器中。
代码语言:javascript复制SUB R0,R1,R2 ;R0 = R1 - R2
SUB R0,R1,#256 ;R0 = R1 - 256
3.比较指令
(1)【直接比较指令】:CMP
代码语言:javascript复制CMP 操作数1,操作数2
代码语言:javascript复制CMP R1,R0;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
CMP R1,#100;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位
4.逻辑运算指令
(1)【逻辑与指令】:AND
代码语言:javascript复制AND 目的寄存器,操作数1,操作数2
AND 指令用于在两个操作数上进行逻辑与运算,并把结果放置到目的寄存器中。
代码语言:javascript复制AND R0,R0,#3 ; 该指令保持R0的0、1位,其余位清零。
(2)【逻辑或指令】:ORR
代码语言:javascript复制ORR 目的寄存器,操作数1,操作数2
ORR 指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。
代码语言:javascript复制ORR R0,R0,#3 ; 该指令设置R0的0、1位,其余位保持不变。
二.转移指令
【跳转指令】
代码语言:javascript复制B 跳转指令
BL 带返回的跳转指令
BLX 带返回和状态切换的跳转指令
BX 带状态切换的跳转指令
三.程序状态寄存器访问指令
1、【MRS指令】
代码语言:javascript复制MRS 通用寄存器,程序状态寄存器(CPSR或SPSR)
代码语言:javascript复制MRS R0,CPSR ;传送CPSR的内容到R0
MRS R0,SPSR ;传送SPSR的内容到R0
2、【MSR指令】
代码语言:javascript复制MSR 程序状态寄存器(CPSR或SPSR)_<域>,操作数
代码语言:javascript复制MSR CPSR,R0 ;传送R0的内容到CPSR
MSR SPSR,R0 ;传送R0的内容到SPSR
四.加载/存储指令
ARM 微处理器支持加载/存储指令用于在寄存器和存储器之间传送数据,加载指令用于将存储器中的数据传送到寄存器,存储指令则完成相反的操作。
1、【LDR指令】
代码语言:javascript复制LDR 目的寄存器,<存储器地址>
LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。
代码语言:javascript复制LDR R0,[R1] ;将存储器地址为R1的字数据读入寄存器R0。
LDR R0,[R1,R2] ;将存储器地址为R1 R2的字数据读入寄存器R0。
LDR R0,[R1,#8] ;将存储器地址为R1 8的字数据读入寄存器R0。
LDR R0,[R1,R2] ! ;将存储器地址为R1 R2的字数据读入寄存器R0,并将新地址R1+R2写入R1。
LDR R0,[R1,#8] ! ;将存储器地址为R1 8的字数据读入寄存器R0,并将新地址R1+8写入R1。
LDRB 和 LDRH 指令大家可以百度。
2、【STR指令】
代码语言:javascript复制STR 源寄存器,<存储器地址>
STR指令用于从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用,且寻址方式灵活多样,使用方式可参考指令LDR。
代码语言:javascript复制STR R0,[R1],#8 ;将R0中的字数据写入以R1为地址的存储器中,并将新地址R1+8写入R1。
STR R0,[R1,#8] ;将R0中的字数据写入以R1+8为地址的存储器中。
STRB 和 STRH指令大家可以百度。
五.异常产生指令
1、【SWI指令】
代码语言:javascript复制SWI 24位的立即数
SWI指令用于产生软件中断,以便用户程序能调用操作系统的系统例程。
代码语言:javascript复制SWI 0x02 ;该指令调用操作系统编号位02的系统例程。
2、【BKPT指令】
代码语言:javascript复制BKPT 16位的立即数
BKPT指令产生软件断点中断,可用于程序的调试。
六.伪代码
1.【AREA】
一个汇编程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段,因此在汇编程序的开头,我们一般的语句会用到AREA。
代码语言:javascript复制AREA 段名 属性 1 ,属性 2 ,....
代码语言:javascript复制AREA Init ,CODE ,READONLY ;定义一个代码段,段名为 Init ,属性为只读。
2、【ALIGN】
代码语言:javascript复制ALIGN { 表达式 { ,偏移量 }}
ALIGN 伪指令可通过添加填充字节的方式,使当前位置满足一定的对其方式。其中,表达式的值用于指定对齐方式,可能的取值为2的幂,如 1 、2 、4 、8 、16 等。eg : xxx = ALIGN(4)
3、【CODE16、CODE32】
代码语言:javascript复制CODE16 (或 CODE32 )
CODE16 伪指令通知编译器,其后的指令序列为 16 位的 Thumb 指令。
CODE32 伪指令通知编译器,其后的指令序列为 32 位的 ARM 指令。
4、【ENTRY】
代码语言:javascript复制ENTRY
ENTRY(stext)
很常见!!!ENTRY 伪指令用于指定汇编程序的入口点。在一个完整的汇编程序中至少要有一个 ENTRY (也可以有多个,当有多个 ENTRY 时,程序的真正入口点由链接器指定),但在一个源文件里最多只能有一个 ENTRY (可以没有)。
5、【END】
代码语言:javascript复制END
END 伪指令用于通知编译器已经到了源程序的结尾。
·················· END ··················