本文介绍: 汇编知识很庞大,本章我们讲解最常用的一些指令,即标号,表示地址位置,有些指令前面可能会有标号,这样就可以通过这个标号得到。汇编还有其它的伪操作,但是最常见的就是上面这些,如果想详细的了解全部的伪操。的编译器不同,因此对于汇编语法就有一些小区别汇编函数返回语句不是必须的,如下代码就是用汇编写的。指令用来将普通寄存器数据传递给特殊寄存器,也就。指令地址标号也可以用来表示数据地址。”指令返回指令函数返回语句不是必须的。都是按照字进行读取写入的,也就是操作的。在进行现场保护的时候需要进行压栈。
       我们学习 STM32
的时候几乎没有用到过汇编,可能在学习
UCOS

FreeRTOS

RTOS
操作系统移植的时候可能会接触到一点汇编。但是我们在进行嵌入式
Linux
开发的时候是绝
对要掌握基本
ARM
汇编,因为
Cortex-A
芯片一上电
SP
指针还没初始化
C
环境还没准备
好,所以肯定不能运行
C
代码,必须先用汇编语言设置
C
环境比如初始化
DDR
设置
SP
指针等等,当汇编把
C
环境设置好了以后才可以运行
C
代码。所以
Cortex-A
一开始肯定是汇
代码,其实
STM32
也一样的,一开始也是汇编,以
STM32F103
为例,启动文件
startup_stm32f10x_hd.s
就是汇编文件,只是这个文件
ST
已经写好了,我们根本不用去修改,所
以大部分学习者都没有深入的去研究。汇编的知识很庞大,本章我们讲解最常用的一些指令
满足我们后续学习即可

一.GNU 汇编语法

如果大家使用
STM32
的话就会知道
MDK

IAR
下的启动文件
startup_stm32f10x_hd.s
其中的汇编语法是有所不同的,将
MDK
下的汇编文件直接复制
IAR
下去编译就会出错,因

MDK

IAR
编译器不同,因此对于汇编的语法就有一些小区别我们要编写的是
ARM
汇编,编译使用
GCC
交叉编译器,所以我们的汇编代码要符合
GNU
语法
GNU
汇编语法用于所有的架构,并不是
ARM
独享的,
GNU
汇编由一系列语句组成,
每行一条语句,每条语句有三个可选部分,如下
label
标号,表示地址位置,有些指令前面可能会有标号,这样就可以通过这个标号得到
指令地址标号也可以用来表示数据地址。注意
label
后面的“:”,任何以“:”结尾的标识
符都会被识别一个标号
instruction
指令,也就是汇编指令或伪指令。
@
符号,表示后面的是注释,就跟
C
语言里面的“
/*
”和“
*/
”一样,其实在
GNU
汇编文
件中我们也可以使用
/*
”和“
*/
”来注释
comment
就是注释内容
add:
MOVS R0, #0X12 @
设置
R0=0X12
上面代码中“
add:
”就是标号,“
MOVS R0,#0X12
”就是指令,最后的“
@
设置
R0=0X12
”就是
注释。
.data
初始化的数据段。
.bss
初始化的数据段。
.rodata
只读数据段。
我们当然可以自己使用
.section
定义一个段,每个段以段名开始,以下一段名或者文件
结束比如
编程序的默认入口标号是
_start
,不过我们也可以在链接脚本使用
ENTRY
来指明其它
的入口点,下面的代码就是使用
_start
作为入口标号:
_start:
ldr r0, =0x12 @r0=0x12
上面代码
.global
是伪操作,表示
_start
一个全局标号,类似
C
语言里面全局变量
样,常见的伪操作有:
.byte
定义单字节数据,比如
.byte 0x12
.short
定义字节数据,比如
.short 0x1234
.long
定义一个
4
字节数据,比如
.long 0x12345678
.equ
赋值语句,格式为:
.equ
变量名表达式比如
.equ num, 0x12
,表示
num=0x12
.align
数据字节对齐比如
.align 4
表示
4
字节对齐。
.end
表示源文件结束。
.global
定义一个全局符号格式为:
.global symbol
比如
.global _start
GNU
汇编还有其它的伪操作,但是最常见的就是上面这些,如果想详细的了解全部的伪操
作,可以参考
ARM Cortex-A(armV7)
编程手册
V4.0.pdf
》的
57
页。
GNU
汇编同样也支持函数函数格式如下
函数
:
函数
返回语句
GNU
汇编函数返回语句不是必须的,如下代码就是用汇编写的
Cortex-A7
中断服务函数:
示例代码 7.1.1.1 汇编函数定义
/*
定义中断
*/
Undefined_Handler
:
ldr r0
, =
Undefined_Handler
bx r0
/* SVC
中断
*/
SVC_Handler
:
ldr r0
, =
SVC_Handler
bx r0
/*
预取终止中断
*/
PrefAbort_Handler
:
ldr r0
, =
PrefAbort_Handler
bx r0
上述代码中定义了三个汇编函数:
Undefined_Handler

