)嵌入式linux之常用汇编指令
Posted 衾许°
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了)嵌入式linux之常用汇编指令相关的知识,希望对你有一定的参考价值。
1.处理器内部数据传输指令
数据传输指令分为 一般寄存器间的数据传输或者 特殊寄存器与一般寄存器间的数据传输。数据传输常用的指令有三个: MOV 、 MRS 和 MSR
用法示例:
1 、 MOV 指令MOV R0,R1 @将寄存器 R1 中的数据传递给 R0,即 R0=R1
MOV R0, #0X12 @将立即数 0X12 传递给 R0 寄存器,即 R0=0X12
2
、
MRS
指令
MRS R0, CPSR @将特殊寄存器 CPSR 里面的数据传递给 R0,即 R0=CPSR
3
、
MSR
指令
MSR CPSR, R0 @将 R0 中的数据复制到 CPSR 中,即 CPSR=R0
注:MRS 指令用于将特殊寄存器(如 CPSR 和 SPSR)中的数据传递给通用寄存器,MSR 指令和 MRS 刚好相反,MSR 指令用来将普通寄存器的数据传递给特殊寄存器,也就是写特殊寄存器,写特殊寄存器只能使用 MSR.
我是这样记的:M开头就是传输指令,MOV最好记,MRS与MSR,R就是(READ)读取,强调读取操作,是读取特殊寄存器中的值。或者你可以认为MRS中R代表普通寄存器,S代表special特殊寄存器,而汇编都是反着读的。
2.存储器访问指令
ARM 不能直接访问存储器,比如 RAM 中的数据, I.MX6UL 中的寄存器就是 RAM 类型的,用汇编来配置 I.MX6UL 寄存器的时候需要借助存储器访问指令,一般先将要配置的值写入到Rx(x=0~12) 寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器中。读取 I.MX6UL 寄存器也是一样的,只是过程相反。常用的存储器访问指令有两种:LDR 和STR。用法示例:
1 、 LDR 指令LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
LDR R1, [R0] @读取地址 0X0209C004 中的数据到 R1 寄存器中
2
、
STR
指令
LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002
STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中
注:LDR 和 STR 都是按照字进行读取和写入的,也就是操作的 32 位数据,如果要按照字节、 半字进行操作的话可以在指令“LDR”后面加上 B 或 H,比如按字节操作的指令就是 LDRB 和STRB,按半字操作的指令就是 LDRH 和 STRH。
我是这样记的:LDR和STR指令的作用我其实感觉有点抽象,因为一开始说的MOV,MSR,MRS指令其实就和他们作用貌似完全一致,区别就是LDR与STR是用于读取存储器中的数据的(RAM类寄存器)其实我有点蒙,在我印象里RAM和ROM类型存储介质的区别一个就是掉电丢失与掉电不丢失,另外寄存器加了[]貌似就如C中的取地址符号,这些也是要注意一下的,而STR指令也是唯一一个从右往左读的汇编指令。3.压栈和出栈指令
A 函数中调用 B 函数,当 B 函数执行完以后再回到 A 函数继续执行要想再跳回 A 函数以后代码能够接着正常运行,那就必须在跳到 B 函数之前将当前处理器状态保存起来
当 B 函数执行完成以后再用前面保存的寄存器值恢复 R0~R15 即可。保存 R0~R15 寄存器的操作就叫做现场保护,恢复 R0~R15 寄存器的操作就叫做恢复现场。 在进行现场保护的时候需要进行压栈 ( 入栈 ) 操作,恢复现场就要进行出栈操作。PUSH R0~R3, R12 @将 R0~R3 和 R12 压栈
PUSH LR @将 LR 进行压栈
处理器的堆栈是向下增长的, 栈区示意图:汇编从右往左读,入栈顺序为R12,R3,R2,R1,R0,LR
POP LR @先恢复 LR
POP R0~R3,R12 @在恢复 R0~R3,R12
出栈的就是从栈顶,也就是
SP
当前执行的位置开始,地址依次减小来提取堆栈中的数据到要恢复的寄存器列表中。
我是这样记的:这个就没什么好说了,不懂栈数据类型的建议先补一下栈数据类型,只有PUSH和POP两个指令,比较简单。
4.跳转指令
有多种跳转操作,一般常用的还是 B 、 BL 或 BX。 1 、 B 指令_start:
ldr sp,=0X80200000 @设置栈指针
b main @跳转到 main 函数
2
、
BL
指令
push r0, r1 @保存 r0,r1
cps #0x13 @进入 SVC 模式,允许其他中断再次进去
bl system_irqhandler @加载 C 语言中断处理函数到 r2 寄存器中
cps #0x12 @进入 IRQ 模式
pop r0, r1
str r0, [r1, #0X10] @中断执行完成,写 EOIR
注:BL 指令相比 B 指令,在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行,这是子程序调用一个基本但常用的手段。
5.算术运算指令
汇编中也可以进行算术运算, 比如加减乘除,常用的运算指令用法如下
主要讲解了一些最常用的指令,还有很多不常用的指令没有讲解 , 但是 够我 们后 续学习用了,要想详细的学习 ARM 的 所有 指令 请参 考《 ARM ArchitectureReference Manual ARMv7-A and ARMv7-R edition.pdf》和《 ARM Cortex-A(armV7) 编程手册 V4.0.pdf 》这两份文档。以上是关于)嵌入式linux之常用汇编指令的主要内容,如果未能解决你的问题,请参考以下文章