ARM汇编基础-GNU汇编语法

1030 字
5 分钟
ARM汇编基础-GNU汇编语法

一、为什么需要汇编#

嵌入式linux驱动开发和STM32一样,在设备启动时,需要一段汇编代码,引导设备运行到我们写的C语言入口。而STM32开发过程中,并不需要开发人员做这一步,原因其实是这段引导代码,已经由ST公司写好了,就是我们常见的 .s 启动文件,如 startup_stm32f10x_hd.s

而在嵌入式linux开发时,不会提供这样的.s文件,这就需要我们自己实现。需要会一定的ARM汇编,但不会太多。

二、GNU汇编语法#

开发STM32的主流IDE有 Keil 和 IAR 两种,但是它们的启动文件却不完全相同,是因为他们的编译器不同。在开发嵌入式linux,使用的是GCC编译器,因此,使用的就是GNU语法。

2.1、指令语法#

GNU语法适用于所有架构,并不是ARM独享的,GNU语句基本结构如下:

Terminal window
label: instruction @ comment

分为以下3个部分:

  • label

    即标号,表示地址位置。有些指令前面可能会有标号,这样就可以通过这个标号得到指令的地址,标号也可以用来表示数据地址。

    注意 label 后面的“:”,任何以“:”结尾的标识符都会被识别为一个标号。

  • instruction

    即指令,也就是汇编指令或伪指令。

  • @ comment

    @符号,表示后面的是注释,就跟 C 语言里面的“/”和“/”一样,其实在 GNU 汇编文件中我们也可以使用“/”和“/”来注释。后面的comment就是注释内容

如:

add:
MOVS R0, #0X12 @设置 R0=0X12

上面代码中 add: 就是标号, MOVS R0,#0X12 就是指令,最后的 @设置 R0=0X12 就是注释。

==注意! ARM 中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用小写,但是不能大小写混用!==

用户可以使用 .section 伪操作来定义一个段,汇编系统预定义了一些段名:

段名描述
.text表示代码段
.data初始化的数据段
.bss未初始化的数据段
.rodata只读数据段

使用 .section 自定义段:

.section .testsection @定义一个 testsetcion 段

这样就自定义了一个 .testsection 段。

汇编程序的默认入口标号是 _start ,不过我们也可以在链接脚本中使用 ENTRY 来指明其它的入口点,下面的代码就是使用 _start 作为入口标号:

.global _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》

2.2、函数语法#

GNU 汇编同样也支持函数,函数格式如下:

函数名:
函数体
返回语句

GNU 汇编函数返回语句不是必须的,如下代码就是用汇编写的 Cortex-A7 中断服务函数:

/* 未定义中断 */
Undefined_Handler:
ldr r0, =Undefined_Handler ; 将标签Undefined_Handler的地址加载到寄存器r0中
bx r0 ; 使用分支指令bx跳转到r0寄存器中的地址
/* SVC 中断 */
SVC_Handler:
ldr r0, =SVC_Handler
bx r0
/* 预取终止中断 */
PrefAbort_Handler:
ldr r0, =PrefAbort_Handler
bx r0

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

以上三个函数,都构成了一个死循环。

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

评论区

Profile Image of the Author
lim
Hello, I'm lim.
公告
欢迎来到我的博客!这是一则示例公告。
分类
标签
站点统计
文章
11
分类
4
标签
5
总字数
14,426
运行时长
0
最后活动
0 天前