keil下汇编语言调试分析


前言

Hex的具体格式如何?
在MDK下不同代码段各有什么意义?
调试状态下ARM寄存器的变化情况?


一、新建工程

  • 点击Project,选择New uvision Project,创建新工程

在这里插入图片描述

  • 选择工程保存路径,命名并保存(所选路径名最好不要带中文)

在这里插入图片描述

  • 选择芯片型号

在这里插入图片描述

二、添加文件

  • 选中Source Group 1,右击选择Add New Item to Group 'Source Group 1'..请添加图片描述
  • 创建汇编文件
    请添加图片描述

三、编写程序并编译

  • demo.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
  • 配置输出选项
    请添加图片描述

  • 编译并调试
    请添加图片描述
    问题
    在进入调试界面后,发现程序一直在SetSysClockTo72()函数里执行,在时钟初始化中死循环,无法正常执行main函数,如下所示。
    请添加图片描述
    上网查阅资料后,参考下面文章终于解决

    STM32-仿真调试时的SystemInit死循环
    请添加图片描述
    最后调试成功
    请添加图片描述

四、各程序段的意义

  • 生成代码段

请添加图片描述
解析

• Code:即代码域,它指的是编译器生成的机器指令,这些内容被存储到 ROM 区。

• RO-data: Read Only data,即只读数据域,它指程序中用到的只读数据,这些数据被存储在 ROM 区,因而程序不能修改其内容。例如 C 语言中 const 关键字定义的变量就是典型的 RO-data。

• RW-data: Read Write data,即可读写数据域,它指初始化为“非 0值”的可读写数据,程序 刚运行时,这些数据具有非 0 的初始值,且运行的时候它们会常驻在 RAM 区,因而应用 程序可以修改其内容。例如 C 语言中使用定义的全局变量,且定义时赋予“非 0 值”给该 变量进行初始化。

• ZI-data: Zero Initialie data,即0 初始化数据,它指初始化为“0 值”的可读写数据域,它与 RW-data 的区别是程序刚运行时这些数据初始值全都为 0,而后续运行过程与 RW-data 的 性质一样,它们也常驻在 RAM 区,因而应用程序可以更改其内容。例如 C 语言中使用定 义的全局变量,且定义时赋予“0值”给该变量进行初始化 (若定义该变量时没有赋予初始 值,编译器会把它当 ZI-data 来对待,初始化为 0);

• ZI-data 的栈空间 (Stack) 及堆空间 (Heap):在 C 语言中,函数内部定义的局部变量属于栈空间,进入函数的时候从向栈空间申请内存给局部变量,退出时释放局部变量,归还内存 空间。而使用 malloc 动态分配的变量属于堆空间。在程序中的栈空间和堆空间都是属于 ZI-data 区域的,这些空间都会被初始值化为 0 值。编译器给出的 ZI-data 占用的空间值中包 含了堆栈的大小 (经实际测试,若程序中完全没有使用 malloc 动态申请堆空间,编译器会优化,不把堆空间计算在内)。

程序组件所属类别
机器代码指令Code
常量RO-data
初始非零的全局变量RW-data
初始为零的全局变量ZI-data
局部变量ZI-data栈空间
使用malloc动态分配的空间ZI-data堆空间

五、分析Hex文件

  • Hex基本格式解析

    以下内容参考博主「小麦大叔」文章 hex文件格式总结

    参考总结如下添加图片描述
    这个Hex文件和一般的通讯协议类似,一帧数据往往包括起始码,数据长度,数据类型,数据,校验码等等;

  • 起始码:每行数据作为一帧,并由:作为起始码;
  • 字节长度:两个十六进制数字(一对十六进制数字),指示数据字段中的字节数(十六进制数字对)。最大字节数为255(0xFF)。16(0x10)和32(0x20)是常用的字节数;
  • 地址:四个十六进制数字,代表数据的16位起始存储器地址偏移量。数据的物理地址是通过将此偏移量添加到先前建立的基地址来计算的,因此允许内存寻址超过16位地址的64KB限制。基地址默认为零,可以通过各种类型的记录进行更改。基地址和地址偏移量始终表示为大端值。
  • 指令类型:两个十六进制数字00到05,定义了这行数据的具体含义; 数据:n字节数据序列,由2个n十六进制数字表示;
  • 校验码:(两个十六进制数字),可以用来验证记录没有错误的计算值;
  • 打开Hex文件(我这里使用Notepad++)

请添加图片描述

  • 取第51行进行分析
    起始码:

    字节长度:0x04’(2个16进制)
    表示后面的数据段共有4个字节

    地址: ‘0x0000’,表示数据地址信息(一般4个16进制位)

    指令类型: '0x05' (两个十六进制位表示)

    数据: 包括0x08,0x00,0x01,0x79共4个字节

    校验码:‘0x75’ (一般两个16位数据)

    将除检验码的数据加起来取反码再加1,即可得到校验码

     1)0x04+0x00+0x00+0x05+0x08+0x00+0x01+0x79=0x8B
     2)~0x8B=0x74
     3)0x74+1=0x75
    

总结

以上内容参考的博客均已列出,若有不当之处,敬请批评指教。

参考

《STM32库开发实战指南–基于野火指南针开发板》

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值