文章内容:
参搭建并配置Keil嵌入式开发环境,完成一个基于STM32汇编程序的编写。
1)记录build生成的 hex文件各段的大小,了解Hex文件格式及其前8个字节内容含义;
2)学习在没有硬件条件下进行仿真调试的方法,观察ARM寄存器变化状况。
目录
实验环境:Keil 5
Keil 5百度网盘下载链接:https://pan.baidu.com/s/1BJ0jyr2Wf41_YyRZkLujgg
提取码:luha
1 基于 MDK 创建汇编语言的STM32工程
1.1 创建新工程
(1) 先点击 菜单栏的Project
,接着点击New uVision Project
创建新工程
(2)在弹出的窗口选择工程路径,输入工程名(可随意命名,最好全英文,这里命名为NEWTEST),并保存
(3)在新窗口中选择STM32F103VE
芯片(这里也可以选择其他合适的芯片)
(4)在新的窗口中:
CMSIS
下选择CORE
;
Device
下Startup
,其中包含了启动文件;
之后点击OK
即可。
1.2 添加源文件
(1)鼠标右击Source Group 1
(2)点击Add New Item to Group 'Source Group 1'...
(3)在新窗口中:
点击 Asm File (.s)
添加汇编文件,然后设置文件名称(可随意命名,最好全英文,这里命名为Test),并点击 Add
保存
添加完成后,可以看到如下界面:
1.3 编写汇编程序
在Test.s
框中输入如下汇编代码:
AREA MYDATA, DATA
AREA MYCODE, CODE
ENTRY
EXPORT __main
__main
MOV R0, #10
MOV R1, #11
MOV R2, #12
MOV R3, #13
;LDR R0, =func01
BL func01
;LDR R1, =func02
BL func02
BL func03
LDR LR, =func01
LDR PC, =func03
B .
func01
MOV R5, #05
BX LR
func02
MOV R6, #06
BX LR
func03
MOV R7, #07
MOV R8, #08
BX LR
1.4 编译准备
点击 魔法棒
,在 Output
界面下,勾选 Create HEX File
,点击OK
,才能生成 hex 文件;
1.5 编译
(1)点击图标编译
工程;
(2)生成hex文件,编译结果如下(警告可忽略):
2 分析编译生成的Hex文件
2.1 生成的hex文件
(1)最终生成的 hex 文件的各段大小
(2)用记事本打开 hex 文件,都是一连串的十六进制
2.2 分析hex文件
2.2.1 何为hex文件
(1)hex文件
- Intel HEX文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中,每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。Intel HEX文件通常用于传输将被存于ROM或者EPROM中的程序和数据。大多数EPROM编程器或模拟器使用Intel HEX文件。
(2)数据格式
- Intel HEX由任意数量的十六进制记录组成。每个记录包含5个域,它们按以下格式排列:
:llaaaatt[dd...]cc
- 每一组字母对应一个不同的域,每一个字母对应一个十六进制编码的数字
- 每一个域由至少两个十六进制编码数字组成,它们构成一个字节,就像以下描述的那样:
字母 | 含义 |
---|---|
: | 每个Intel HEX记录都由冒号开头 |
ll | 是数据长度域,它代表记录当中数据字节(dd)的数量 |
aaaa | 是地址域,它代表记录当中数据的起始地址 |
tt | 是代表HEX记录类型的域,它可能是以下数据当中的一个:(00-数据记录、01-文件结束记录、02-扩展段地址记录、04-扩展线性地址记录) |
dd | 是数据域,它代表一个字节的数据。一个记录可以有许多数据字节.记录当中数据字节的数量必须和数据长度域(ll)中指定的数字相符 |
cc | 是校验和域,它表示这个记录的校验和。校验和的计算是通过将记录当中所有十六进制编码数字对的值相加,以256为模进行以下补足 |
记录格式可表示为:“
:[1字节长度][2字节地址][1字节记录类型][n字节数据段][1字节校验和]
”
2.2.2 对生成的hex文件分析
(1)扩展线性地址记录
- 扩展线性地址记录也叫作32位地址记录或HEX386记录 , 这些记录含数据的高16位。扩展线性地址记总是有两个数据字节 , 外观如下(上述工程所生成的hex文件):
:020000040800F2
数据 | 分析 |
---|---|
02 | 记录当中数据字节的数量 |
0000 | 是地址域,对于扩展段地址记录,这个域总是0000 |
04 | 记录类型 04( 扩展线性地址记录) |
0800 | 地址的高 16 位 |
F2 | 是这个记录的校验和,计算方法:01h+NOT(02h+00h+00h+04h+08h+00h) |
- 当一个扩展线性地址记录被读取,存储于数据域的扩展线性地址被保存,它被应用于从Intel HEX文件读取来的随后的记录。线性地址保持有效,直到它被另外一个扩展地址记录所改变。
- 通过把记录当中的地址域与被移位的来自扩展线性地址记录的地址数据相加获得数据记录的绝对存储器地址。
(2)数据记录
- 第二行是数据记录,里面的地址值是0x0000。那么数据1D000A00000000000000000000000000(共16个字节)要写入FLASH中的地址为 (0x00008000<< 16)| 0x0000,也就是写入FLASH的0x80000000这个地址。
- 第三行的数据写入地址为0x80000010。当一个HEX文件的数据超过64k的时候,文件中就会出现多个扩展线性地址记录。
(3)文件尾
- Intel HEX文件必须以文件结束(EOF)记录结束这个记录的记录类的值必须是01。EOF记录外观总是如下(位于hex文件最后一排):
:00000001FF
数据 | 分析 |
---|---|
00 | 记录当中数据字节的数量 |
0000 | 数据被下载到存储器当中的地址,在文件结束记录当中地址是没有意义、被忽略的。(0000h 是典型的地址) |
01 | 记录类型 01(文件结束记录) |
FF | 是这个记录的校验和,计算方法如下: 256D-(00H+00H+00H+01H)=FFH |
3 仿真调试
3.1 仿真调试前准备
- 点击
魔法棒
,调出Options for Target 'Target 1'
界面,在其中点击Debug
; - 选中
Use Simulator
,选中Run to main()
; 在下面的Dialog DLL:
空白处填入DARMSTM.DLL
,在Parameter:
空白处填入-pSTM32F103VE
(此处芯片名称与上述工程选择的芯片名称必须一致); - 最后点击
OK
,准备完成
3.2 进入调试模式
-
点击下图表示标识,将进入
调试
模式;
-
可以看到,此时,寄存器
R0
,R1
,R2
,R3
,R5
,R6
,R7
,R8
的值和程序设置不一致,具体如下图所示:
-
接着进行
断点调试
,最后可以看到,结果符合预期,寄存器R5
,R6
,R7
,R8
的值和程序设置一致,具体如下图所示:
4 总结
首次接触这种汇编方式,也相当于是个新手,好在通过理解和参考完成了,大体熟悉了各种软件的操作和汇编语言的创建。在仿真调试时,也重温了一回断点调试,体验了在没有硬件条件下进行仿真调试来观察ARM寄存器的变化状况。实验操作整体不错,往后继续努力吧。