一、创建新工程
1、创建新工程 ① 打开mdk5,点击Project,在弹出的窗口点击选项New uVision Project ,创建新的工程
② 选择文件保存的路径以及文件的命名
2、环境配置
①由于本次使用的单片机是野火指南者 ,故此处芯片选择了STM32F103RC
② 运行环境选择:CMSIS 下 选择CORE ,Device 下选择Startup ,其中包好了启动文件 到此,一个工程的建立就算是完成了
二、基于mdk环境下的stm32汇编编程
1.添加源文件 ①鼠标右键单击Source Group 1 ,选择Add New Item to Group
② 由于是要编写汇编程序,选择了Asm File(.s) ,设置源文件名称,点击Add
2.汇编程序
AREA MYDATA, DATA
AREA MYCODE, CODE
ENTRY
EXPORT __main
__main
MOV R0,
MOV R1,
MOV R2,
MOV R3,
;LDR R0, =func01
BL func01
;LDR R1, =func02
BL func02
BL func03
LDR LR, =func01
LDR PC, =func03
B .
func01
MOV R5,
BX LR
func02
MOV R6,
BX LR
func03
MOV R7,
MOV R8,
BX LR
3.配置仿真器
点击魔法棒 ,在Output 界面下,勾选 Create HEX File ,才能生产成Hex 文件 在Dubug 界面下,勾选Use Simulator ,表示使用软件仿真;选择Run to main() ,表示跳过汇编代码,直接跳转到main 函数开始仿真。然后设置下面的Dialog DLL 项分别为DARMSTM.DLL 和TARMSTM.DLL ,由于我选择的芯片为STM32F103RC ,所以parameter 项设置为-pSTM32F103RC ,具体根据自己实际情况进行选择 4.编译调试 程序编译:点击Rebuild 进行编译,出现一个警告可以忽略,编译成功,如果是出现了错误提示则需要修改程序 程序调试:点击右上角调试图标进行调试 最后可以看到,结果符合预期,寄存器R5 ,R6 ,R7 ,R8 的值和程序设置一致,具体如下图所示:
三、分析生成的 hex 文件
1、hex文件 最终生成.hex 文件各段的大小: 上面提到的 Program Size 包含以下几个部分: Code :代码段,存放程序的代码部分; RO-data :只读数据段,存放程序中定义的常量; RW-data :读写数据段,存放初始化为非 0 值的全局变量; ZI-data :0 数据段,存放未初始化的全局变量及初始化为 0 的变量;
通过查阅keil5的帮助文档(ARM Development Tools),看到这样的的一个数据,如图:
Code (inc. data) RO Data RW Data ZI Data Debug
3712 1580 19 44 10200 7436 Object Totals
0 0 16 0 0 0 (incl. Generated)
0 0 3 0 0 0 (incl. Padding)
21376 648 805 4 300 10216 Library Totals
0 0 6 0 0 0 (incl. Padding)
===============================================================================
Code (inc. data) RO Data RW Data ZI Data Debug
25088 2228 824 48 10500 17652 Grand Totals
25088 2228 824 48 10500 17652 ELF Image Totals
25088 2228 824 48 0 0 ROM Totals
===============================================================================
Total RO Size (Code + RO Data) 25912 ( 25.30kB)
Total RW Size (RW Data + ZI Data) 10548 ( 10.30kB)
Total ROM Size (Code + RO Data + RW Data) 25960 ( 25.35kB)
用记事本打开 hex 文件,都是一连串的十六进制 ,如图: 2、扩展线性地址记录
扩展线性地址记录(hex 文件的第一排十六进制)也叫作 32 位地址记录或 HEX386 记录;此处的地址记录数据为 :020000040800F2 这些记录包含数据地址的高 16 位; 扩展线性地址记录总是有两个数据字节,外观如下(这里我通过标记方便对应原始数据):
内容 | 描述 |
---|
02 | 记录当中数据字节的数量 | 0000 | 记录地址域,对于扩展线性地址记录,这个域总是 0000 | 04 | 记录类型 04 (扩展线性地址记录) | 0800 | 是地址的高 16 位 | F2 | 是这个记录的校验和,计算方法:01h + NOT(02h + 00h + 00h + 04h + 08h + 00h) |
当一个扩展线性地址记录被读取,存储于数据域的扩展线性地址被保存,它被应用于从 Intel HEX 文件读取来的随后的记录; 线性地址会保持有效,直到它被另外一个扩展地址记录所改变; 通过把记录当中的地址域与被移位的来自扩展线性地址记录的地址数据相加获得数据记录的绝对存储器地址;
3、数据部分
Intel HEX 由任意数量的十六进制记录组成。每个记录包含 5 个域,它们按一定格式排列::llaaaatt[dd…]cc; Intel HEX文件由任意数量以回车换行符结束的数据记录组成; 每一组字母对应一个不同的域,每一个字母对应一个十六进制编码的数字,每一个域由至少两个十六进制编码数字组成,它们构成一个字节,同如下表格描述一般:
内容 | 描述 |
---|
: | 每个Intel HEX记录都由冒号开头 | ll | 数据长度域,它代表记录当中数据字节(dd)的数量 | aaaa | 地址域,它代表记录当中数据的起始地址 | tt | 代表HEX记录类型的域,它可能是以下数据当中的一个:00(数据记录) 、01(文件结束记录) 、02(扩展段地址记录) 、04(扩展线性地址记录) | dd | 数据域,它代表一个字节的数据。一个记录可以有许多数据字节.记录当中数据字节的数量必须和数据长度域(ll)中指定的数字相符 | cc | 校验和域,它表示这个记录的校验和(校验和的计算是通过将记录当中所有十六进制编码数字对的值相加,以256为模进行以下补足) |
4、文件尾 在文件的最后一排,是一个文件的结束标志::00000001FF
内容 | 描述 |
---|
00 | 记录的长度为 0 | 0000 | LOAD OFFSET为0000 | 01 | TYPE = 01 | FF | 校验和为FF |
这个是一个 END OF FILE RECORD ,标识文件的结尾
四、总结
本次在软件平台上进行汇编程序的编译与测试的实验中,仿真器容易连接不上,在调试过程的时候出现了很多问题,需要注意仿真器的配置以及芯片的选择是否一致。
五、参考资料
基于 MDK 创建 STM32 汇编语言工程并分析 HEX 文件内容
keil5编译后生成 Program Size: Code RO-data RW-data ZI-data是什么
|