汇编语法的组成部分
1.伪操作:不参与程序的执行,但是用于告诉编译器程序该怎么编译
.text
.global .end .if .else .endif .data
2.汇编指令
编译器将一条汇编指令编译成一条机器码,在内存里一条指令占4字节内存,一条指令可以实现一个特定的功能
3.伪指令
不是指令,看起来像是一条指令,可以实现和指令类似的功能。一条伪指令实际上可能是由多条指令共同实现
4.注释
单行注释: @
多行注释 /* */
条件编译
.if 0
指令段
.else
指令段
.endif
汇编指令的基本格式
指令的基本格式:
<opcode>{<cond>}{s} <Rd>, <Rn>, <shifter_operand>
解释:
<opcode>:指令码
{<cond>}:条件码
{s}:状态位,如果在指令后面加上s,则运算的结果会影响CPSR的条件位
<Rd>:目标寄存器
<Rn>:第一操作寄存器 只能是寄存器
<shifter_operand>:第二操作数,可以是寄存器,也可以是立即数
按照指令码将第一操作寄存器和第二操作数进行运算,将运算后的结果保存在目标寄存器
注意:
1.一条汇编指令一般占一行
2.汇编不区分大写小写
汇编指令
数据搬移指令
<opcode>{<cond>}{s} <Rd>, <shifter_operand>
解释:
<opcode>:指令码
{<cond>}:条件码
{s}:状态位,如果在指令后面加上s,则运算的结果会影响CPSR的条件位
<Rd>:目标寄存器
<shifter_operand>:第一操作数,可以是寄存器,也可以是立即数
按照指令码将第一操作数运算后的结果保存在目标寄存器
指令码功能:
mov:将第一操作数的值保存在目标寄存器
mvn:将第一操作数的值按位取反,将结果保存在目标寄存器
立即数的概念
定义:能够直接当作指令的一部分参与到指令的执行过程中的数据就是立即数.立即数由一个0-255范围内的数循环右移偶数位获得。
在指令的32为中将低12位预留保存立即数的数据
如何判断一个数据是不是立即数:
在0-255范围内找一个数,让它循环右移偶数位(一个0-15范围内的数*2得到),如果能够得到这个数据,则这个数就是一个立即数。
循环右移:最低位移出去的数补到最高位
0000 0000 0000 0000 0000 0000 0000 1010
右移两位: 0000 0000 0000 0000 0000 0000 0000 0010
循环右移两位: 100000 0000 0000 0000 0000 0000 0000 10
ex:
0X104: 0000 0000 0000 0000 0000 0001 0000 0100
循环右移2位-》000000 0000 0000 0000 000000 0100 0001 -》0x41
换句话说,将0x41循环右移30位得到0X104,所以,0X104是一个立即数
0X101:0000 0000 0000 0000 0000 0001 0000 0001
0X101找不到一个0-255范围内的数循环右移得到它,所以0X101不是立即数
移位指令
格式以及指令码
格式:<opcode>{<cond>}{s} <Rd>, <Rn>, <shifter_operand>
解释:将第一操作寄存器的数值移位第二操作数指定的位数,将结果保存在目标寄存器中
指令码:
LSL:左移运算 低位补0
LSR:右移运算 高位补0
ROR:循环右移:低位移出的值补到高位
位运算指令
格式:<opcode>{<cond>}{s} <Rd>, <Rn>, <shifter_operand>
解释:将第一操作寄存器和第二操作数进行位运算,将结果保存在目标寄存器中
指令码:
and:与 与0清0 与1不变
orr:或 或1置1 或0不变
eor:异或 相同为0 不同为1
bic:按位清零指令,想将哪一位设置为0,只需要用bic指令给这一位运算一个1即可
实例
1.and:
mov r0,#0XFF
and r1,r0,#0XF0 @R1结果为0XF0
2.ORR:
mov r0,#0XFF
orr r1,r0,#0XF000 @R1结果为0XF0FF
3.EOR:
ldr r0,=0xf0f0
EOr r1,r0,#0XFF @R1结果为0XF00F
0000 0000 0000 0000 0000 0000 1111 1111
0000 0000 0000 0000 1111 0000 1111 0000
结果:0000 0000 0000 0000 1111 0000 0000 1111 -》0XF00F
4.BIC
ldr r0,=0xFF
BIC r0,r0,#(0x1<<5) @将R0的值第5位清0 @R0结果为0XDF
算术运算指令
格式:<opcode>{<cond>}{s} <Rd>, <Rn>, <shifter_operand>
解释:将第一操作寄存器的值和第二操作数进行算数运算,结果保存在目标寄存器中
add:加法运算
adc:进行加法运算时需要考虑CPSR的条件位
sub:减法运算
sbc:进行减法运算时需要考虑CPSR的条件位
mul:乘法运算
比较指令
格式:
cmp 第一操作数,第二操作寄存器
比较两个数据
cmp命令本质:实际上就是比较的两个数进行减法运算,并且减法运算的结果会影响到CPSR寄存器的条件位
通常比较指令完毕之后会使用条件码进行判断,根据判断的结果做不同的逻辑
跳转指令
格式:
<opcode>{<cond>} 标签
功能:跳转到指定的标签下
指令码:
b:跳转时不影响LR寄存器的值
ex:.text
.global _start
_start:
mov r1,#3
mov r2,#4
b fun1 @程序跳转
mul r5,r1,r2
stop:
b stop
fun1:
add r4,r1,r2
.end
bl:跳转时影响LR寄存器的值
.text
.global _start
_start:
mov r1,#3
mov r2,#4
bl fun1 @程序跳转
mul r5,r1,r2
stop:
b stop
fun1:
add r4,r1,r2
mov pc,lr @程序返回
.end
实现1~100的和
.text
.globl _start
_start:
MOV R0,#0
MOV R1,#1
MOV R2,#100
FUN:
CMP R1,R2
ADDNE R0,R0,R1
ADDNE R1,R1,#1
BNE FUN
stop:
b stop
.end