• Intel HEX文件解析


    近期有一个需求就是为Arduino开发板做一个基于蓝牙的无线烧录程序。眼下的Arduino程序都是通过USB线连接到电脑的主机上,实际的传输过程是基于USB协议的,这个过程还是比較麻烦的。由于每次的编译完以后都须要通过一个USB线来完毕传输烧录的工作,这个还是非常麻烦的。

    原理解读

    在Arduino中。利用USB来完毕传输烧录大概是这么一个过程。

    每一个Arduino源程序。即sketch文件,经过一系列的编译处理以后。终于会形成一个Intel HEX格式的文件。这个HEX文件事实上就一个被封装好的数据包,包括头部、长度、偏移量、数据类型、数据和校验和等6个字段。

    再利用USB协议传输这个数据包,再通过板子上已有的bootloader程序把这个HEX文件里的有效字节码写到板子上的Flash存储器中。就是由于这个bootloader程序的存在。才使得多数的单片机具有片内引导程序自编程功能。MCU通过执行这个常驻Flash的bootloader程序。就能够利用不论什么可用的数据接口读代替码(注:在Arduino中,这里的代码是指HEX文件里的有效数据字段,是终于字节码的形式)后写入到自身的flash存储器中,从而实现了自编程的功能。

    理解了上面的原理以后,你比方说我要做一个支持无线传输的类似bootloader的东西。无线传输採用蓝牙协议。

    蓝牙的接收端将接收到的数据所有存在串口中,所以核心的技术除了蓝牙收发部分以及对flash存储器的读写和存储空间的管理以外,还须要实现对这个HEX文件的解析,更准确、形象地说应该是对这些数据包的解析。怎么把这个数据包拆开,取出有效的字节码数据,然后把这些字节码按顺序分块组装,写到flash存储器。再把PC指针指到開始的地方就能够了。只是这东西确实非常底层,就是在直接跟内存打交道。怎么管理内存。怎么读写内存,怎么拆分组装数据,出错了以后怎么擦除已经写的内容,怎样优化等等一些列问题都须要解决。

    事非经过不知难。经过方知难与易。慢慢做吧!先来第一步。对HEX格式的文件进行解析。解析之前自然要弄懂HEX文件的详细格式。


    HEX文件的格式

    Intel HEX格式的文件是由多条记录组成,而每条记录又是由6个字段组成。这些记录是由一些代表机器语言代码和常量的16进制数据组成的。Intel HEX 文件经常使用来传输要存储在 ROM 或者 EPROM 中的程序和数据。大部分的 EPROM 编程器能使用 Intel HEX文件记录的基本格式例如以下:

    RecordMark

    RecordLength

    LoadOffset

    RecordType

    Data

    Checksum

    记录标志

    记录长度

    装载偏移

    记录类型

    数据

    校验和

    当中,RecordMark字段事实上就是每条记录的首部,其值为0x3A,在ASCII码中就是冒号“:”。该字段在HEX文件里,这个头部仅仅占有一个字节。RecordLength表示每条记录包括的数据的长度,以字节为单位。最大描写叙述255个字节,表现为2个16进制的字符,该字段在HEX文件里占2个字节。

    LoadOffset表示该记录中的数据在整个存取器空间中的偏移,用4个十六进制字符描写叙述一个16位数据。在HEX文件里该字段占有4个字节。

    RecordType表示记录类型。表现为2个十六进制字符。取值有下面几种:

    00表示数据记录。

    01表示文件结束记录;

    02描写叙述拓展段地址记录。

    03描写叙述開始段地址记录。

    04描写叙述扩展线性地址记录;

    05描写叙述開始线性地址记录。

    Data字段表示数据的详细内容,描写叙述方法仍是两个16进制的字符表示1字节的数据。此字段的长度由该记录的RecordLength决定,数据的解释取决于记录类型(RecordType)。

    Checksum字段为校验和。这个校验和是这么来的。将RecordMark(“:”)后的全部的数据按字节相加,即成对相加起来,然后模除256得到余数,再对这个余数求补码,终于得出的结果就是校验和。所以检測方法也非常easy:在每一条记录内,将RecordMark(“:”)后的全部数据(包含Checksum)按字节相加后得到的8位数据为0,则说明数据无误。否则说明出错了。

    至于什么是拓展段地址记录、開始段地址记录、扩展线性地址记录、開始线性地址记录这里不做具体的介绍。在芯艺的《AVR单片机GCC程序设计》的附录部分有具体的说明。而在Arduino的HEX文件里,记录类型仅仅有两种。数据记录和文件结束记录。所以RecordType这个字段的值不是0x00就是0x01。数据记录适用于8位、16位和32位格式,其具体格式例如以下:

    记录名

    RecordMark

    RecordLength

    LoadOffset

    RecordType

    Data

    Checksum

    记录标志

    记录长度

    装载偏移

    记录类型

    数据

    校验和

    内容

    “:”

    X

    -

    “00”

    -

    -

    字节数

    1

    1

    2

    1

    X

    1

    文件结束记录适用于8位、16位和32位格式。其具体格式例如以下:

    记录名

    RecordMark

    RecordLength

    LoadOffset

    RecordType

    Checksum

    记录标志

    记录长度

    装载偏移

    记录类型

    校验和

    内容

    “:”

    “00”

    “0000”

    “01”

    “FF”

    字节数

    1

    1

    2

    1

    1

    比方说。有例如以下一条数据记录:“:1001A000808184608083808182608083808181609F”,则,其RecordMark为“:”,RecordLength为”10”。这里是16进制的,相应10进制为16,也就是说Data字段有16个字节;LoadOffset的值为01A0,也就是说在该条记录中,数据字段在内存中的起始地址为01A0;RecordType为00,表示是记录类型;Data的值为80818460808380818260808380818160,一共同拥有16个字节;Checksum的值为9F。用计算器依照上面的方式验证一下是能够得到一个低8位为0的数据,也就是说这条记录是合法的。

    以下開始编码实现对HEX文件的解析。

    HEX文件解析的实现

    解析过程还是比較简单的。这里直接附上源代码。

    HexLexer.h头文件里定义了相关的类的属性和操作。

    #ifndef _HEXLEXER_H_
    #define _HEXLEXER_H_
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    /*
    Intel Hex文件解析器V1.0
    Hex文件的格式例如以下:
    RecordMark	RecordLength	LoadOffset	RecordType	Data	Checksum
    在Intel Hex文件里,RecordMark规定为“:”
    */
    #pragma warning(disable:4996)
    #define MAX_BUFFER_SIZE 43
    class Hex
    {
    public:
    	Hex(char mark);
    	~Hex();
    	void ParseHex(char *data);//解析Hex文件
    	void ParseRecord(char ch);//解析每一条记录
    	size_t GetRecordLength();//获取记录长度
    	char GetRecordMark();//获取记录标识
    	char *GetLoadOffset();//获取内存装载偏移
    	char *GetRecordType();//获取记录类型
    	char *GetData();//获取数据
    	char *GetChecksum();//获取校验和
    
    private:
    	char m_cBuffer[MAX_BUFFER_SIZE];//存储待解析的记录
    	char m_cRecordMark;//记录标识
    	size_t m_nRecordLength;//记录长度
    	char *m_pLoadOffset;//装载偏移
    	char *m_pRecordType;//记录类型
    	char *m_pData;//数据字段
    	char *m_pChecksum;//校验和
    	bool m_bRecvStatus;//接收状态标识
    	//size_t m_nIndex;//缓存的字符索引值
    };
    
    Hex::Hex(char mark)
    {
    	this->m_cRecordMark = mark;
    	m_cBuffer[0] = '';
    	//m_pBuffer = NULL;
    	m_nRecordLength = 0;
    	m_pLoadOffset = NULL;
    	m_pRecordType = NULL;
    	m_pData = NULL;
    	m_pChecksum = NULL;
    	m_bRecvStatus = false;
    	//m_nIndex = 0;
    }
    
    Hex::~Hex()
    {
    	delete m_pLoadOffset, m_pRecordType, m_pData, m_pChecksum;
    }
    
    #endif
    

    HexLexer.cpp文件实现了头文件里函数,并给出了測试用例。

    #include "HexLexer.h"
    #include <iostream>
    using namespace std;
    //获取记录标识
    char Hex::GetRecordMark()
    {
    	return this->m_cRecordMark;
    }
    //获取每条记录的长度
    size_t Hex::GetRecordLength()
    {
    	//char *len = (char*)malloc(sizeof(char)* 3);
    	if (strlen(m_cBuffer)>=2)
    	{
    		char len[3];
    		len[0] = m_cBuffer[0];
    		len[1] = m_cBuffer[1];
    		len[2] = '';
    		char *p = NULL;
    		return strtol(len, &p, 16);
    	}
    	else
    	{
    		return 0;
    	}
    }
    //获取装载偏移
    char* Hex::GetLoadOffset()
    {
    	if (strlen(m_cBuffer) == (GetRecordLength() + 5) * 2)
    	{
    		char *offset = (char*)malloc(sizeof(char)* 5);
    		for (int i = 0; i < 4; ++i)
    		{
    			offset[i] = m_cBuffer[i + 2];
    		}
    		offset[4] = '';
    		m_pLoadOffset = offset;
    		offset = NULL;
    	}
    	return m_pLoadOffset;
    }
    //获取记录类型
    char* Hex::GetRecordType()
    {
    	if (strlen(m_cBuffer) == (GetRecordLength() + 5) * 2)
    	{
    		char *type=(char*)malloc(sizeof(char)*3);
    		type[0] = m_cBuffer[6];
    		type[1] = m_cBuffer[7];
    		type[2] = '';
    		m_pRecordType = type;
    		type = NULL;
    	}
    	return m_pRecordType;
    }
    //获取数据
    char* Hex::GetData()
    {
    	if (strlen(m_cBuffer) == (GetRecordLength() + 5) * 2)
    	{
    		int len = GetRecordLength();
    		char *data = (char*)malloc(sizeof(char)*(len * 2 + 1));
    		for (int i = 0; i < len * 2;++i)
    		{
    			data[i] = m_cBuffer[i + 8];
    		}
    		data[len * 2] = '';
    		m_pData = data;
    		data = NULL;
    	}
    	return m_pData;
    }
    //获取校验和
    char* Hex::GetChecksum()
    {
    	int len = GetRecordLength();
    	if (strlen(m_cBuffer) == (len + 5) * 2)
    	{
    		char *checksum=(char*)malloc(sizeof(char)*3);
    		checksum[0] = m_cBuffer[(len + 5) * 2 - 2];
    		checksum[1] = m_cBuffer[(len + 5) * 2-1];
    		checksum[2] = '';
    		m_pChecksum = checksum;
    		checksum=NULL;
    	}
    	return m_pChecksum;
    }
    //解析Hex文件里的每一条记录
    void Hex::ParseRecord(char ch)
    {
    	size_t buf_len = strlen(m_cBuffer);
    	if (GetRecordMark()==ch)
    	{
    		m_bRecvStatus = true;
    		m_cBuffer[0] = '';
    		//m_nIndex = 0;
    		return;
    	}
    	if ((buf_len==(GetRecordLength()+5)*2-1))
    	{
    		//接收最后一个字符
    		m_cBuffer[buf_len] = ch;
    		m_cBuffer[buf_len + 1] = '';
    		//检验接收的数据
    		char temp[3];
    		char *p = NULL;
    		long int checksum = 0;
    		for (int i = 0; i < strlen(m_cBuffer);i+=2)
    		{
    			temp[0] = m_cBuffer[i];
    			temp[1] = m_cBuffer[i + 1];
    			temp[2] = '';
    			checksum += strtol(temp, &p, 16);
    			temp[0] = '';
    		}
    		checksum &= 0x00ff;//取计算结果的低8位
    		if (checksum==0)//checksum为0说明接收的数据无误
    		{
    			cout << "RecordMark " << GetRecordMark() << endl;
    			cout << "RecordLength " << GetRecordLength() << endl;
    			cout << "LoadOffset " << GetLoadOffset() << endl;
    			cout << "RecordType " << GetRecordType() << endl;
    			cout << "Data " << GetData() << endl;
    			cout << "Checksum " << GetChecksum() << endl;
    		}
    		else//否则接收数据有误
    		{
    			cout << "Error!" << endl;
    		}
    		m_cBuffer[0] = '';
    		m_bRecvStatus = false;
    		m_nRecordLength = 0;
    		m_pLoadOffset = NULL;
    		m_pRecordType = NULL;
    		m_pChecksum = NULL;
    		m_bRecvStatus = false;
    	}
    	else if (m_bRecvStatus)
    	{
    		m_cBuffer[buf_len] = ch;
    		m_cBuffer[buf_len + 1] = '';
    		//m_nIndex++;
    	}
    }
    //解析Hex文件
    void Hex::ParseHex(char *data)
    {
    	for (int i = 0; i < strlen(data);++i)
    	{
    		ParseRecord(data[i]);
    	}
    }
    int main(int argc, char *argv[])
    {
    	freopen("in.txt", "r", stdin);
    	freopen("out.txt", "w", stdout);
    
    	Hex hex(':');
    	char ch;
    	while (cin>>ch)
    	{
    		hex.ParseRecord(ch);
    	}
    	fclose(stdout);
    	fclose(stdin);
    	return 0;
    }
    

    in.txt是在Arduino IDE编译blink程序生成的blik.cpp.hex的原始内容,直接复制到记事本中,其内容例如以下:

    :100000000C945C000C946E000C946E000C946E00CA
    :100010000C946E000C946E000C946E000C946E00A8
    :100020000C946E000C946E000C946E000C946E0098
    :100030000C946E000C946E000C946E000C946E0088
    :100040000C9488000C946E000C946E000C946E005E
    :100050000C946E000C946E000C946E000C946E0068
    :100060000C946E000C946E00000000080002010069
    :100070000003040700000000000000000102040863
    :100080001020408001020408102001020408102002
    :10009000040404040404040402020202020203032E
    :1000A0000303030300000000250028002B000000CC
    :1000B0000000240027002A0011241FBECFEFD8E043
    :1000C000DEBFCDBF21E0A0E0B1E001C01D92A930AC
    :1000D000B207E1F70E94F1010C9401020C940000B8
    :1000E00061E08DE00C94810161E08DE00E94BA0135
    :1000F00068EE73E080E090E00E94F50060E08DE043
    :100100000E94BA0168EE73E080E090E00C94F50084
    :100110001F920F920FB60F9211242F933F938F933C
    :100120009F93AF93BF938091010190910201A091A1
    :100130000301B09104013091000123E0230F2D371A
    :1001400020F40196A11DB11D05C026E8230F0296DB
    :10015000A11DB11D20930001809301019093020124
    :10016000A0930301B09304018091050190910601D1
    :10017000A0910701B09108010196A11DB11D8093C6
    :10018000050190930601A0930701B0930801BF9168
    :10019000AF919F918F913F912F910F900FBE0F9034
    :1001A0001F9018953FB7F894809105019091060132
    :1001B000A0910701B091080126B5A89B05C02F3F6B
    :1001C00019F00196A11DB11D3FBF6627782F892F19
    :1001D0009A2F620F711D811D911D42E0660F771FDE
    :1001E000881F991F4A95D1F70895CF92DF92EF9219
    :1001F000FF92CF93DF936B017C010E94D200EB0151
    :10020000C114D104E104F10489F00E9400020E94AB
    :10021000D2006C1B7D0B683E734090F381E0C81ADE
    :10022000D108E108F108C851DC4FEACFDF91CF9146
    :10023000FF90EF90DF90CF900895789484B582601E
    :1002400084BD84B5816084BD85B5826085BD85B57A
    :10025000816085BDEEE6F0E0808181608083E1E829
    :10026000F0E0108280818260808380818160808361
    :10027000E0E8F0E0808181608083E1EBF0E0808164
    :1002800084608083E0EBF0E0808181608083EAE736
    :10029000F0E08081846080838081826080838081BF
    :1002A000816080838081806880831092C10008957E
    :1002B000833081F028F4813099F08230A1F00895E4
    :1002C0008730A9F08830B9F08430D1F48091800073
    :1002D0008F7D03C0809180008F7780938000089588
    :1002E00084B58F7702C084B58F7D84BD08958091D9
    :1002F000B0008F7703C08091B0008F7D8093B000F5
    :100300000895CF93DF9390E0FC01E458FF4F2491D0
    :10031000FC01E057FF4F8491882349F190E0880F5A
    :10032000991FFC01E255FF4FA591B4918C559F4F49
    :10033000FC01C591D4919FB7611108C0F8948C91CC
    :10034000209582238C93888182230AC0623051F4E5
    :10035000F8948C91322F309583238C938881822B53
    :10036000888304C0F8948C91822B8C939FBFDF917B
    :10037000CF9108950F931F93CF93DF931F92CDB723
    :10038000DEB7282F30E0F901E859FF4F8491F901D9
    :10039000E458FF4F1491F901E057FF4F04910023F7
    :1003A000C9F0882321F069830E9458016981E02FF8
    :1003B000F0E0EE0FFF1FEC55FF4FA591B4919FB7F2
    :1003C000F8948C91611103C01095812301C0812B99
    :1003D0008C939FBF0F90DF91CF911F910F91089544
    :1003E00008950E941D010E94F0010E947000C0E06B
    :1003F000D0E00E9474002097E1F30E940000F9CF42
    :060400000895F894FFCFFF
    :00000001FF
    

    解析的结果直接写入到记事本中。结果例如以下:

    RecordMark :
    RecordLength 16
    LoadOffset 0000
    RecordType 00
    Data 0C945C000C946E000C946E000C946E00
    Checksum CA
    RecordMark :
    RecordLength 16
    LoadOffset 0010
    RecordType 00
    Data 0C946E000C946E000C946E000C946E00
    Checksum A8
    RecordMark :
    RecordLength 16
    LoadOffset 0020
    RecordType 00
    Data 0C946E000C946E000C946E000C946E00
    Checksum 98
    RecordMark :
    RecordLength 16
    LoadOffset 0030
    RecordType 00
    Data 0C946E000C946E000C946E000C946E00
    Checksum 88
    RecordMark :
    RecordLength 16
    LoadOffset 0040
    RecordType 00
    Data 0C9488000C946E000C946E000C946E00
    Checksum 5E
    RecordMark :
    RecordLength 16
    LoadOffset 0050
    RecordType 00
    Data 0C946E000C946E000C946E000C946E00
    Checksum 68
    RecordMark :
    RecordLength 16
    LoadOffset 0060
    RecordType 00
    Data 0C946E000C946E000000000800020100
    Checksum 69
    RecordMark :
    RecordLength 16
    LoadOffset 0070
    RecordType 00
    Data 00030407000000000000000001020408
    Checksum 63
    RecordMark :
    RecordLength 16
    LoadOffset 0080
    RecordType 00
    Data 10204080010204081020010204081020
    Checksum 02
    RecordMark :
    RecordLength 16
    LoadOffset 0090
    RecordType 00
    Data 04040404040404040202020202020303
    Checksum 2E
    RecordMark :
    RecordLength 16
    LoadOffset 00A0
    RecordType 00
    Data 0303030300000000250028002B000000
    Checksum CC
    RecordMark :
    RecordLength 16
    LoadOffset 00B0
    RecordType 00
    Data 0000240027002A0011241FBECFEFD8E0
    Checksum 43
    RecordMark :
    RecordLength 16
    LoadOffset 00C0
    RecordType 00
    Data DEBFCDBF21E0A0E0B1E001C01D92A930
    Checksum AC
    RecordMark :
    RecordLength 16
    LoadOffset 00D0
    RecordType 00
    Data B207E1F70E94F1010C9401020C940000
    Checksum B8
    RecordMark :
    RecordLength 16
    LoadOffset 00E0
    RecordType 00
    Data 61E08DE00C94810161E08DE00E94BA01
    Checksum 35
    RecordMark :
    RecordLength 16
    LoadOffset 00F0
    RecordType 00
    Data 68EE73E080E090E00E94F50060E08DE0
    Checksum 43
    RecordMark :
    RecordLength 16
    LoadOffset 0100
    RecordType 00
    Data 0E94BA0168EE73E080E090E00C94F500
    Checksum 84
    RecordMark :
    RecordLength 16
    LoadOffset 0110
    RecordType 00
    Data 1F920F920FB60F9211242F933F938F93
    Checksum 3C
    RecordMark :
    RecordLength 16
    LoadOffset 0120
    RecordType 00
    Data 9F93AF93BF938091010190910201A091
    Checksum A1
    RecordMark :
    RecordLength 16
    LoadOffset 0130
    RecordType 00
    Data 0301B09104013091000123E0230F2D37
    Checksum 1A
    RecordMark :
    RecordLength 16
    LoadOffset 0140
    RecordType 00
    Data 20F40196A11DB11D05C026E8230F0296
    Checksum DB
    RecordMark :
    RecordLength 16
    LoadOffset 0150
    RecordType 00
    Data A11DB11D209300018093010190930201
    Checksum 24
    RecordMark :
    RecordLength 16
    LoadOffset 0160
    RecordType 00
    Data A0930301B09304018091050190910601
    Checksum D1
    RecordMark :
    RecordLength 16
    LoadOffset 0170
    RecordType 00
    Data A0910701B09108010196A11DB11D8093
    Checksum C6
    RecordMark :
    RecordLength 16
    LoadOffset 0180
    RecordType 00
    Data 050190930601A0930701B0930801BF91
    Checksum 68
    RecordMark :
    RecordLength 16
    LoadOffset 0190
    RecordType 00
    Data AF919F918F913F912F910F900FBE0F90
    Checksum 34
    RecordMark :
    RecordLength 16
    LoadOffset 01A0
    RecordType 00
    Data 1F9018953FB7F8948091050190910601
    Checksum 32
    RecordMark :
    RecordLength 16
    LoadOffset 01B0
    RecordType 00
    Data A0910701B091080126B5A89B05C02F3F
    Checksum 6B
    RecordMark :
    RecordLength 16
    LoadOffset 01C0
    RecordType 00
    Data 19F00196A11DB11D3FBF6627782F892F
    Checksum 19
    RecordMark :
    RecordLength 16
    LoadOffset 01D0
    RecordType 00
    Data 9A2F620F711D811D911D42E0660F771F
    Checksum DE
    RecordMark :
    RecordLength 16
    LoadOffset 01E0
    RecordType 00
    Data 881F991F4A95D1F70895CF92DF92EF92
    Checksum 19
    RecordMark :
    RecordLength 16
    LoadOffset 01F0
    RecordType 00
    Data FF92CF93DF936B017C010E94D200EB01
    Checksum 51
    RecordMark :
    RecordLength 16
    LoadOffset 0200
    RecordType 00
    Data C114D104E104F10489F00E9400020E94
    Checksum AB
    RecordMark :
    RecordLength 16
    LoadOffset 0210
    RecordType 00
    Data D2006C1B7D0B683E734090F381E0C81A
    Checksum DE
    RecordMark :
    RecordLength 16
    LoadOffset 0220
    RecordType 00
    Data D108E108F108C851DC4FEACFDF91CF91
    Checksum 46
    RecordMark :
    RecordLength 16
    LoadOffset 0230
    RecordType 00
    Data FF90EF90DF90CF900895789484B58260
    Checksum 1E
    RecordMark :
    RecordLength 16
    LoadOffset 0240
    RecordType 00
    Data 84BD84B5816084BD85B5826085BD85B5
    Checksum 7A
    RecordMark :
    RecordLength 16
    LoadOffset 0250
    RecordType 00
    Data 816085BDEEE6F0E0808181608083E1E8
    Checksum 29
    RecordMark :
    RecordLength 16
    LoadOffset 0260
    RecordType 00
    Data F0E01082808182608083808181608083
    Checksum 61
    RecordMark :
    RecordLength 16
    LoadOffset 0270
    RecordType 00
    Data E0E8F0E0808181608083E1EBF0E08081
    Checksum 64
    RecordMark :
    RecordLength 16
    LoadOffset 0280
    RecordType 00
    Data 84608083E0EBF0E0808181608083EAE7
    Checksum 36
    RecordMark :
    RecordLength 16
    LoadOffset 0290
    RecordType 00
    Data F0E08081846080838081826080838081
    Checksum BF
    RecordMark :
    RecordLength 16
    LoadOffset 02A0
    RecordType 00
    Data 816080838081806880831092C1000895
    Checksum 7E
    RecordMark :
    RecordLength 16
    LoadOffset 02B0
    RecordType 00
    Data 833081F028F4813099F08230A1F00895
    Checksum E4
    RecordMark :
    RecordLength 16
    LoadOffset 02C0
    RecordType 00
    Data 8730A9F08830B9F08430D1F480918000
    Checksum 73
    RecordMark :
    RecordLength 16
    LoadOffset 02D0
    RecordType 00
    Data 8F7D03C0809180008F77809380000895
    Checksum 88
    RecordMark :
    RecordLength 16
    LoadOffset 02E0
    RecordType 00
    Data 84B58F7702C084B58F7D84BD08958091
    Checksum D9
    RecordMark :
    RecordLength 16
    LoadOffset 02F0
    RecordType 00
    Data B0008F7703C08091B0008F7D8093B000
    Checksum F5
    RecordMark :
    RecordLength 16
    LoadOffset 0300
    RecordType 00
    Data 0895CF93DF9390E0FC01E458FF4F2491
    Checksum D0
    RecordMark :
    RecordLength 16
    LoadOffset 0310
    RecordType 00
    Data FC01E057FF4F8491882349F190E0880F
    Checksum 5A
    RecordMark :
    RecordLength 16
    LoadOffset 0320
    RecordType 00
    Data 991FFC01E255FF4FA591B4918C559F4F
    Checksum 49
    RecordMark :
    RecordLength 16
    LoadOffset 0330
    RecordType 00
    Data FC01C591D4919FB7611108C0F8948C91
    Checksum CC
    RecordMark :
    RecordLength 16
    LoadOffset 0340
    RecordType 00
    Data 209582238C93888182230AC0623051F4
    Checksum E5
    RecordMark :
    RecordLength 16
    LoadOffset 0350
    RecordType 00
    Data F8948C91322F309583238C938881822B
    Checksum 53
    RecordMark :
    RecordLength 16
    LoadOffset 0360
    RecordType 00
    Data 888304C0F8948C91822B8C939FBFDF91
    Checksum 7B
    RecordMark :
    RecordLength 16
    LoadOffset 0370
    RecordType 00
    Data CF9108950F931F93CF93DF931F92CDB7
    Checksum 23
    RecordMark :
    RecordLength 16
    LoadOffset 0380
    RecordType 00
    Data DEB7282F30E0F901E859FF4F8491F901
    Checksum D9
    RecordMark :
    RecordLength 16
    LoadOffset 0390
    RecordType 00
    Data E458FF4F1491F901E057FF4F04910023
    Checksum F7
    RecordMark :
    RecordLength 16
    LoadOffset 03A0
    RecordType 00
    Data C9F0882321F069830E9458016981E02F
    Checksum F8
    RecordMark :
    RecordLength 16
    LoadOffset 03B0
    RecordType 00
    Data F0E0EE0FFF1FEC55FF4FA591B4919FB7
    Checksum F2
    RecordMark :
    RecordLength 16
    LoadOffset 03C0
    RecordType 00
    Data F8948C91611103C01095812301C0812B
    Checksum 99
    RecordMark :
    RecordLength 16
    LoadOffset 03D0
    RecordType 00
    Data 8C939FBF0F90DF91CF911F910F910895
    Checksum 44
    RecordMark :
    RecordLength 16
    LoadOffset 03E0
    RecordType 00
    Data 08950E941D010E94F0010E947000C0E0
    Checksum 6B
    RecordMark :
    RecordLength 16
    LoadOffset 03F0
    RecordType 00
    Data D0E00E9474002097E1F30E940000F9CF
    Checksum 42
    RecordMark :
    RecordLength 6
    LoadOffset 0400
    RecordType 00
    Data 0895F894FFCF
    Checksum FF
    RecordMark :
    RecordLength 0
    LoadOffset 0000
    RecordType 01
    Data 
    Checksum FF

    參考文献

    [1]Wikipedia.Intel HEX[DB/OL].http://en.wikipedia.org/wiki/Intel_HEX,2016,4


  • 相关阅读:
    组件映射
    联合主键关联
    一对一单向双向主键关联
    7函数
    forEach与map
    3运算符与表达式
    作用域声明提升
    php程序设计 1,2章节
    angularJs(3)过滤器
    angularJs(1)指令篇
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7222987.html
Copyright © 2020-2023  润新知