一.keil的安装
注册
1.点击运行注册器程序。
2.在桌面找到keil软件图标,点击右键,以管理员身份运行。
3.点击File–>Lincense Management–>Single-User Lincense,找到CID,复制CID中的内容填写到注册器的CID空白处,将注册器中Target选择为ARM,点击Generate,得到注册码。
4.将生成的注册码复制粘贴到Keil的New Lincense ID Code空白处,点击Add LIC,点击Close。
支持包安装
点击运行下载的支持包,NEXT开始安装,安装完成,点击Finish。
二.stm32程序
1.创建工程
①点击Project
,选择New uvison Project
②选择文件保存的路径以及文件的名称
2.环境配置
①选择对应的芯片,本文章采用的STM32F103ZE
②运行环境选择,主要是CMSIS下
选择CORE
;Device
下Startup
,其中包含了启动文件。
这样子,一个工程的建立就算完成了。
3.添加文件
(1).鼠标右键单击Source Group 1
,选择Add New Item to Group
(2).选择Asm File (.s)
,设置源文件的名称,点击Add
这样添加文件的过程就完成了,我们就可以开始编写汇编程序。
4.汇编程序
(1) 输入代码如下:
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
(2)设置仿真器模式
点击菜单中的Project
,找到Options for Target ‘Target 1’
并点击(也可以直接点击魔法棒图标进入,)选择Debug–>Use Simulator
,将Dialog DLL
以及Parameter
处修改为自己选择的设备,OK。
(3)编译调试
选择rebuild
,点击debug
在左上角点击step
或step over
或Run To Cursor Line
观察寄存器R5,R6,R7,R8的值和程序设置是否一致
由图可发现最终结果可以看出寄存器的值与设置的值一致。
三.分析编译生成的Hex文件
点击 魔法棒
,在 Output
界面下,勾选 Create HEX File
,才能生成 hex 文件,然后打开hex文件进行分析。
- 进行编译可看见如图所示最终生成的hex文件各部分的大小。
- 打开hex文件,可获得一连串的十六进制
1.扩展线性地址记录
该文件为16进制的一串字符。hex文件的第一排字符称之为扩展线性地址记录,也称为32位地址记录或HEX386记录。
在第一行数据:020000040800F2中,其实际表达为0x02 0x00 0x00 0x04 0x08 0x00 0xf2。
1.第一个字节 0x02表示本行数据的长度;
2.第二、三字节 0x00 0x00表示本行数据的起始地址;
3.第四字节 0x04表示数据类型,用来标识扩展线性地址的记录,该字节还可以是其他值。
‘00’ Data Rrecord:用来记录数据,HEX文件的大部分记录都是数据记录
'01’End of File Record: 用来标识文件结束,放在文件的最后,标识HEX文件的结尾
‘02’ Extended Segment Address Record: 用来标识扩展段地址的记录
‘03’ Start Segment Address Record:开始段地址记录
‘04’ Extended Linear Address Record: 用来标识扩展线性地址的记录
‘05’ Start Linear Address Record:开始线性地址记录
4.0x08 0x00 数据类型是 04 ,即该行记录的是一个拓展地址(0x08 0x00 是地址信息,用法是将该地址(0x0800<<16) 后作为基地址
5.0xF2是这个记录的校验和,计算方法为:01h + NOT(02h + 00h + 00h + 04h + 08h + 00h)
- 当一个扩展线性地址记录被读取,存储于数据域的扩展线性地址被保存,它被应用于从 Intel HEX 文件读取来的随后的记录
- 线性地址保持有效,直到它被另外一个扩展地址记录所改变
- 通过把记录当中的地址域与被移位的来自扩展线性地址记录的地址数据相加获得数据记录的绝对存储器地址
2.数据部分
- Intel HEX 由任意数量的十六进制记录组成。每个记录包含 5 个域,它们按一定格式排列:
:llaaaatt[dd...]cc
;其中每一组字母对应一个不同的域,每一个字母对应一个十六进制编码的数字,每一个域由至少两个十六进制编码数字组成,它们构成一个字节。
内容 | 描述 |
---|---|
:llaaaatt[dd…]cc | |
: | 每个Intel HEX记录都由冒号开头 |
ll | 数据长度域,它代表记录当中数据字节(dd)的数量 |
aaaa | 地址域,它代表记录当中数据的起始地址 |
tt | 代表HEX记录类型的域,它可能是以下数据当中的一个:00 (数据记录)、01 (文件结束记录)、02 (扩展段地址记录)、04 (扩展线性地址记录) |
dd | 数据域,它代表一个字节的数据。一个记录可以有许多数据字节.记录当中数据字节的数量必须和数据长度域(ll)中指定的数字相符 |
cc | 校验和域,它表示这个记录的校验和(校验和的计算是通过将记录当中所有十六进制编码数字对的值相加,以256为模进行以下补足) |
- Intel HEX文件由任意数量以回车换行符结束的数据记录组成,我们以第二行为例做讲解
:100000000006002031010008390100083B0100080A
内容 | 描述 |
---|---|
:100000000006002031010008390100083B0100080A | |
10 | 记录当中数据字节的数量 |
0000 | 数据将被下载到存储器当中的地址 |
00 | 记录类型(数据记录) |
00060…0008 | 数据 |
0A | 这个记录的校验和 |
3.文件尾
- 在文件的最后一排,是一个文件的结束标志:
:00000001FF
这个是一个 END OF FILE RECORD,标识文件的结尾
内容 | 描述 |
---|---|
:00000001FF | |
00 | 记录的长度为 0 |
0000 | LOAD OFFSET为0000 |
01 | TYPE = 01 |
FF | 校验和为FF |
四.汇编语言常用指令
指令 | 含义 | 示例 | 命令解析 |
---|---|---|---|
LDR(load) | 读内存命令 | LDR R0 ,[R1] --假设R1的值为x | 读取地址x上的数据(4个字节)保存到R0中。 |
LDR(伪指令) | 伪指令(并不存在的指令,最终被解析成真正的汇编指令) | LDR R0,=0x12345678, | 把0x12345678的值赋值给R0 |
STR(Srote) | 写内存命令 | STR R0 ,[R1] --假设R1的值为x | 把R0的值(4字节)写到地址x中去 |
BL | 跳转到指定指令,把返回地址(下一条指令的地址)保存在lr寄存里边 | BL xx | 命令跳转到xx处执行,且lr寄存器保存aa的地址,以便继续运行 |
MOV(move) | 赋值指令 | 例1:MOV R0,R1 例2:MOV R0,#0x100 | 把R1的值赋值给R0 ; 把0x100赋值给R0 |
sub | 减法指令 | sub ro ,r1,#5 | 其含义是:r0 = r1 -5 |
add | 加法指令 | add ro ,r1,r2 | 其含义是:r0 = r1 + r2 |
五.总结
本文主要讲述了keil的安装与基本使用,完成了一个基于STM32汇编程序的编写,并且记录build生成的 hex文件各段的大小,了解Hex文件格式及其前8个字节内容含义。由于笔者之前也尚未接触过汇编语言,所以找了许多参考,学习路前路漫漫,需要各位多加练习共同努力。
参考
1.https://blog.youkuaiyun.com/qq_45659777/article/details/120496577
2. https://blog.youkuaiyun.com/u010632165/article/details/106481146
3. https://blog.youkuaiyun.com/ssj925319/article/details/111868500
4. https://blog.youkuaiyun.com/qq_43279579/article/details/111717607