u-boot 代码中常见汇编指令

在嵌入式开发中,汇编程序常常用于非常关键的地方,比如系统启动时初始化,进出中断时的环境保护,恢复等对性能有要求的地方。

ARM指令集可以分为六大类,分别为数据处理指令Load/Store指令跳转指令程序状态寄存器处理指令协处理器指令异常产生指令
ARM 指令使用的基本格式如下:
〈opcode〉{〈cond〉}{S}     〈Rd〉,〈Rn〉{,〈operand2〉}
opcode 操作码;指令助记符,如LDR、STR等。
cond 可选的条件码;执行条件,如EQ、NE等。
S 可选后缀;若指定“S”,则根据指令执行结果更新CPSR中的条件码。
Rd 目标寄存器。
Rn 存放第1操作数的寄存器。
operand2 第2个操作数
 
arm的寻址方式如下:
立即寻址
寄存器寻址
寄存器间接寻址
基址加偏址寻址
堆 栈寻址
块拷贝寻址
相对寻址
这里不作详细描述,可以查阅相关文档。
 
数据处理指令
Load/Store 指令
程序状态寄存器与通用寄存器之间的传送指令
转移指令
异常中断指令
协处理器指令

 

1、 相对跳转指令:b、bl

其中bl除了跳转之外,还将返回地址保存在lr寄存器中。这两条指令的可跳转范围是当前指令的前后32MB。它们是位置无关的指令。

b funa
....
funa:
    b funb
....
funb:
....

2、数据传送指令mov,地址读取伪指令ldr
mov指令可以把一个寄存器的值赋给另外一个寄存器,或者把一个常数赋给寄存器。
mov r1, r2
/*上面是r1 = r2*/
mov r1,#1024
/*r1 = 1024*/

mov传送的常数必须能用立即数来表示。当不能用立即数表示时,可以用ldr命令来赋值。
ldr是伪命令,不是真实存在的指令,编译器会 把它扩展成真正的指令;如果该常数能用“立即数”来表示,则使用mov指令,否则编译时将该常数保存在某个位置,使用内存读取指令把它读出来。
ldr r1, = 1024
/*r1 = 1024*/

3、内存访问指令 ldr、str、ldm、stm
ldr既可以指地址读取伪指令,也可以是内存访问指令。当他的第二个参数前面有'='时标伪 指令,否则表内存访问指令。
ldr指令从内存中读取数据到寄存器,str指令把寄存器的指存储到内存中,他们的操作数都是32位的。
 
