执行文件
hex文件解析 Keil开发环境编程时对源程序进行编译链接后都可以成一个可执行文件即hex文件,但是有不完全是一个可执行文件。然后可以通过烧录工具烧写到对应的单片机的flash中,当然也还有其他方法可以进行烧录。大家在编程时是否对生成的hex文件有这样的疑问: 1、?当hex文件的大小大于单片机的flash时烧录工具还是可以把hex文件烧写到flash中呢; 2、?单片机运行的是二进制指令和数据,那么hex文件的内容是否都是二进制数呢; 3、?烧录工具是根据什么把程序指令和数据烧写到flash固定的位置呢。 我们就带着这三个疑问深入学习hex文件,想深入理解hex文件必须从内容入手。查看hex文件的很简单,用文本随便打开一个文件都可以看到hex文件的内容。例如: :020000040800F2 :1000000080040020690100087101000873010008E4 :1000100000000000000000000000000000000000E0 :100020000000000000000000000000007501000852 :1000300000000000000000007701000879010008BE `````````` `````````` `````````` :1005E0002001000800000000006CDC020000000098 :1005F00000000000010203040607080900000000D3 :04000005080000C12E :00000001FF 上面就是一个hex文件内容首尾的一部分数据,从内容中很明显可以看出这不是二进制数据。Hex文件是用ASCII来表示二进制的数值,十六进制数组成的指令或者数据,每一行就是一个hex记录。由于单片机执行的只能是二进制指令和数据,而hex文件是十六进制数,所以烧录器的工作必然有一个进制转换机制。具体机制怎么实现暂时可以不管,知道是烧录器处理的就行了。从这里可以找出第二问题的答案。 ? hex文件的每一行数据记录都是以行为单位,每行从“:”(0x3a)开始,这从文件内容可以看出。以回车键结束(0x0d,0x0a),每行以换行结束。每行的数据都是由两个字符表示一个16进制字节,例如第一行,:020000040800F2中的“02”表示数为0x02,“F2”就表示为0xF2。如果数据位地址时,地址高位在前低位在后。 以上面内容的第二行数据为例,进行详细解析: :1000000080040020690100087101000873010008E4 1、“:”表示一行的开始; 2、第1、2个字符1和0,即“0x10”表示本行包含的数据长度为16个; 3、第3、4、5、6个字符,固定这4位表示地址,即“0000”表示数据存储的起始地址,表示在0x0000地址开始存放本行包含的16个数据。 4、第7、8个字符,固定这2位表示本行包含数据数据的类型,即“00”表示本行包含的数据为实际烧写的数据。而数据的类型有如下几种: “00”表示实际数据记录 “01”表示文件结束记录 “02”表示扩展段地址记录 “04”表示扩展线性地址记录 5、由前两个字符“10”可知本行的数据长度位16个字节,所有往后的32个字符就是本行包含的数据,每两个字符表示一个字节数据,总共有16个字节数据。跟最前两个字符决定的长度一致。但是这个数据的长度不是固定的,例如最后一行00000001FF,这行包含的数据长度0,没有数据。 6、最后两个字符为本行的校验码。 通过上面的几点分析可以总结出hex文件的每一行的格式: <0x3a>[数据长度1Byte][数据地址2Byte][数据类型1Byte][数据nByte] [验证码1Byte]<0x0d><0x0a> 所以通过hex文件的格式可以知道其实hex文件烧录时烧录器只是根据数据长度和地址这些辅助信息把实际的数据烧写到指定的地址中,这就解决了第三个疑问。其实这里还可以知道第二个疑问的答案,hex文件中的实际数据只是占hex文件的少部分内容。就比如我之前编程时遇到的情况,我编写的程序编译后生成的hex文件的大小为89K,单片机的flash才有64k,但是还是完全可以把hex文件烧写进去。原因就是我编写的代码和数据的大小只有51k,这个可以通过编译信息可以知道。显然,64k大小的flash存51k大小的指令和数据是完全没问题的。但是如果指令和数据的大小大于64K时,这可能就有问题,我还没有验证过。 ? 由于每行标识数据地址只有2Byte,所以最大只能到64K,为了可以保存高地址的数据,可以通过扩展线性地址来处理,也就是这行的数据类型是“0x04”。那么,这行的数据就是随后数据的基地址。 扩展线性地址: 当一个扩展线性地址记录被读到后,扩展线性地址将被保存并应用到后面从hex文件读出的记录,这个扩展线性一直有效,直到读到下一个扩展线性地址记录。 绝对地址与扩展线性地址的关系: 绝对地址?=?移位后的扩展线性地址?+?数据记录中的地址 扩展段地址: 当一个扩展段地址记录被读到后,扩展段地址将被保存并应用到后面从hex文件读出的记录,这个扩展段地址一直有效,直到读到下一个扩展段地址记录。 绝对地址与扩展段地址的关系: 绝对地址?=?移位后的扩展段地址?+?数据记录中的地址 如第一行:?020000040800F2 这行的数据类型就是0x04,所以0x0800就是基地址,又由于第二行的地址是0x0000,所以第二行中的实际数据80040020690100087101000873010008是从地址(0x0800<<16)|0x0000,即0x08000000开始烧写。同理,第三行的实际数据是从0x08000010地址开始烧录,以此类推······ 上面的hex文件内容是用keil开发环境编写stm32内核为Cortex-M0芯片的程序而产生的,而Cortex-M0内核芯片烧写指令默认是从flash地址为0x08000000开始的,所以从hex文件也可以验证这一点。 每个hex文件的最后一行记录都是固定的,即:00000001FF。数据长度为0,地址为0。 ? 校验的算法: 计算从(0x3a)以后的所有各字节的和模256的余。即各字节二进制算术和,不计超过256的溢出值,然后用0x100减去这个算数累加和,得出的值就是此行校验码。举一个简单的例子,如第一行020000040800F2 0x02+0x00+0x00+0x00+0x04+0x08+0x00?=?0x0E 0x100?–?0x0E?=?0xF2. hex文件解析完毕! 如果此文章对你有帮助,请麻烦加以评论,谢谢! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |