学习汇编的目的
ARM汇编的主要目的是为了编写ARM启动代码,启动代码启动以后,引导程序到c语言环境下运行。启动代码的主要任务有:
1.初始化异常向量表;
2.初始化各工作模式的栈指针寄存器
3.开启arm内核中断允许
4.将工作模式设置为user模式
5.引导程序进入C语言主函数执行
1.汇编代码格式(注意加空格)
伪操作:
area reset ,code,readonly
code32
entry
end
area: 这是最重要的一个伪操作,用于定义一个段。程序、数据、堆栈等都需要被组织在不同的段中。
reset: 这是你为这个段起的名字。名字 reset 具有很强的暗示性,通常用于表示复位向量段,即CPU上电或复位后首先执行的第一段代码所在的位置。
code: 指定该段的属性为代码,意味着这个段包含可执行的指令。
readonly: 指定该段的属性为只读。对于代码段来说,这通常是默认且必须的。
code32: 表示后续指令使用 32位的 ARM 指令集。
thumb: 表示后续指令使用 16位的 Thumb 指令集。
2.指令
1.mov
MOV{S}<c> <Rd>, #<const>
MOV{S}<c> <Rd>, <Rm>
注意:#<n>/<Rs> 取值范围 (0 - 31)
MOV instruction Canonical form
MOV{S} <Rd>, <Rm>, ASR #<n> ASR{S} <Rd>, <Rm>, #<n>
MOV{S} <Rd>, <Rm>, LSL #<n> LSL{S} <Rd>, <Rm>, #<n>
MOV{S} <Rd>, <Rm>, LSR #<n> LSR{S} <Rd>, <Rm>, #<n>
MOV{S} <Rd>, <Rm>, ROR #<n> ROR{S} <Rd>, <Rm>, #<n>
MOV{S} <Rd>, <Rm>, ASR <Rs> ASR{S} <Rd>, <Rm>, <Rs>
MOV{S} <Rd>, <Rm>, LSL <Rs> LSL{S} <Rd>, <Rm>, <Rs>
MOV{S} <Rd>, <Rm>, LSR <Rs> LSR{S} <Rd>, <Rm>, <Rs>
MOV{S} <Rd>, <Rm>, ROR <Rs> ROR{S} <Rd>, <Rm>, <Rs>
MOV{S} <Rd>, <Rm>, RRX RRX{S} <Rd>, <Rm>
例:mov r0,#0x8
mov r1,r0
2.add(加法)
立即数作为第二操作数: ADD{S}<c> <Rd>, <Rn>, #<const>
寄存器作为第二操作数寄存器: ADD{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
寄存器作为第二操作数移位量: ADD{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
例:add r6,r0,#0xF0
add r7,r0,r1
add r7,r0, r1, lsl #1
add r7, r0, r1, lsl r2
3.sub(减法)
立即数作为第二操作数: SUB{S}<c> <Rd>, <Rn>, #<const>
寄存器作为第二操作数寄存器: SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
寄存器作为第二操作数移位量: SUB{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
和add类似
4.ldr(加载指令)
LDR<c> <Rt>, <label>
5.mvn(按位取反移动指令)
MVN{S}<c> <Rd>, #<const>{, <shift>}
MVN{S}<c> <Rd>, <Rm>
MVN{S}<c> <Rd>, <Rm>, <type> <Rs>
6.bic(bit clear):指定位清零
BIC{S}<c> <Rd>, <Rn>, #<const>
BIC{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
BIC{S}<c> <Rd>, <Rn>, <Rm>, <type> <Rs>
例:
mov r0, #0xFFFFFFFF
mov r1, #1
bic
7.循环
(1)do...while(C)
int i = 0;
int sum = 0;
do{
sum += i;
i++;
}while(i <= 100)
汇编:
mov r0, #0
mov r1, #0
loop
add r1, r1, r0
add r0, r0, #1
cmp r0, #100
ble loop
(2)int i = 0;
int sum = 0;
while(i <= 100)
{
sum += i;
i++;
}
汇编:while;
mov r0, #1
mov r1, #0
lable
cmp r0, #1000
bgt finish
add r1, r1, r0
add r0, r0, #1
b lable
3.立即数
1.定义:计算机指令中直接包含在指令本身中的常数值,是CPU在执行指令时可以直接使用的数值,一般小于255的数
- 12位立即数判断标准:把某个数展开成2进制,该数必须存在一种循环右移(偶数位),使得移位后高24位全0,低8位即为有效imm8;
4.b, bl, bx 的区别
|----|---------------------------|-------------------------------------------|
| 类型 | 功能 | 特点 |
| b | 最简单的跳转,类似于goto | 不保存返回地址, 不会自动返回 用于循环、条件分支、函数内跳转 |
| bl | 跳转到目标地址, 将下一条指令地址保存到LR寄存器 | 用于函数调用, 被调函数通常以 bx lr 或 mov pc, lr 返回 |
| bx | 跳转到寄存器指定的地址, | 目标地址由寄存器指定(间接跳转) 常用于函数返回和模式切换 |
5.ARM内核采用的栈
默认采用满减栈:栈顶指针SP始终指向已存数据的最后一个位置(栈非空时,SP指向有效数据);
栈增长方向为地址递减,入栈时SP先减4再存入数据,出栈时先读取数据,SP再加4
6.CPSR中条件标志位,分别在什么情况下被置位
|-----|--------|--------------------------------------|
| 标志位 | 名称 | 置位条件 |
| N | 符号位标志位 | 最高位位1,结果位负时 |
| Z | 零值标记位 | 结果为0 |
| C | 进位标志位 | 无符号:加法运算时最高位向更高位进位时或减法运算时最高位无借位(大-小) |
| V | 溢出标志位 | 有符号:"两个正数相加得负数" 或 "两个负数相加得正数" |
7.arm汇编调用c语言函数以及c语言函数调用汇编编写的函数,函数参数和返回值如何处理?
(1)arm汇编调用C语言
函数参数:
1.前四个参数依次放在r0,r1,r2,r3
2.如果参数超过四个,多余的参数会从右到左依次压入栈中
返回值:
通过寄存器r0返回
(2)C语言调用汇编
函数参数:
与汇编调用C语言一致
返回值:
汇编函数直接读取寄存器或栈位置
需保存被调用的寄存器(r0-r12,lr)