知识零碎:
跳转指令b: b 指令类似c语言的goto语句,能够实现无条件跳转。跳转时需要一个lable,表示要跳转到什么地方去 如 b finish ,finish就是一个lable(标签)
系统函数finish: 退出仿真器,返回主操作系统
export声明: 在汇编中用export声明函数,同时需要在c语言中用extern声明函数,按照标准,调用者负责保护现场和恢复现场
1、汇编程序于c程序函数相互调用是的传参和返回值规则是什么?
如果参数个数 小于等于4个,就直接用 r0~r3 传参,c函数返回值通过 r0 寄存器返回: 如果参数个数 大于4个,从第 五 个参数开始就需要通过 栈 来传参 (GNU规定)
2、对于函数调用,保护现场和恢复现场是由哪一方负责?
主调函数负责保护现场和恢复现场
3、读写cpsr寄存器的指令是什么?
cpsr寄存器的低5位(M位)来设置的,那么就可以先把cpsr读出来,更改低5位之后再设置进去。
读cpsr使用mrs指令 写cpsr寄存器用msr 指令
需要注意的是在keil环境下写cpsr需要写成: msr cpsr_c r0;将r0的值写入到cpsr寄存器
4、入栈和出栈操作使用的指令是什么?
入栈保护指令 stmfd storage(存储)
STMFD<c> <Rn>{!}, <registers>
Rn 表示 栈底 指针寄存器,< registers >表示需要 入栈保护 的寄存器 ! 表示 入栈 之后sp自动自减。如:
stmfd sp!, {r0, r1, r2, r3-r12, lr}
出栈恢复指令 ldmfd load(加载)
LDMFD<c> <Rn>{!}, <registers>
Rn 表示栈底指针寄存器,< registers >表示需要入栈保护的寄存器 ! 表示 出栈 之后sp自动自增。
ldmfd sp!, {r0, r1, r2, r3-r12, lr}
5.栈的实现类型:
2440实现保护和恢复现场使用的栈是 数组栈,即用一段连续的内存空间为栈提供空间。从数组栈的具体实现来看入栈的方式有四种做法:
- 空增:先写入数据,再让栈指针自增;
- 空减:先写入数据,再让栈指针自减;
- 满增:先让栈指针自增,再写入数据;
- 满减:先让栈指针自减,再写入数据。
arm体系采用的方案是 满减 1.我们必须先告诉2440栈底的位置,这里我们把栈底设置为0x40001000 2.从地址0x40000000开始的0x1000这段内存空间对应的是2440内部的一段ram,总共4k。 3.实际能够使用的内存空间为[0x40000000~0x40000FFF] 4.设置栈底指针寄存器: ldr sp =0x40001000
6.汇编指令的s后缀有什么用?
几乎所有的汇编指令都可以在指令后面加上s后缀 s后缀的含义: 是在指令执行过程中会 更新cpsr寄存器的N,V,C,Z位
N: 在结果是有符号的二进制补码情况下,如果结果为负数,则N=1;如果结果为非负数,则N=0
Z: 如果结果为0,则Z=1;如果结果为非零,则Z=0
C: 是针对无符号数最高有效位向更高位进位时C=1;减法中运算结果的最高有效位从更高位借位时C=0
V: 该位是针对有符号数的操作,会在下面两种情形变为1,两个最高有效位均为0的数相加,得到的结果最高有效位为1;两个最高有效位均为1的数相加,得到的结果最高有效位为0;除了这两种情况以外V位为0
例如:
mov r0, #0xFFFFFFFF
adds r1, r0, #1
上面的操作会导致Z,C置位,这是因为结果为0,并且从无符号数角度来看,已经从最高位向更高位进位了
而
mov r0. #0x7FFFFFFF
adds r1, r0, #1
会造成N位和C位置位,这是因为计算结果0x80000000最为位为1,代表负数,并且 从有符号角度来看,把一个整数加成了负数。
汇编指令的启动代码
---------------------------------------------------------------------------------------------------------------------------------
preserve8
area reset, code, readonly
code32
entry
b start
nop
nop
nop
nop
nop
b do_interrput
nop
start
ldr sp, =0x40001000
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x12
bic r0, r0, #(0x01 << 7)
msr cpsr_c, r0
ldr sp, =0x40001000
sub sp, sp, #1024
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x10
msr cpsr_c, r0
ldr sp, =0x40001000
sub sp, sp, #2048
import main
b main
do_interrput
sub lr, lr, #4
stmfd sp!, {r0-r12, lr}
import interrupt_handle
bl interrupt_handle
ldmfd sp!, {r0-r12, pc}^ (^:切换user模式和supervisor模式)
end
---------------------------------------------------------------------------------------------------------------------------
常用指令后缀和条件判断
EQ : 等于
NE : 不等
CS : 无符号>=
CC : 无符号<
MI : 负数
PL : 非负[>=0]
VS : 溢出
VC : 无溢出
HI : 无符号>
LS : 无符号<=
GE : 有符号>=
LT : 有符号<
GT : 有符号>
LE : 有符号<=