一、立即数
立即数判断规则:
-
如果某个数的数值范围是0~255之间,那么这个数一定是立即数;
-
把某个数展开成2进制,这个数的最高位1至最低位1之间的二进制数序列的位数不能超过8位;
-
这个数的二进制序列的右边必须为偶数个连续的 0
例:①0x3f4 = 0000 0000 0000 0000 0000 0011 1111 0100
最高位1至最低位1之间的二进制数序列:1111 1101 从第一个1开始到最后一个1之间没有超过8位
末尾1的右边有2个0,所以0x3f4是立即数
②0x132 = 0000 0000 0000 0000 0000 0001 0011 0010
最高位1至最低位1之间的二进制数序列:1001 1001 从第一个1开始到最后一个1之间没有超过8位
末尾1的右边有1个0,不满足第二条,所以0x132不是立即数
为什么最高位1至最低位1之间的二进制数序列的位数不能超过8位?
- 因为在ARM中将这 12bits 分为 8bit 常数(0~255)和 4bit 循环右移位值(0~15),只有8bit常数位,只能存下8位。
为什么立即数的二进制序列的右边必须为偶数个连续的 0
- 因为在ARM中将这 12bits 分为 8bit 常数(0~255)和 4bit 循环右移位值(0~15),循环右移位值步进是2,如果是奇数个连续的0,在提取其中的最高位1至最低位1之间的二进制数序列后,移动偶数次无法得到右边奇数个连续0的二进制序列,和立即数的二进制序列不相同。
二、基础汇编指令
1、mov指令
加载立即数到寄存器或转移一个寄存器的值到另外一个寄存器,数字压缩到代码里面
MOV{S}<c> <Rd>, #<const>
eg:mov r0, #2 ;加载立即数2到寄存器r0。
MOV{S}<c> <Rd>, <Rm>
eg:mov r1, r0 ;将r0寄存器的值加载到r1。
2、add指令
ADD{S}<c> <Rd>, <Rn>, #<const>
ADDS}<c> <Rd>, <Rn>, <Rm>{, <shift>}
3、sub指令
SUB{S}<c> <Rd>, <Rn>, #<const>
SUB{S}<c> <Rd>, <Rn>, <Rm>{, <shift>}
4、ldr寄存器加载指令
用于将数据从内存加载到寄存器中,是一条伪指令,将数字放入代码区
LDR{<c>}{<q>} <Rt>, <label> ;
如:ldr r0, =0x2FAB4
ldr指令多用于从ram中将一个32位的字数据传送到目的寄存器中
LDR<c> <Rt>, [<Rn>{, #+/-<imm12>}]
如:LDR R0,[R1,#8];将内存地址为R1+8的字数据读入寄存器R0,这里的#8作为12位立即数是可以省略的。
通过r0指向的数将数保存到r1中,此时r0是一个指针
LDR<c> <Rt>, [<Rn>], #+/-<imm12>
如:ldr r0, [r1], #8 ;将内存地址R1的字数据读入r0,之后r1+8
LDR<c> <Rt>, [<Rn>, #+/-<imm12>]!
如:LDR R0,[R1,#8] !;将存储器地址为R1+8的字数据读入寄存器R0,并将新地址R1+8写入R1。
5、bic指定位清零指令
BIC{S}<c> <Rd>, <Rn>, #<const>;
将rn中的字数据const为1的比特清零,把结果放入rd。<const>的反码与<Rn>按位逻辑与
6、orr指定位置位指令:
ORR{S}<c> <Rd>, <Rn>, #<const> 按位逻辑或
三、指令b,bx,bl的主要区别
b 无条件跳转到指定的标签
bl无条件跳转到指定的标签,并将返回地址保存到链接寄存器(LR,通常是R14)
bx跳转到指定寄存器的地址,并根据地址的最低有效位选择ARM或Thumb状态。
在 ARM 汇编中,SWI(Software Interrupt)指令用于生成软件中断,通常用于请求操作系统服务或调用特定的系统功能。SWI #7 表示生成一个软件中断,传递的参数是 #7。
当执行 SWI #7 时,处理器会跳转到一个预定义的中断处理程序,该程序会根据 #7 的值来执行特定的操作。具体的操作取决于操作系统的实现。例如,在某些系统中,SWI #7 可能被用来请求特定的系统调用,如获取系统时间或处理文件操作。
四、程序状态寄存器
(1)条件码标志
N、Z、C、V,最高4位称为条件码标志。ARM的大多数指令可以条件执行的,即通过检测这些条件码标志来决定程序指令如何执行。
各个条件码的含义如下:
N:在结果是有符号的二进制补码情况下,如果结果为负数,则N=1;如果结果为非负数,则N=0。
Z:如果结果为0,则Z=1;如果结果为非零,则Z=0。
C:其设置分一下几种情况:
对于加法指令(包含比较指令CMN),如果产生进位,则C=1;否则C=0。
对于减法指令(包括比较指令CMP),如果产生借位,则C=0;否则C=1。
对于有移位操作的非法指令,C为移位操作中最后移出位的值。
对于其他指令,C通常不变。
V:对于加减法指令,在操作数和结果是有符号的整数时,如果发生溢出,则V=1;如果无溢出发生,则V=0;对于其他指令,V通常不发生变化。
五、C语言和汇编语言的调用
调用函数时所传递的参数是:r0 r1 r2 r3作为前四个参数;第五个参数以后通过栈来传递。返回值通过r0传递。pop push,
谁调函数,谁保护现场恢复现场
六、三种模式切换及异常处理
preserve8
area reset, code, readonly
code32
entry
b start
ldr pc, =do_undifined
ldr pc, =do_swi
ldr pc, =do_p_abort
ldr pc, =do_d_abort
nop
ldr pc, do_irq
ldr pc, do_fiq
do_fiq
b do_fiq
do_irq
import irq_handler
sub lr, lr, #4
stmfd sp!, {r0-r12, lr}
bl irq_handler
ldmfd sp!, {r0-r12, pc}^
do_d_abort
b do_d_abort
do_p_abort
b do_p_abort
do_swi
import swi_handler
stmfd sp!, {r0-r12, lr} ;入栈,保护现场
bl swi_handler
ldmfd sp!, {r0-r12, pc}^ ;出栈,恢复现场,并切换回原来的工作模式
do_undifined
b do_undifined
start
ldr sp, =0x40001000 ;svc_sp
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x12
bic r0, #(1 << 7) ;中断禁止位,禁止irq
msr cpsr_c, r0
ldr r0, =0x40001000
sub r0, r0, #1024
mov sp, r0
mrs r0, cpsr ;读
bic r0, r0, #0x1F ;irq到user模式
orr r0, r0, #0x10
msr cpsr_c, r0 ;写
ldr r0, =0x40001000
sub r0, r0, #2048
mov sp, r0
import main
b main
asm_fn
export asm_fn
swi #7
bx lr
finished
b finished
end
extern void asm_fn(void);
void swi_handler(void)
{
}
void irq_handler(void)
{
}
int main(void)
{
while(1)
{
}
return 0;
}