契机
笔者落笔的日子是6.1,这篇文章还不知道什么时候能发出去。不得不说这个时间是很尴尬的,主要是有两点:
- 博客鸽了很久了
- 6.4笔者就有一门期末考试,现在还没开始复习
但是笔者就是不想复习,毕竟DDL越近复习起来越刺激嘛(划掉
笔者这学期有微机原理的课程,在其中学习x86汇编,但是似乎身边每一个搞嵌入式的朋友都会吐槽这门课:为什么教x86汇编而不是ARM汇编!?
毕竟对于我们来说ARM汇编似乎还更实用一些。
笔者当然也会吐槽。这不,临近期末,看了看自己写的x86汇编代码,终究还是没忍住。
复习?学个屁!还是ARM汇编比较香。
搭建过程
IDE及内核架构
IDE:Keil v5
内核:Cortex-M4
内核架构:Armv7-M
单片机:STM32F401CCU6
准备过程
整个准备过程包括但不限于以下几点:
-
下载并安装Keil,此处略
-
从官网下载Cortex-M4的技术参考手册(用于参考)
-
安装需要的单片机支持包(STM32为例
-
需要实际硬件开发的话,还需要准备对应型号的开发板
-
......
新建工程
直接使用Keil新建工程就不赘述了。
Project
->New Project
->选型号
->blablabla
添加依赖
选择软件包之后的工程,并不能直接添加汇编文件来进行编译运行的操作,需要向其中添加一些单片机正常启动必须的库:
PS:
Startup中含有重启后真正的入口函数ResetHandler,而ResetHandler中调用的__main
函数内部其实调用了大量的CORE中的函数(例如:__rt_entry
等),所以需要将Startup和CORE全部添加到工程中单片机才能正常启动。
添加main文件
首先将默认生成的Target和文件组重命名成顺眼的名字:
首先单击选中目标,然后在已经是选中状态的目标上单机即可快速重命名。
直接向工程中添加汇编(.s)文件即可,不再赘述:
添加文件之后随便写段代码编译验证一下:
AREA MAIN_AREA,CODE,READONLY
EXPORT main
main proc
mov r0,#0
mov r1,#0
mov r0,#0xff
mvn r1,#0xff
nop
endp
END
编译,完美通过:
调试过程
如果你需要使用硬件进行实际调试,就像正常使用C库一样编译烧录调试即可。
当然也可以不用硬件,只要在调试界面将设置项改为模拟器即可:
直接向工程中添加汇编(.s)文件即可,不再赘述:
至此,环境搭建结束。
使用此环境学习汇编的一些说明
在网上考到了很多使用Keil搭建汇编开发环境的文章,但是并没有人解释过这部分内容,导致笔者自己产生了很多困惑,在这里解释一下。
首先明确一点,如果你像一些教程中教的一样写入类似如下的代码:
AREA Demo,CODE,READONLY
ENTRY
CODE32
Start
ADD R1,R2,#4
MOV R5,R1
END
在Keil中时没有办法过编译的。语法错了吗?语法并没有发生错误。
这是由于处理器架构以及单片机的启动代码导致的。
报错(和警告)主要来源于三个点:
CODE32导致的报错
CODE32
会导致如下报错:
"../Src/main.s", line 3: Error: A1630E: Specified processor or architecture does not support ARM instructions
简单翻译一下得知:笔者使用的处理器架构并不支持ARM指令集。那么问题来了,ARM指令集和我CODE32
又有什么关系呢?翻一下ARM编译器armasm参考手册不难得知:
The ARM
directive and the CODE32
directive are synonyms.
也就是说CODE32其实是在为下方的指令指定使用ARM指令集。显然笔者的处理器架构并不支持,所以可以直接删除该句代码,让汇编器自动指定使用的指令集即可。
如果想要规范一些(像笔者一样犟),可以将CODE32改为THUMB。
启动代码导致的报错
删除上述内容后,进行编译仍然会报错:
.\Objects\armAsmLearn.axf: Error: L6218E: Undefined symbol main (referred from __rtentry2.o).
说白了就是没有main函数,所以没法直接运行代码。
一些Arm汇编教程中之所以可以直接运行这段代码是由于教程作者使用的环境一般是没有任何额外的依赖的”干净的“环境,所以代码会直接从设置的ENTRY
处开始运行。
但是我们使用的环境中,真正的程序入口并非ENTRY
,而是Startup文件中的Reset_Handler
函数,而在Reset_Handler
中间接的调用了main函数,所以没有main函数的话自然会报出链接错误。
正确的书写方式是定义一个main函数,将我们希望运行的代码写到main函数中:
AREA Demo,CODE,READONLY
ENTRY
main PROC
EXPORT main
Start
ADD R1,R2,#4
MOV R5,R1
ENDP
END
笔者注:
正如我们不会直接在一个.c文件中写上运行的代码,而是写在main函数中一样,即使是汇编开发也是这样一个流程。
ENTRY导致的警告
即使是更改成上述代码在编译过后也不是完美的,会有一个警告出现:
.\Objects\armAsmLearn.axf: Warning: L6305W: Image does not have an entry point. (Not specified or not set due to multiple choices.)
这个警告是ENTRY
这句指令导致的。
正如上面讲的:
但是我们使用的环境中,真正的程序入口并非ENTRY
,而是Startup文件中的Reset_Handler
函数。
所以我们增加的ENTRY指令其实是冗余的,多定义了一个程序入口出来,进而导致链接器发出警告。所以将ENTRY
删除即可解决。
书续下篇:来学学ARM汇编----基本知识(上)