SVC_Handler
PrefAbort_Handler
。以函数
Undefined_Handler
为例我们来看一下汇编函数组成,

Undefined_Handler
”就是函数名,“
ldr r0, =Undefined_Handler
”是函数体,“
bx r0
”是函数
返回语句,“
bx
”指令是返回指令,函数返回语句不是必须的。

二.处理器内部数据传输指令

三个指令:
1

MOV
指令
MOV
指令用于将数据从一个寄存器拷贝到另外一个寄存器,或者将一个立即数传递到寄
MOV R0

R1
@
寄存器
R1
中的数据传递给
R0
,即
R0=R1
MOV R0, #0X12
@
将立即数
0X12
传递给
R0
寄存器,即
R0=0X12
2

MRS
指令
MRS
指令用于将特殊寄存器
(

CPSR

SPSR)
中的数据传递给通用寄存器,要读取特殊
寄存器的数据只能使用
MRS
指令!使用示例如下
MRS R0, CPSR
@
特殊存器
CPSR
里面的数据传递给
R0
,即
R0=CPSR
3

MSR
指令
MSR
指令和
MRS
刚好相反,
MSR
指令用来将普通寄存器的数据传递给特殊存器,也就
是写特殊存器,写特殊寄存器只能使用
MSR
,使用示例如下
MSR CPSR, R0
@

R0
中的数据复制
CPSR
中,即
CPSR=R0

三.存储器访问指令

1

LDR
指令
LDR
主要用于从存储加载数据到寄存器
Rx
中,
LDR
也可以将一个立即数加载到寄存器
Rx
中,
LDR
加载立即数的时候要使用“
=
”,而不是“
#
”。在嵌入式开发中,
LDR
最常用的就是读

CPU
的寄存器值,比如
I.MX6UL
有个寄存器
GPIO1_GDIR
,其地址
0X0209C004
,我们
现在要读取这个寄存器中的数据,示例代码如下
示例代码 7.2.2.1 LDR 指令使用
1
LDR R0
, =
0X0209C004
@
将寄存器地址
0X0209C004
加载到
R0
中,即
R0
=
0X0209C004
2
LDR R1
, [
R0
]
@
读取地址
0X0209C004
中的数据到
R1
寄存器中
上述代码就是读取寄存器
GPIO1_GDIR
中的值,读取到的寄存器值保存
R1
寄存器中
上面代码中
offset

0
,也就是没有用到
offset
2

STR
指令
LDR
是从存储器读取数据
STR
就是将数据写入存储器中,同样以
I.MX6UL
寄存器
GPIO1_GDIR
为例,现在我们要配置寄存器
GPIO1_GDIR
的值为
0X20000002
,示例代码如下:
示例代码 7.2.2.2 STR 指令使用
1
LDR R0
, =
0X0209C004
@
将寄存器地址
0X0209C004
加载到
R0
中,即
R0
=
0X0209C004
2
LDR R1
, =
0X20000002
@R1
保存写入到寄存器的值,即
R1
=
0X20000002
3
STR R1
, [
R0
]
@

R1
中的值写入
R0
中所保存的地址中
LDR

STR
都是按照字进行读取和写入的,也就是操作
32
位数据,如果要按照字节、
半字进行操作的话可以在指令“
LDR
”后面加上
B

H
,比如按字节操作的指令就是
LDRB
STRB
,按半字操作的指令就是
LDRH

STRH

四. 压栈和出栈指令

        通常会在 A
函数中调用
B
函数,当
B
函数执行完以后再回到
A
函数继续执行。要想
再跳回
A
函数以后代码能够接着正常运行,那就必须在跳到
B
函数之前将当前处理器状态保存
起来
(
就是保存
R0~R15
这些寄存器值
)
,当
B
函数执行完成以后再用前面保存的寄存器值恢复
R0~R15
即可。保存
R0~R15
寄存器的操作就叫做现场保护恢复
R0~R15
寄存器的操作就叫做
复现场。在进行现场保护的时候需要进行压栈
(
入栈
)
操作,恢复现场就要进行出栈操作。压栈
的指令为
PUSH
,出栈的指令为
POP

PUSH

POP
是一种多存储和多加载指令,即可一次
操作多个寄存器数据

原文地址:https://blog.csdn.net/weixin_66634995/article/details/134565620

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_15627.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注