ldr r1, [r2, #4] /*将地址为r2+4的内存单元数据读取到r1中*/
ldr r1,[r2] /*将地址为r2的内存单元数据读取到r1中*/
ldr r1,[r2], #4/*将地址为r2的内存单元数据读取到r1中,然后r2=r2+4*/
str r1 ,[r2, #4]/*将r1的数据保存到地址为r2+4的内存单元中*/
str r1, [r2]/*将r1的数据保存到地址为r2的内存单元中。*/
str r1, [r2],#4/*将r1的数据保存到地址为r2的内存单元,然后r2= r2+4*/

 

批量数据加载/存储指令LDM(或 STM)指令的格式为:
LDM(或 STM){条件}{类型} 基址寄存器{!},寄存器列表{∧}
LDM(或 STM)指令用于从由基址寄存器所指示的一片连续存储器到寄存器列表所指示的多个寄存器之间传送数据,该指令的常见用途是将多个寄存器的内容入栈(SDM)或出栈(LDM)。其中,{类型}为以下几种情况:
IA  每次传送后地址加 1;
IB  每次传送前地址加 1;
DA  每次传送后地址减 1;
DB  每次传送前地址减 1;
FD  满递减堆栈;
ED  空递减堆栈;
FA  满递增堆栈;
EA  空递增堆栈;

ldmia   r0!, {r3-r10}  /*将基址寄存器r0开始的连续8个地址单元的值分别赋给r3,r4,r5,r6,r7,r8,r9,r10,注意的是r0指定的地址每次赋一次r0会加1,

指向下一个地址单元*/

stmia   r1!, {r3-r10} /*跟上面指令功能相反,将寄存器r3到r10的值依次赋值给r1指定的地址单元,每次赋值一次r1就加1*/

 

4,CMP 指令的格式
CMP{条件} 操作数 1,操作数 2
CMP 指令用于把一个寄存器的内容和另一个寄存器的内容或立即数进行比较,同时更新 CPSR 中条件标志位的值。该指令进行一次减法运算,但不存储结果,只更改条件标志位。标志位表示的是操作数 1 与操作数 2 的关系(大、小、相等),例如,当操作数 1 大于操作操作数 2,则此后的有 GT 后缀的指令将可以执行。
指令示例:
CMP R1,R0  ;将寄存器R1的值与寄存器R0的值相减,并根据结果设置CPSR的标志位
CMP R1,#100 ;将寄存器R1的值与立即数100相减,并根据结果设置CPSR的标志位

copy_loop:
        ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
        stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
        cmp     r0, r2                  /* until source end addreee [r2]    */
        ble     copy_loop /*比较r0和r2的值,如果不相等则重新跳到copy_loop处*/

 

5,ORR 指令的格式
ORR{条件}{S} 目的寄存器,操作数 1,操作数 2
ORR 指令用于在两个操作数上进行逻辑或运算,并把结果放置到目的寄存器中。操作数 1应是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即数。该指令常用于设置操作数 1 的某些位。
指令示例:
ORR   R0,R0,#3             ; 该指令设置R0的0、1位,其余位保持不变。

 

6,BIC 指令的格式
BIC{条件}{S} 目的寄存器,操作数 1,操作数 2
BIC指令用于清除操作数1 的某些位,并把结果放置到目的寄存器中。操作数 1 应是一个寄存器,操作数 2 可以是一个寄存器,被移位的寄存器,或一个立即数。操作数 2 为 32 位的掩码,如果在掩码中设置了某一位,则清除这一位。未设置的掩码位保持不变。
指令示例:
BIC   R0,R0,#%1011     ; 该指令清除 R0 中的位 0、1、和 3,其余的位保持不变。

 

7、程序状态寄存器的访问指令msr,mrs

ARM指令中有两条指令,用于在状态寄存器和通用寄存器之间传送数据。修改状态寄存器一般是通过“读取-修改-写回”三个步骤的操作来实现的。 这两条指令分别是:
状态寄存器到通用寄存器的传送指令(MRS)
通用寄存器到状态寄存器的传送指令(MSR)

其汇编格式如下:
MRS{<cond>} Rd,CPSR|SPSR
其汇编格式如下:
MSR{<cond>} CPSR_f | SPSR_f,#<32-bit immediate>
MSR{<cond>} CPSR_<field> | SPSR_<field>,Rm

msr cpsr, r0 /*复制r0到cpsr中*/
mrs r0, cpsr /*复制cpsr到r0中*/

 

例:下面这段代码是在u-boot中将cpu设置为SVC32模式

        mrs     r0,cpsr
        bic     r0,r0,#0x1f
        orr     r0,r0,#0xd3 /*通过这两条指令可以看到将后面5位设置为10011也就是管理模式,将6,7位设置为1也就是禁止IRQ和FIQ*/
        msr     cpsr,r0

可以来看看程序状态寄存器CPSR中各个位分别表示什么含义:

CPSR_f或SPSR_f CPSR_s或SPSR_s CPSR_x或SPSR_x CPSR_c或SPSR_c
31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
N Z C V - - - - - - - - - - - - - - - - - - - - I F T M4 M3 M2 M1 M0












保留位 IRQ



1



0

FIQ



1



0
允 许




0
ARM

1
Thumb
模式位
10000-0x0010-用户
10001-0x0011- 快速中断
10010-0x0012-中断
10011-0x0013-管理
10111-0x0017-未定义
11111-0x001F- 系统

 

8,MCR 指令的格式

MCR{条件} 协处理器编码,协处理器操作码1,源寄存器,目的寄存器1,目的寄存器2,协处

理器操作码2。

MCR 指令用于将ARM 处理器寄存器中的数据传送到协处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,源寄存器为ARM 处理器的寄存器,目的寄存器1 和目的寄存器2 均为协处理器的寄存器。

指令示例:

MCR P3 , 3 , R0 , C4 , C5 , 6 ;该指令将 ARM 处理器寄存器 R0 中的数据传送到协处理器 P3 的寄存器 C4 和 C5 中。

 

MRC 指令的格式

MRC{条件} 协处理器编码,协处理器操作码1,目的寄存器,源寄存器1,源寄存器2,协处理

器操作码2。

MRC 指令用于将协处理器寄存器中的数据传送到ARM 处理器寄存器中,若协处理器不能成功完成操作,则产生未定义指令异常。其中协处理器操作码1 和协处理器操作码2 为协处理器将要执行的操作,目的寄存器为ARM 处理器的寄存器,源寄存器1 和源寄存器2 均为协处理器的寄存器。

指令示例:

MRC P3 , 3 , R0 , C4 , C5 , 6 ;该指令将协处理器 P3 的寄存器中的数据传送到 ARM 处理器寄存器中.

 

例:这是u-boot中一段代码

        mov     r0, #0
        mcr     p15, 0, r0, c7, c7, 0   /* flush v3/v4 cache */将r0的值也就是0赋值给协处理器p15的c7寄存器
        mcr     p15, 0, r0, c8, c7, 0   /* flush v4 TLB */

有必要来看看arm中CP15协处理器中各个寄存器的意义:

 

寄存器编号

基本作用

MMU 中的作用

PU 中的作用

0

ID 编码(只读)

ID 编码和 cache 类型

 

1

控 制位(可读写)

各 种控制位

 

2

存 储保护和控制

地 址转换表基地址

Cachability 的控制位

3

存 储保护和控制

域 访问控制位

Bufferablity 控制位

4

存 储保护和控制

保 留

保 留

5

存 储保护和控制

内 存失效状态

访 问权限控制位

6

存 储保护和控制

内 存失效地址

保 护区域控制

7

高 速缓存和写缓存

高 速缓存和写缓存控制

 

8

存 储保护和控制

TLB 控制

保 留

9

高 速缓存和写缓存

高 速缓存锁定

 

10

存 储保护和控制

TLB 锁定

保 留

11

保 留

 

 

12

保 留

 

 

13

进 程标识符

进 程标识符

 

14

保 留

 

 

15

因 不同设计而异

因 不同设计而异

因 不同设计而异

主要来看看里面c7和c8两个寄存器的意思:

CP15 C7 寄存器用来控制 cache 和写缓存,它是一个只写寄存器,读操作将产生不可预知的后果。

CP15 C8 寄存器用来控制清除 TLB 的内容,是只写寄存器,读操作将产生不可预知的后果。

 

9、 其它伪指令

常见如下:
.extern    main

.text

.global   _start

_start:

“.extern”定义一个外部符号,上面的代码表示本文件中引用的main是一个外部函数。

“.text”表示下面的语句都属于代码段。

“.global”将本文件中的某个程序标号定义为全局的。

 

说说这个.word伪指令的作用。
.word expression就是在当前位置放一个word型的值,这个值就是expression
举例来说,
_rWTCON:  .word 0x15300000
就是在当前地址,即_rWTCON处放一个值0x15300000
翻译成intel的汇编语句就是:
_rWTCON dw 0x15300000
就是在当前位置放个expression的值。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值