KEIL 5.38的ARM-CM3/4 ARM汇编设计学习笔记1——基本的ARM汇编语法

一、使用KEIL的背景介绍

我之前一直在用KEIL以外的很多IDE进行程序开发,比如STM32CUBEIDE、SEGGER EMBEDDED STUDIO和RT-STUDIO。这些IDE一般都是使用的GNU汇编。正如我其他的文章里说的那样。然而最近我看了一本CM4的书,我又想起当时用KEIL做事情的时候的故事。于是干脆重新打开KEIL,找找感觉。

我从不否认,KEIL是非常优秀的IDE。只是之前有一阵子欧洲搞制裁,没得用了。既然现在又有的用了,拿起来感觉还是很香的。

KEIL下面使用的汇编是ARM汇编,所有的伪指令要按照ARM汇编的格式来做。具体的内容可以参考下面的文档
1、ARM Developer Suite Assembler Guide
2、ARM Compiler toolchain Using the Assembler Version 4.1
3、创建工程文件的时候系统给的startup_xxxxx.s

二、简述测试环境

名称描述
开发板正点原子的探索者F4 (STM32f407ZG)
调试器J-link plus compact
IDEKEIL 5.38

在这里插入图片描述

三、常用的ARM伪指令

CM3/4都是使用Thumb指令的。而有关的指令集除了上面介绍的两个文章中会出现,ST的官方手册中也会有。所以关于指令就不再赘述。但是伪指令就推荐在上面的第一个文件中看。比较全面。我这里只列举引导词,具体的语法参考手册。

引导词用法
ALIGN字节对齐
AREA设置区域,类似于GNU汇编中的.section。但是好像因为KEIL的链接器和其他的IDE的链接器是不一样的,所以这条语句用起来也会有不一样的地方
DCD、DCW、DCB铺数据的指令,和GNU汇编中的.word .short .byte是一样的。注意那个DCB同时也可以铺字符串。
SPACE和GNU汇编中的.space一样的用法
PROC 、ENDP; FUNCTION、ENDFUNC开始、结束一个函数
END本汇编源文件结束
EQU设置符号值
EXTERN、IMPORT引入外部符号。两者有微小区别,参考手册
EXPORT将本符号引出到外部。相当于GNU汇编的.global

四、代码实现

1,创建工程文件

开局简单,Project >> new project >> STM32F407ZG
在这里插入图片描述
接下来设置RTE。这里很简单,只要把CMSIS/CORE和Device/Startup勾上就行了。
在这里插入图片描述
这里有个提示,说是要用C99以上的C标准。这个去魔法棒>>C/C++(AC6)调一下就好。我一般都是改成c11。这样就可以了。

2,参考Reser_Handler

参考一下Device/startup_stm32f407xx.s文件,看一下Reset_Handler的实现

                AREA    |.text|, CODE, READONLY

; Reset handler
Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

这里这个__main和我们的真正的main不是同一个符号。编译器只要一看到这个符号,就会给你补上一部分初始化代码,再跳转到我们自己的main符号处。详细情况参考MDK __main()代码执行分析

3,创建main函数

右键Source Group 1,Add New Item to …,创建main_asm.asm文件。
在这里插入图片描述

4,浅说KEIL的链接脚本.sct文件

这里,为了实现段的手动分配,需要简单插一段讲讲.sct链接脚本的用法。这里有很多大牛已经把.sct的语法讲过了。如果是全面的资料,可以去参考ARM的官方资料——《ARM Compiler toolchain Using the Linker》。我就不再赘述.sct的语法。我就简单说说怎么用这个链接脚本吧。

点击魔法棒/Linker。勾掉Use Memory Layout from Target Dialog,这样Scatter File激活。

在这里插入图片描述
点Edit可以看到整个.sct文件。初始状态下是这样的。

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x08000000 0x00100000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00100000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data
   .ANY (+RW +ZI)
  }
}

考虑407还有个片上CCM,开始与0x10000000,大小为64kB(0x10000)。我就做个域(region),名字叫RAM_CCM,输入段是所有的CCM数据。

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************

LR_IROM1 0x08000000 0x00100000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00100000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data
   .ANY (+RW +ZI)
  }
  RAM_CCM 0x10000000 0x00010000  {  ; RW data
   * (CCM) 
  }
}

这样,就将段设置好了。

5,main()测试

测试一下根据前面做的sct文件,将数据初始化放在CCM中。读出,并放到片内的SRAM上。

	area  ccm, data
user_data1 dcd 0x121234		
	
	area data
user_data	space 100
	
	area text, code
main	proc
	export main
		
		ldr r0, =user_data
		ldr r2, =user_data1
		ldr r1, [r2]
		str r1, [r0]
		ldr r3, [r0]
		b	.
		bx lr
		endp
	end

有必要稍微说明一下,当创建了main()以后,系统就给补上了必要的初始化代码。这部分代码完成了RAM的初始化加载。这也就是为什么dcd 0x121234可以将数据初始化到RAM上了。

这个程序的调试结果如下所示。
在这里插入图片描述
可以看出,数据成功的从CCM上转移到了SRAM上。

五、结论

好久没有用过KEIL了。重新拿起来还是有点生疏。有以下两点体会:

  1. 要主要使用链接脚本对内存进行分段,便可以在汇编语句中直接使用这些段。
  2. ARM的链接器检测到main函数时会补上初始化代码,完成初始化变量的赋值。
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值