一、ARM汇编指令
1.move
move{s}<c> <rd>, <rm>
2.add
1)add{s}<c><rd>, <rn>,#<const>
add r0, r1, #1
2)add{s}<c><rd>, <rn>, <rm> {,<shift>}
add r0, r1, r2
3)add{s}<c><rd>, <rn>, <rm> , <type> <rs>
add r0, r0, r1, lsl, r1
3.sub
1)sub{s}<c><rd>, <rn>,#<const>
sub r0, r1, #1
2)sub{s}<c><rd>, <rn>, <rm> {,<shift>}
sub r0, r1, r2
3)sub{s}<c><rd>, <rn>, <rm> , <type> <rs>
sub r0, r0, r1, lsl, r1
tips:立即数(immediate)
定义:指令中可以直接包含的常数
1)数值范围在0~0xFF之间,这个数一定是立即数
2)把数展开为二进制数,最高位及最低位之间的位数不能超过8
3)把数展开位二进制数,右边0的个数,必须是偶数
1 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 |
在arm中存取数据,一个数占12个比特,但是arm为了让存的数字更大,将前四位设置为旋转位,现在后八位是0xFA,如果要存0xFA00,就要将当前的数字循环右移24次,旋转位填循环次数的1/2。
当不是立即数时,但是又用到mov,此时编译器会自动调用mvn,mvn的存取方式是先对操作数按位取反再进行存取
4.ldr
ldr的作用是从ram或指定的地址加载数据到通用寄存器中
ldr<c><rt>, [<rn>{,#+/-<imm12>}]
ldr r1, [r0]
这行代码的作用是将r0寄存器的内容放到r1
tips:ram对内存的划分
0xFFFFFFFF-1 |
0x40001000 |
0x40000FFF |
0x40000000 |
0x20000 |
0x1FFFF |
0x00000000 |
0x00000000~0x1FFFF:代码区(nor flash)
0x40000000~0x40000FFF:片上RAM(变量存放)
其他空白空间:外设寄存器
5.str
str的作用是把通用寄存器中的数据加载到ram或指定的地址
str r1, [r0]
这行代码的作用是将r1的内容写到r0中
6.bic
作用:指定位清零
bic{s}<c> <rd>, <rn>, #<const>
7.orr
作用:指定位置一
orr{s}<c> <rd>, <rn>, #<const>
8.跳转
b:跳转到标识符,不改变链接寄存器
bl:跳转到标识符,改变链接寄存器
bx:后面跟寄存器地址,作用是将这个地址装入pc
9.stmfd
入栈,保护现场
stmd<c> <rn> {!}, <registers>
加上感叹号表示sp栈指针可变,registers表示用列表的形式写要保存的寄存器地址
10.ldmfd
出栈,恢复现场
ldmd<c> <rn> {!}, <registers>
加上感叹号表示sp栈指针可变,registers表示用列表的形式写要保存的寄存器地址
11.mrs
读取某个特殊寄存器
mrs<c> <rd>, <spec_reg>
12.msr
读取通用寄存器
msr<c> <spec_reg>, <rd>
二、汇编模拟
1.cpsr
n | z | c | v |
有符号时,结果为负的情况 下置一,正置零 |
结果为零,置一 | 无符号的情况下 进位置一,借位置零 |
有符号的情况下,俩个最高位位0的数相加结果为1,最高位为1相加0,置一 |
作用:可以根据这四位实现c语言中if else的作用
加上后缀就可以实现
三、函数调用
tips:栈
空栈:入栈时,先入栈再挪
满栈:入栈时,先挪再入栈
增栈:入栈地址由低到高
减栈:入栈地址由高到低
在keil中,
汇编调c
1)保护现场
2)import声明
3)用r0~r3或者栈来传参
4)bl跳转
5)恢复现场
c调汇编
1)用extern声明
2)函数调用(在keil下,需要在汇编里加export 函数名,来声明函数)
3)靠r0把结果返回c,需要在汇编里面把结果写入r0
谁调用,谁保护恢复现场
四、代码
ldr pc, =_start
_asm_max
mov r0, #0
mov r1, #1
stmfd sp!, {r0-r12, lr}
bl _asm_min
ldmfd sp!, {r0-r12, lr}
cmp r0, r1
movge r2, r0
movge r2, r1
bx lr
_asm_min
cmp r0, r1
movge r2, r1
movge r2, r0
mov r0, r2
bx lr
_start
ldr sp, =0x40001000
//调用汇编
;stmfd sp!, {r0-r12, lr}
;bl _asm_max
;ldmfd sp!, {r0-r12, lr}
//调用c程序
import c_max
mov r0, #1
mov r1, #2
bl c_max
ldr sp, =0x40001000
sub sp, sp, #1024
finished
b finished
end
sp需要布局,因为每个模式都有自己独立的sp