精华内容
参与话题
问答
  • Hex编码 十六进制编码

    千次阅读 2018-07-18 11:06:29
    import java.io.UnsupportedEncodingException;... * HEX字符串与字节码(字符串)转换工具  */ public class HexUtils {  public static void main(String[] args) throws Exception {  ...
    1. 
      import java.io.UnsupportedEncodingException;
      import java.net.URLEncoder;
      /**
       * HEX字符串与字节码(字符串)转换工具
       */
      public class HexUtils {
          public static void main(String[] args) throws Exception {
              test("a");//编码前【a】编码后【61】解码后【a】
              test("A");//编码前【A】编码后【41】解码后【A】
              test("1");//编码前【1】编码后【31】解码后【1】
              test("白");//编码前【白】编码后【E799BD】解码后【白】
              test("白乾涛");//编码前【白乾涛】编码后【E799BDE4B9BEE6B69B】解码后【白乾涛】
              System.out.println(URLEncoder.encode("白乾涛", "UTF-8"));//和上述编码结果一致【%E7%99%BD%E4%B9%BE%E6%B6%9B】
              System.out.println(encodeHex("白乾涛".getBytes("UTF-8")));//使用apache的工具类编码和上述编码结果一致【e799bde4b9bee6b69b】
              System.out.println(new String(decodeHex("e799bde4b9bee6b69b".toCharArray()), "UTF-8"));
          }
          private static void test(String input) throws UnsupportedEncodingException {
              String charsetName = "UTF-8";
              System.out.print("编码前【" + input + "】");
              System.out.print("编码后【" + str2HexStr(input, charsetName) + "】");
              System.out.println("解码后【" + hexStr2Str(str2HexStr2(input, charsetName), charsetName) + "】");
          }
          //******************************************************************************************
          //                       参数或返回值为字符串
          //******************************************************************************************
          /**
           * 将原始字符串转换成16进制字符串【方法一】
           */
          public static String str2HexStr(String input, String charsetName) throws UnsupportedEncodingException {
              byte buf[] = input.getBytes(charsetName);
              StringBuffer sb = new StringBuffer();
              for (int i = 0; i < buf.length; i++) {
                  //以十六进制(基数 16)无符号整数形式返回一个整数参数的字符串表示形式。
                  //如果参数为负,那么无符号整数值为参数加上 2^32;否则等于该参数。将该值转换为十六进制(基数 16)的无前导 0 的 ASCII 数字字符串。
                  //如果无符号数的大小值为零,则用一个零字符 '0' (’\u0030’) 表示它;否则,无符号数大小的表示形式中的第一个字符将不是零字符。
                  //用以下字符作为十六进制数字【0123456789abcdef】。这些字符的范围是从【'\u0030' 到 '\u0039'】和从【'\u0061' 到 '\u0066'】。
                  String hex = Integer.toHexString(buf[i] & 0xFF);//其实核心也就这一样代码
                  if (hex.length() == 1) hex = '0' + hex;
                  sb.append(hex.toUpperCase());
              }
              return sb.toString();
          }
          /**
           * 将原始字符串转换成16进制字符串【方法二】
           */
          public static String str2HexStr2(String str, String charsetName) throws UnsupportedEncodingException {
              byte[] bs = str.getBytes(charsetName);
              char[] chars = "0123456789ABCDEF".toCharArray();
              StringBuilder sb = new StringBuilder();
              for (int i = 0, bit; i < bs.length; i++) {
                  bit = (bs[i] & 0x0f0) >> 4;
                  sb.append(chars[bit]);
                  bit = bs[i] & 0x0f;
                  sb.append(chars[bit]);
              }
              return sb.toString();
          }
          /**
           * 将16进制字符串转换为原始字符串
           */
          public static String hexStr2Str(String hexStr, String charsetName) throws UnsupportedEncodingException {
              if (hexStr.length() < 1) return null;
              byte[] hexbytes = new byte[hexStr.length() / 2];
              for (int i = 0; i < hexStr.length() / 2; i++) {
                  int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
                  int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
                  hexbytes[i] = (byte) (high * 16 + low);
              }
              return new String(hexbytes, charsetName);
          }
          //******************************************************************************************
          //                                                                      参数或返回值为字节数组
          //******************************************************************************************
          /**
           * 将二进制转换成16进制
           */
          public static String encode(byte buf[]) {
              StringBuffer sb = new StringBuffer();
              for (int i = 0; i < buf.length; i++) {
                  String hex = Integer.toHexString(buf[i] & 0xFF);
                  if (hex.length() == 1) hex = '0' + hex;
                  sb.append(hex.toUpperCase());
              }
              return sb.toString();
          }
          /**
           * 将16进制转换为二进制(服务端)
           */
          public static byte[] deocde(String hexStr) {
              if (hexStr.length() < 1) return null;
              byte[] result = new byte[hexStr.length() / 2];
              for (int i = 0; i < hexStr.length() / 2; i++) {
                  int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
                  int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2), 16);
                  result[i] = (byte) (high * 16 + low);
              }
              return result;
          }
          //******************************************************************************************
          //                          org.apache.commons.codec.binary.Hex的实现方式
          //******************************************************************************************
          private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
          public static char[] encodeHex(byte[] data) {
              int l = data.length;
              char[] out = new char[l << 1];
              int i = 0;
              for (int j = 0; i < l; i++) {
                  out[(j++)] = DIGITS[((0xF0 & data[i]) >>> 4)];
                  out[(j++)] = DIGITS[(0xF & data[i])];
              }
              return out;
          }
          public static byte[] decodeHex(char[] data) throws Exception {
              int len = data.length;
              if ((len & 0x1) != 0) throw new Exception("Odd number of characters.");
              byte[] out = new byte[len >> 1];
              int i = 0;
              for (int j = 0; j < len; i++) {
                  int f = toDigit(data[j], j) << 4;
                  j++;
                  f |= toDigit(data[j], j);
                  j++;
                  out[i] = ((byte) (f & 0xFF));
              }
              return out;
          }
          private static int toDigit(char ch, int index) throws Exception {
              int digit = Character.digit(ch, 16);
              if (digit == -1) throw new Exception("Illegal hexadecimal charcter " + ch + " at index " + index);
              return digit;
          }
      }

      转载自:https://www.cnblogs.com/baiqiantao/p/a15999e101a1cf16224bf54d303eaee7.html

    展开全文
  • HEX文件格式详解

    万次阅读 多人点赞 2018-08-07 11:08:13
    之前写的比较随意,但发现查找该信息的同学还比较多。 所以文章后部分增加了通俗易懂的版本。便于同学们查阅。请往后看补充内容....  ******************** ...如图,其中第一行020000040002f8中,可以看做是0x...

    之前写的比较随意,但发现查找该信息的同学还比较多。

    所以文章后部分增加了通俗易懂的版本。便于同学们查阅。请往后看补充内容....

    

    ********************

    

    如图,其中第一行020000040002f8中,可以看做是0x02 0x00 0x00 0x04 0x00 0x02 0xf8,其前四个字节和最后一个字节有特殊含义。中间为数据

    第一个0×02表示该行数据中有两个数据

    第二个,第三个0x00 0x00表示本行数据的起始地址位

    第四个字节有0x00 0x01 0x02 0x03 0x04 0x05,分别有以下含义

    '00'Data Rrecord:用来记录数据,HEX文件的大部分记录都是数据记录

    '01'文件结束记录:用来标识文件结束,放在文件的最后,标识HEX文件的结尾

    '02'扩展段地址记录:用来标识扩展段地址的记录

    '03'开始段地址记录:开始段地址记录

    '04'扩展线性地址记录:用来标识扩展线性地址的记录

    '05'开始线性地址记录:开始线性地址记录

    最后一个字节0xf8为校验和校验和= 0x100 - 累加和。在nodepad++中,如果该校验和不是绿色,则表示该校验和是错的。

    注意,0×04标识扩展线性地址的记录,所以如上图中的020000040002f8中,拓展地址是0002。那么第二行数据的起始地址就是0002c000,即0x0002c000开始

     

    补充内容开始:

    前面记录的比较简单,但看起来还是不好理解,下面是详细通俗易懂版本的hex文件说明,应该能满足大部分同学的需要。

    第一字节表示该行的数据字节数;如第1行只有 0x08 0x00 两个字节的数据,类型是 04 ,即该行记录的是一个拓展地址(0x08 0x00 是地址信息,用法是将该地址(0x0800<<16) 后作为基地址。并且表示在下一个04类型行出现之前都要使用该地址.

    例如第2行的地址信息是 0x0000,则表示该行数据从0x08000000( (0x0800<<16) | 0x0000 )开始记录。

    第3行则从 0x08000010 ( (0x0800<<16) | 0x0010 )开始记录。

    另外最后一个字节的校验和 0xBA = 0xff & ( 0x100- (0x10+4*(0x00)+0x5F+0x00+...+0x00+0x08) ) = 0xff & (0x100-0x246)

    没错,就是从每行的第一个字节开始计算

     

    小技巧: 在nodepad++中,如果校验和不是绿色,则表示校验和错误,如上图中的第6行.正确的应该是 BA

     

    16行位置只有四个数据,但是 标注类型是 05, 即他是一个 “开始线性地址记录”。
    说那么多,什么是开始线性地址记录呢?其实他就是函数入口地址
    例如我的 .map 文件中可以看到以下信息

    Memory Map of the image

      Image Entry point : 0x08020189
      ....
        __Vectors_End                            0x08020188   Data           0     ......
        __main                                        0x08020189   Thumb Code     0  entry.o(.ARM.Collect$$$$00000000)
        _main_stk                                   0x08020189   Thumb Code     0  entry2.o(.ARM.Collect$$$$00000001)
        _main_scatterload                      0x0802018d   Thumb Code     0  entry5.o(.ARM.Collect$$$$00000004)
      ....

     

    这一行就是类型是 0x01, 表示文件结束.

    附nodepad++文件链接(无需积分): https://download.csdn.net/download/weixin_39752827/12106358

     ----------------------------------总是会自己变成需要积分下载的状态... 我修改了几次了,,再次上传网盘链接

    链接:https://pan.baidu.com/s/1pZVNJiRBRWUKZa9igzfmWw 
    提取码:wrp8

     

     

    展开全文
  • Hex和Bin的区别

    万次阅读 2018-01-29 11:12:53
    因为自己也是新手,所以一直对这两个文件懵懵懂懂,不甚了解,最近在做STM32单片机的IAP更新,其中要考虑HEX文件和BIN文件,所以需要学习下这两种文件。下面是最近的我的了解,如有不对地方还请指正。

    转自:http://blog.csdn.net/spdian/article/details/52963467     


      HEX文件和BIN文件是我们经常碰到的2种文件格式。因为自己也是新手,所以一直对这两个文件懵懵懂懂,不甚了解,最近在做STM32单片机的IAP更新,其中要考虑HEX文件和BIN文件,所以需要学习下这两种文件。下面是最近的我的了解,如有不对地方还请指正。

    1. HEX文件是包括地址信息的,而BIN文件格式只包括了数据本身
        在烧写或下载HEX文件的时候,一般都不需要用户指定地址,因为HEX文件内部的信息已经包括了地址。而烧写BIN文件的时候,用户是一定需要指定地址信息的。

    2. HEX文件格式
        HEX文件都是由记录(RECORD)组成的。在HEX文件里面,每一行代表一个记录。以下为记录(Record)的具体格式:

     Record structure

      A record (line of text) consists of six fields (parts) that appear in order from left to right:

    1. Start code, one character, an ASCII colon ':'.
    2. Byte count, two hex digits, indicating the number of bytes (hex digit pairs) in the data field. The maximum byte count is 255 (0xFF). 16 (0x10) and 32 (0x20) are commonly used byte counts.
    3. Address, four hex digits, representing the 16-bit beginning memory address offset of the data. The physical address of the data is computed by adding this offset to a previously established base address, thus allowing memory addressing beyond the 64 kilobyte limit of 16-bit addresses. The base address, which defaults to zero, can be changed by various types of records. Base addresses and address offsets are always expressed as big endian values.
    4. Record type (see record types below), two hex digits, 00 to 05, defining the meaning of the data field.
    5. Data, a sequence of n bytes of data, represented by 2n hex digits. Some records omit this field (n equals zero). The meaning and interpretation of data bytes depends on the application.
    6. Checksum, two hex digits, a computed value that can be used to verify the record has no errors.


         看个例子:
         :020000040000FA
         :10000400FF00A0E314209FE5001092E5011092E5A3
         :00000001FF         
           
          对上面的HEX文件进行分析:
          第1条记录的长度为02,LOAD OFFSET为0000,RECTYPE为04,说明该记录为扩展段地址记录。数据为0000,校验和为FA。从这个记录的长度和数据,我们可以计算出一个基地址,这个地址为0X0000。后面的数据记录都以这个地址为基地址。
          第2条记录的长度为10(16),LOAD OFFSET为0004,RECTYPE为00,说明该记录为数据记录。数据为FF00A0E314209FE5001092E5011092E5,共16个BYTE。这个记录的校验和为A3。此时的基地址为0X0000,加上OFFSET,这个记录里的16BYTE的数据的起始地址就是0x0000 + 0x0004 = 0x0004.
            第3条记录的长度为00,LOAD OFFSET为0000,TYPE = 01,校验和为FF。说明这个是一个END OF FILE RECORD,标识文件的结尾。
           
            在上面这个例子里,实际的数据只有16个BYTE:FF00A0E314209FE5001092E5011092E5,其起始地址为0x4。

    3. BIN文件格式
        对二进制文件而言,其实没有”格式”。文件只是包括了纯粹的二进制数据。

    4. HEX文件是用ASCII来表示二进制的数值。例如一般8-BIT的二进制数值0x3F,用ASCII来表示就需要分别表示字符'3'和字符'F',每个字符需要一个BYTE,所以HEX文件需要 > 2倍的空间。
        对一个BIN文件而言,你查看文件的大小就可以知道文件包括的数据的实际大小。而对HEX文件而言,你看到的文件 大小并不是实际的数据的大小。一是因为HEX文件是用ASCII来表示数据,二是因为HEX文件本身还包括别的附加信息。



    另外一篇博客的解释



    1.分析一下hex文件

      HEX格式文件以行为单位,每行由“:”(16进制为:0x3a)开始,以回车键结束(16进制为:0x0d,0x0a)。行内的数据都是由两个字符表示一个16进制字节,比如”01”就表示数0x01;”0a”,就表示0x0a。对于16位的地址,则高位在前低位在后,比如地址0x010a,在HEX格式文件中就表示为字符串”010a”。

    下面为HEX文件中的一行,分析一下:

    :10000000FF0462FF051EFF0A93FF0572FF0A93FF

    “:” 表示一行的开始。

    “:” 后的第1,2个字符“10”表示本行包含的数据的长度,这里就是0x10即16个。

     第3,4,5,6个字符“0000”表示数据存储的起始地址,这里表示从0x0000地址开始存储16个数据,其中高位地址在前,低位地址在后。

    第7,8个字符“00”表示数据的类型。该类型总共有以下几种:

    00 ----数据记录      

    01 ----文件结束记录

    02 ----扩展段地址记录

    04 ----扩展线性地址记录

    这里就是0x00即为普通数据记录。

    自后的32个字符FF0462FF051EFF0A93FF0572FF0A93FF就是本行包含的数据,每两个字符表示一个字节数据,总共有16个字节数据跟行首的记录的长度相一致。

    最后两个字符BC表示校验码。

     

    再分析一个实际编译出来的hex文件:


    第一行为:020000040000FA

    “:” 表示一行的开始。

    “:” 后的第1,2个字符“02”表示本行包含的数据的长度,这里就是0x02即2个。

     第3,4,5,6个字符“0000”表示数据存储的起始地址,这里表示从0x0000地址开始存储2个数据,其中高位地址在前,低位地址在后。

    第7,8个字符“04”表示数据的类型。该类型总共有以下几种:

    00 ----数据记录      

    01 ----文件结束记录

    02 ----扩展段地址记录

    04 ----扩展线性地址记录

    这里就是0x04即为扩展线性地址记录。

    自后的4个字符0000就是本行包含的数据,每两个字符表示一个字节数据,总共有2个字节数据跟行首的记录的长度相一致。

    最后两个字符FA 表示校验码。

     

    每个HEX格式的最后一行都是固定为:

    :00000001FF

    01表示文件结束记录

     

    2.hex文件和bin文件的对比

    1 : HEX文件是包括地址信息的,而BIN文件格式只包括了数据本身。在烧写或下载HEX文件的时候,一般都不需要用户指定地址,因为HEX文件内部的信息已经包括了地址。而烧写BIN文件的时候,用户是一定需要指定地址信息的

    2 :BIN文件格式  对二进制文件而言,其实没有”格式”。文件只是包括了纯粹的二进制数据。

    3:HEX文件格式  HEX文件都是由记录(RECORD)组成的。在HEX文件里面,每一行代表一个记录。记录的基本格式为:

    | RECORD | RECLEN | LOAD | RECTYPE | INFO or DATA | CHKSUM |

    | MARK ':' |               | OFFSET |

    记录类型包括: 

    '00' Data Rrecord:用来记录数据,HEX文件的大部分记录都是数据记录

     '01' End of FileRecord: 用来标识文件结束,放在文件的最后,标识HEX文件的结尾

    '02' Extended Segment Address Record: 用来标识扩展段地址的记录

     '04' Extended LinearAddress Record: 用来标识扩展线性地址的记录

    4: HEX文件和BIN文件大小有区别,  HEX文件是用ASCII来表示二进制的数值。例如一般8-BIT的二进制数值0x3F,用ASCII来表示就需要分别表示字符'3'和字符'F',每个字符需要一个BYTE,所以HEX文件需要> 2倍BIN文件的空间。对一个BIN文件而言,你查看文件的大小就可以知道文件包括的数据的实际大小。而对HEX文件而言,你看到的文件大小并不是实际的数据的大小。一是因为HEX文件是用ASCII来表示数据,二是因为HEX文件本身还包括别的附加信息(:,长度,)。

        Bin文件是最纯粹的二进制机器代码,或者说是"顺序格式"。按照assemblycode顺序翻译成binarymachine code,内部没有地址标记。Bin是直接的内存映象表示,二进制文件大小即为文件所包含的数据的实际大小。



    举个实际的例子,比如源代码中的字符串“MCU start”,对应在bin文件中就是:


    二进制对应的就是:4D 43 55 20 73 74 61 72 74 20 ,用记事本打开显示为MCU start,因为记事本显示的是ASCII码字符。


    对应的hex文件为:



    比如原来的M 对应二进制是4D,对应到hex中就用34 44 来表示,记事本打开显示为4D


    HEX文件转化为BIN文件源程序


    Intel HEX文件是记录文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记录,由十六进制数组成的机器码或者数据常量。Intel HEX文件经常被用于将程序或数据传输存储到ROMEPROM,大多数编程器和模拟器使用Intel HEX文件。

           很多编译器的支持生成HEX格式的烧录文件,尤其是Keil c。但是编程器能够下载的往往是BIN格式,因此HEX转BIN是每个编程器都必须支持的功能。

           HEX格式文件以行为单位,每行由“:”(0x3a)开始,以回车键结束(0x0d,0x0a)。行内的数据都是由两个字符表示一个16进制字节,比如”01”就表示数0x01;”0a”,就表示0x0a。对于16位的地址,则高位在前低位在后,比如地址0x010a,在HEX格式文件中就表示为字符串”010a”。下面为HEX文件中的一行:

    :10000000FF0462FF051EFF0A93FF0572FF0A93FFBC

           “:”表示一行的开始。

           “:”后的第1,2个字符“10”表示本行包含的数据的长度,这里就是0x10即16个。

           第3,4,5,6个字符“0000”表示数据存储的起始地址,这里表示从0x0000地址开始存储16个数据,其中高位地址在前,低位地址在后。

           第7,8个字符“00”表示数据的类型。该类型总共有以下几种:

    00 ----数据记录       
    01 ----文件结束记录
    02 ----扩展段地址记录
    04 ----扩展线性地址记录

    这里就是0x00即为普通数据记录。

    自后的32个字符就是本行包含的数据,每两个字符表示一个字节数据,总共有16个字节数据跟行首的记录的长度相一致。

    最后两个字符表示校验码。

    每个HEX格式的最后一行都是固定为:

    :00000001FF

           以上的信息其实就足够进行HEX转BIN格式的程序的编写。首先我们只处理数据类型为0x00及0x01的情况。0x02表示对应的存储地址超过了64K,由于我的编程器只针对64K以下的单片机,因此在次不处理,0x04也是如此。

           我的编程思路是从文件中一个一个读出字符,根据“:”判断一行的开始,然后每两个字符转换成一个字节,并解释其对应的意义。然后将数据从该行中剥离出来保存到缓冲区中,并最终输出到文件中。

           具体程序如下,该程序在VC2005下采用控制台项目编译,需要在release下编译,在debug模式中会提示一个dll文件无法找到,这可能是VC自身的错误。

    // hextobin.cpp : 定义控制台应用程序的入口点。

    //

     

      1#include "stdafx.h"
      2
      3#include <malloc.h>
      4
      5#include <memory.h>
      6
      7typedef unsigned char BYTE;
      8
      9 
     10
     11//将两个字符转化为一个字节量
     12
     13void CharToByte(char* pChar,BYTE* pByte)
     14
     15{
     16
     17     char h,l;
     18
     19     h=pChar[0];//高位
     20
     21     l=pChar[1];//低位
     22
     23     if(l>='0'&&l<='9')
     24
     25         l=l-'0';
     26
     27     else if(l>='a' && l<='f')
     28
     29         l=l-'a'+0xa;
     30
     31     else if(l>='A' && l<='F')
     32
     33         l=l-'A'+0xa;
     34
     35     if(h>='0'&&h<='9')
     36
     37         h=h-'0';
     38
     39     else if(h>='a' && h<='f')
     40
     41         h=h-'a'+0xa;
     42
     43     else if(h>='A' &&h <='F')
     44
     45         h=h-'A'+0xa;
     46
     47     *pByte=(BYTE)h*16+l;
     48
     49}

     50
     51 
     52
     53int _tmain(int argc, _TCHAR* argv[])
     54
     55{
     56
     57     char fileName[100];
     58
     59     char data[2];
     60
     61     BYTE *outBuf;
     62
     63     FILE *myFile;
     64
     65     int len;
     66
     67     int i;
     68
     69     BYTE adressHigh;
     70
     71     BYTE adressLow;
     72
     73     BYTE dataLen;
     74
     75     BYTE dataType; 
     76
     77     BYTE byteData;
     78
     79     int totalLen;
     80
     81     totalLen = 0;
     82
     83     len = 0;
     84
     85     adressHigh = 0;
     86
     87     adressLow = 0;
     88
     89     dataLen = 0;
     90
     91     dataType = 0;
     92
     93     printf("请输入HEX格式文件名:");
     94
     95     scanf_s("%s",fileName);
     96
     97     printf("\n");
     98
     99     if (fopen_s(&myFile,fileName,"r") != 0)
    100
    101     {
    102
    103         printf("打开文件%s失败!",fileName);
    104
    105     }

    106
    107     //将文件长度计算出来用于申请存储数据的缓冲区
    108
    109     while (!feof(myFile))
    110
    111     {
    112
    113         ++len;
    114
    115         fgetc(myFile);
    116
    117     }

    118
    119     rewind(myFile);
    120
    121     //因为是每两个字符表示一个字节,所以最大的数据个数要少于文件字符个数的一半
    122
    123     outBuf = (BYTE*)malloc(len/2);
    124
    125     memset(outBuf,0xff,len/2);
    126
    127     while (!feof(myFile))
    128
    129     {
    130
    131         //:号表示一行的开始
    132
    133         if (fgetc(myFile) == ':')
    134
    135         {
    136
    137              //一行的头两个字符表示该行包含的数据长度
    138
    139              data[0] = fgetc(myFile);
    140
    141              data[1] = fgetc(myFile);
    142
    143              CharToByte(data,&dataLen);
    144
    145              //一行的第、个字符表示数据存储起始地址的高位
    146
    147              data[0] = fgetc(myFile);
    148
    149              data[1] = fgetc(myFile);
    150
    151              CharToByte(data,&adressHigh);
    152
    153              //一行的第、个字符表示数据存储起始地址的低位
    154
    155              data[0] = fgetc(myFile);
    156
    157              data[1] = fgetc(myFile);
    158
    159              CharToByte(data,&adressLow);
    160
    161              //一行的第、个字符表示数据类型
    162
    163              data[0] = fgetc(myFile);
    164
    165              data[1] = fgetc(myFile);
    166
    167              CharToByte(data,&dataType);
    168
    169              //当数据类型为时,表示本行包含的是普通数据记录
    170
    171              if (dataType == 0x00)
    172
    173              {
    174
    175                   for (i=0;i<dataLen;i++)
    176
    177                   {
    178
    179                       data[0] = fgetc(myFile);
    180
    181                       data[1] = fgetc(myFile);
    182
    183                       CharToByte(data,&byteData);
    184
    185                       outBuf[adressHigh*256+adressLow+i] = byteData;
    186
    187                   }

    188
    189                   totalLen += dataLen;
    190
    191              }

    192
    193              //当数据类型为时,表示到了最后一行
    194
    195              if (dataType == 0x01)
    196
    197              {
    198
    199                   printf("文件结束记录!");
    200
    201              }

    202
    203              //当数据类型为时,表示本行包含的是扩展段地址记录
    204
    205              if (dataType == 0x02)
    206
    207              {
    208
    209                   printf("不支持扩展段地址记录!");
    210
    211                   return 0;
    212
    213              }

    214
    215              //当数据类型为时,表示本行包含的是扩展线性地址记录
    216
    217              if (dataType == 0x04)
    218
    219              {
    220
    221                   printf("不支持扩展线性地址记录!");
    222
    223                   return 0;
    224
    225              }

    226
    227         }

    228
    229     }

    230
    231     fclose(myFile);
    232
    233     printf("请输入保存的BIN格式文件名:");
    234
    235     scanf_s("%s",fileName);
    236
    237     if (fopen_s(&myFile,fileName,"w") != 0)
    238
    239     {
    240
    241         printf("打开文件%s失败!",fileName);
    242
    243     }

    244
    245     for (i=0;i<totalLen;i++)
    246
    247     {
    248
    249         fputc(outBuf[i],myFile);
    250
    251     }

    252
    253     return 0;
    254
    255}





    256


    Hex、bin、axf、elf格式文件小结


    一、HEX

    Hex文件,一般是指Intel标准的十六进制文件。Intelhex 文件常用来保存单片机或其他处理器的目标程序代码。它保存物理程序存储区中的目标代码映象。一般编程器均支持生成此种格式文件。如,KEIL下可通过配置相关选项来生成HEX目标文件。


    HEX文件由记录(RECORD)组成。在HEX文件里面,每一行代表一个记录。

    形如 
    :BBAAAATTHHHH...HHHHCC 

    BB:字节个数。 

    AAAA:数据记录的开始地址,高位在前,低位在后。

    TT: Type 

    00数据记录,用来记录数据。

    01记录结束,放在文件末尾,用来标识文件结束。

    02用来标识扩展段地址的记录 

    04扩展地址记录(表示32位地址的前缀)

    HHHH:一个字(Word)的数据记录,高字节在前,低字节在后。TT之后共有 BB/2 个字的数据 
    CC: 
    占据一个ByteCheckSum 

    举例分析:

    :020000040000FA
    :10000400FF00A0E314209FE5001092E5011092E5A3
    :00000001FF         

    第1条记录长度为0x02,LOAD OFFSET为0000,RECTYPE为04,说明该记录为扩展段地址记录。数据为0000,校验和为FA。从这个记录的长度和数据,我们可以计算出基地址为0X0000。后面的数据记录都以此地址为基地址。
    第2条记录长度为0x10(16),LOAD OFFSET为0004,RECTYPE为00,说明该记录为数据记录。数据为FF00A0E314209FE5001092E5011092E5,共16个字节,记录的校验和为A3。此时的基地址为0X0000,加上OFFSET,这个记录里的16BYTE的数据的起始地址就是0x0000 + 0x0004 = 0x0004. 其实际的数据只有16个BYTE:FF00A0E314209FE5001092E5011092E5。

    第3条记录的长度为00,LOAD OFFSET为0000,TYPE= 01,校验和为FF。类型为01,说明这个是一个END OF FILE RECORD,标识文件的结尾。HEX结束符一般以:00000001FF结尾。

    二、BIN

    Bin文件是最纯粹的二进制机器代码, 或者说是"顺序格式"。按照assembly code顺序翻译成binary machine code,内部没有地址标记。Bin是直接的内存映象表示,二进制文件大小即为文件所包含的数据的实际大小。

    简单总结一下这2种文件格式的区别:

    1、HEX文件包含地址信息而BIN文件只包含数据本身,烧写或下载HEX文件时,一般不需要用户指定地址,因为HEX文件内部已经包含了地址信息。烧写BIN文件时则需要用户指定烧录的地址信息。
    2、HEX文件是用ASCII码来表示二进制的数值。例如8-BIT的二进制数值0x4E,用ASCII来表示就需要分别表示字符‘4’和字符‘E’,每个字符均需要一个字节,因此HEX文件至少需要2倍BIN文件的空间。

    三、Axf

    Axf文件由ARM编译器产生,除了包含bin的内容之外,还附加其他调试信息,这些调试信息加在可执行的二进制数据之前。调试时这些调试信息不会下载到RAM中,真正下载到RAM中的信息仅仅是可执行代码。因此,如果ram的大小小于axf文件的大小,程序是完全有可能在ram中调试的,只要axf除去调试信息后文件大小小于ram的大小即可。

    调试信息有以下功用:

    1、 可将源代码包括注释夹在反汇编代码中,这样我们可随时切换到源代码中进行调试。

    2、 我们还可以对程序中的函数调用情况进行跟踪(通过Watch & Call Stack Window查看)。

    3、对变量进行跟踪(利用Watch & Call Stack Window)。

    调试信息虽然有用,但程序功能实现后,在目标文件和库中减少调试信息却是非常有益的。减少调试信息可减少目标文件和库大小、加快链接速度、减小最终镜象代码。以下几种方法可用来减少每个源文件产生的调试信息:

    1、避免在头文件中条件性使用#define,链接器不能移除共用的调试部分,除非这些部分是完全一样的。

    2、更改C/C++源文件,使#included包含的所有头文件有相同顺序。

    3、尽量使用数量较多的小头文件而不是较大的单一头文件,这有利于链接器获取更多的通用块。

    4、程序中最好只包含必须用到的头文件。避免重复包含头文件,可使用编译器选项--remarks来产生警告信息;

    5、使用编译命令行选项--no_debug_macros,从调试表中丢弃预处理宏定义。

    四、ELF

    ELFExecutableand linking format)文件是x86 Linux系统下的一种常用目标文件(objectfile)格式,有三种主要类型:
    (1)
    适于连接的可重定位文件(relocatablefile),可与其它目标文件一起创建可执行文件和共享目标文件。

    (2)适于执行的可执行文件(executable file),用于提供程序的进程映像,加载到内存执行。

    (3)共享目标文件(shared object file),连接器可将它与其它可重定位文件和共享目标文件连接成其它的目标文件,动态连接器又可将它与可执行文件和其它共享目标文件结合起来创建一个进程映像。 

    ELF文件格式比较复杂。

    小结:可由elf文件转化为hexbin两种文件,hex也可以直接转换为bin文件,但是bin要转化为hex文件必须要给定一个基地址。而hexbin不能转化为elf文件,因为elf的信息量要大。Axf文件可以转化为bin文件,KEIL下可用以下命令fromelf -nodebug xx.axf -bin xx.bin即可。



    展开全文
  • hex文件解析实现代码

    千次阅读 2018-07-05 14:09:23
    Hex文件格式介绍(介绍部分转载地址:http://www.forwhat.cn/post-240.html)Hex文件是可以烧录到MCU中,被MCU执行的...Hex文件可以按照如下的方式进行拆分来分析其中的内容:例如 “:1000080080318B1E0828092820280...

    Hex文件格式介绍(介绍部分转载地址:http://www.forwhat.cn/post-240.html

    Hex文件是可以烧录到MCU中,被MCU执行的一种文件格式。如果用记事本打开可发现,整个文件以行为单位,每行以冒号开头,内容全部为16进制码(以ASCII码形式显示)。Hex文件可以按照如下的方式进行拆分来分析其中的内容:

    例如 “:1000080080318B1E0828092820280B1D0C280D2854”可以被看作“0x10 0x00 0x08 0x00 0x80 0x31 0x8B 0x1E 0x08 0x28 0x09 0x28 0x20 0x28 0x0B 0x1D 0x0C 0x28 0x0D 0x28 0x54”

    第一个字节 0x10表示本行数据的长度;

    第二、三字节 0x00 0x08表示本行数据的起始地址;

    第四字节 0x00表示数据类型,数据类型有:0x00、0x01、0x02、0x03、0x04、0x05。

    '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:开始线性地址记录

    然后是数据,最后一个字节 0x54为校验和。

    校验和的算法为:计算0x54前所有16进制码的累加和(不计进位),检验和 = 0x100 - 累加和

    在上面的后2种记录,都是用来提供地址信息的。每次碰到这2个记录的时候,都可以根据记录计算出一个“基”地址。对于后面的数据记录,计算地址的时候,都是以这些“基”地址为基础的。

    HEX文件都是由记录(RECORD)组成的。在HEX文件里面,每一行代表一个记录。记录的基本格式为:

    Record mark ‘:’

    Length

    Load offset

    Record type

    INFO or DATA

    CHKSUM

    1 byte

    1 byte

    2 bytes

    1 byte

    n bytes

    1 byte

    看个例子:

    :020000040008F2

    :10000400FF00A0E314209FE5001092E5011092E5A3

    :00000001FF      

    对上面的HEX文件进行分析:

    第1条记录的长度为02,LOAD OFFSET为0000,RECTYPE为04,说明该记录为扩展段地址记录。数据为0008,校验和为F2。从这个记录的长度和数据,我们可以计算出一个基地址,这个地址为(0x0008 << 16)。后面的数据记录都以这个地址为基地址。

    第2条记录的长度为10(16),LOAD OFFSET为0004,RECTYPE为00,说明该记录为数据记录。数据为FF00A0E314209FE5001092E5011092E5,共16个BYTE。这个记录的校验和为A3。此时的基地址为0X80000,加上OFFSET,这个记录里的16BYTE的数据的起始地址就是0x80000 + 0x0004 = 0x80004.

    第3条记录的长度为00,LOAD OFFSET为0000,TYPE = 01,校验和为FF。说明这个是一个END OF FILE RECORD,标识文件的结尾。

    在上面这个例子里,实际的数据只有16个BYTE:FF00A0E314209FE5001092E5011092E5,其起始地址为0x0004.

    以下是我的代码实现:

    头文件:

    #ifndef CHEX_H
    #define CHEX_H
    
    #include <QFile>
    
    const quint8 MIN_HEX_LINE_COUNT_LENGHT = 12;
    
    typedef enum __tagHexErrorCode
    {
        HEX_NO_ERROR = 0,
        HEX_FORMAT_ERROR,
        HEX_VERIFY_ERROR,
        HEX_LENGHT_ERROR,
        HEX_USERPAPR_EEROR,
    }EHexErrorCode;
    
    typedef enum __tagHexType
    {
        RECORD_DATA = 0,
        RECORD_END_OF_FILE,
        RECORD_EXTENDED_SEGMENT_ADDRESS,
        RECORD_START_SEGMENT_ADDRESS,
        RECORD_EXTENDED_LINEAR_ADDRESS,
        RECORD_START_LINEAR_ADDRESS,
        RECORD_HEX_MAX,
    }emHexType;
    
    typedef struct __tagHexLineData
    {
        emHexType   type;
        quint8      count;
        quint32     address;
        quint8      data[80];
        quint8      checksum;
        quint8      datalen;
    }stHexLineData;
    
    class CHex
    {
    public:
        CHex();
        EHexErrorCode getHexLineData(QByteArray bydata,stHexLineData *p);
    private:
        char ConvertHexChar(char ch);
    };
    
    #endif // CHEX_H

    源文件:

    #include "chex.h"
    
    const QString HexTypeTable[6] =
    {
        "00","01","02","03","04","05",
    };
    
    CHex::CHex()
    {
    
    }
    
    char CHex::ConvertHexChar(char ch)
    {
        if((ch >= '0') && (ch <= '9'))
            return (ch-0x30);
        else if((ch >= 'A') && (ch <= 'F'))
            return ((ch-'A')+10);
        else if((ch >= 'a') && (ch <= 'f'))
            return ((ch-'a')+10);
        else return (-1);
    }
    
    EHexErrorCode CHex::getHexLineData(QByteArray bydata,stHexLineData *p)
    {
        quint8 i = 0;
        quint8 cs_temp = 0;
        QString str(bydata);
        char *pcdata = bydata.data();
        quint32 linelen = str.size();
        if((linelen < MIN_HEX_LINE_COUNT_LENGHT)) {return HEX_LENGHT_ERROR;}
        if(*pcdata != 0x3A) {return HEX_FORMAT_ERROR;}//必须以":"号开始
        //获取Type
        QString stype = str.mid(7,2);
        for(i = 0; i < RECORD_HEX_MAX; i++)
        {
            if(stype == HexTypeTable[i])
            {
                p->type = (emHexType)i;
                break;
            }
        }
        if(i == RECORD_HEX_MAX) {qDebug("HEX_FORMAT_ERROR");return HEX_FORMAT_ERROR;}
        cs_temp += (ConvertHexChar(*(pcdata + 7)) << 4) | ConvertHexChar(*(pcdata + 8));
        //获取count
        p->count = (ConvertHexChar(*(pcdata + 1)) << 4) | ConvertHexChar(*(pcdata + 2));
        cs_temp += p->count;
        if(p->count != (((linelen - 2) / 2) - 5)) {qDebug("HEX_FORMAT_ERROR");return HEX_FORMAT_ERROR;}
        //获取address
        p->address = (ConvertHexChar(*(pcdata + 3)) << 12) | (ConvertHexChar(*(pcdata + 4)) << 8) | (ConvertHexChar(*(pcdata + 5)) << 4) | ConvertHexChar(*(pcdata + 6));
        cs_temp += (p->address >> 8) & 0xFF;
        cs_temp += p->address & 0xFF;
        //获取data
        for(i = 0; i < p->count; i++)
        {
            p->data[i] = (ConvertHexChar(*(pcdata + 2*i + 9)) << 4) | ConvertHexChar(*(pcdata + 2*i + 10));
            cs_temp += p->data[i];
        }
        p->checksum = (ConvertHexChar(*(pcdata + 2*i + 9)) << 4) | ConvertHexChar(*(pcdata + 2*i + 10));
        if(p->checksum != ((0x100 - cs_temp) & 0xFF))
        {
            qDebug("HEX_VERIFY_ERROR");
            return HEX_VERIFY_ERROR;
        }
        p->datalen = p->count;
    
        return HEX_NO_ERROR;
    }
    


    展开全文
  • HEX文件格式解析

    万次阅读 2015-01-31 12:11:32
    Intel HEX 文件是由一行行符合Intel HEX 文件格式的文本所 构 成的ASCII 文本文件。在Intel HEX 文件中,每一行包含一 个 HEX 记录 。 这 些 记录 由 对应 机器 语 言 码 和/ 或常量 数 据的...
  • Hex

    2014-01-04 16:22:02
    Hex 全称 (Intel HEX)文件是由一行行符合Intel HEX文件格式的文本所构成的ASCII文本文件。在Intel HEX文件中,每一行包含一个HEX记录。这些记录由对应机器语言码和/或常量数据的十六进制编码数字组成。Intel HEX...
  • hex文件说明

    千次阅读 2018-11-18 13:25:01
    在项目学习的时候,烧录生成的工程文件.hex给stm32单片机,需要分析hex文件的内容,并对其中某些数据进行修改。通过学习,了解了hex的格式内容。并记录之 在工程项目中是把程序下载到flash 的0x0800 0000开头的位置...
  • HEX文件格式

    2019-08-21 17:21:07
    以*.hex为后缀的文件我们称之为HEX文件。 HEX的英语原始意思是16进制。这种文件格式主要用于保 存单片机固件。 整个文件以行为单位,每行以冒号开头,内容全部为16进制码,2个ASCII码字符表示1个Hex字节 :...
  • HEX格式详解

    千次阅读 2019-05-29 17:06:03
    : (冒号)每个Intel HEX 记录 都由冒号开头 ; LL 是 数 据长度域,它 代表 记录当中数据字节 (dd) 的 数量 ; aaaa 是地址域, 它代表 ...
  • hex文件、bin文件、axf文件的区别?

    千次阅读 2020-01-14 09:27:44
    在STM32开发中,经常会碰到hex文件、bin文件与axf文件,这些都是可以烧写到板子里运行的文件。这三个文件有什么区别呢?在这之前,先来一起回顾一下C语言编译的过程: 编译的原理 在之前的C语言笔记《C程序的编译...
  • HEX文件合并

    千次阅读 2017-06-21 23:44:36
    HEX文件合并芯片一开始是空的,多个HEX文件需要多次下载,比较麻烦,效率低。若可以把多个HEX文件合并为一个。那么下载一次即可。**Intel HEX是把二进制信息转换成ASCLL文本的格式。**一、 HEX文件的格式 1、 以行为...
  • HEX文件格式文档(用于解析HEX文件)
  • 前言:很多MCU代码编译器都会生成hex文件hex文件的用途很多。有些直接把它放进U盘,然后给MCU自举升级,在MCU读取hex文件的时候需要将hex里的数据转换之后才能写到自身的flash里,给自身升级。当然,也可以先把hex...
  • out文件转hex文件方法

    2018-03-16 16:09:02
    .OUT文件转换为.HEX文件方法 1. 工具 TI公司提供的hex2000软件 2. 步骤 举例说明将 Powervotex305KTL_MasterV1.0.2.out 转换成Powervortex305KTL_Master_ V1.0.2.hex文件 2.1复制出hex2000,并与xxx.out文件放到同一...
  • hex文件格式总结

    千次阅读 2020-01-06 18:53:13
    hex文件格式总结 本文会结合具体实践过程中遇到的问题,对hex文件做一个新的认识。 什么是hex文件? hex是用于文件格式是intel规定的标准,总体来说,hex是文本文件,经常在微控制器的固件开发中看到hex的身影,例如...
  • Hex文件转Bin文件

    万次阅读 2016-09-29 00:35:52
    hex文件的内容转成按地址顺序(从低到高)排列的二进制数据(bin文件),对整个转换过程进行分析。
  • bin文件和hex文件互转

    万次阅读 2015-10-30 11:18:51
    对于嵌入式而言,hex文件可能大家再熟悉不过了,对,我们大学时学习的51单片机编写的代码在keil上编译后就生成了hex文件。那bin文件又是什么意思呢,它又和hex文件的区别在哪?这也不是本文的重点,下面简单的描述下...
  • QT实现HEX文件操作

    2019-12-04 18:14:44
    资源中包括《HEX文件格式解析.pdf》文章,使用QT实现HEX文件生成、HEX文件解析、文件读写及文件拼接功能的工程源码,因项目开发写的工程,可以直接使用,也可作为HEX文件操作参考。
  • bin文件转换为hex文件C语言实现

    千次阅读 2015-04-19 19:25:22
    对于嵌入式而言,hex文件可能大家再熟悉不过了,对,我们大学时学习的51单片机编写的代码在keil上编译后就生成了hex文件。那bin文件又是什么意思呢,它又和hex文件的区别在哪?这也不是本文的重点,下面简单的描述下...
  • hex文件结构

    千次阅读 2010-08-31 14:31:00
    HEX文件以行为单位。每行以字符‘:’ (0x3a)开头,以回车换行符0x0d, 0x0a为结束。每行开始和结束之间的所有内容,都是以字符形式表现的。例如数据如果是 0x1A ,那么转换到HEX格式的行里面就是0x31 0x41。...
  • Intel HEX文件解析

    万次阅读 2016-04-05 17:22:50
    最近有一个需求就是为Arduino开发板做一个基于蓝牙的无线烧录程序。目前的Arduino程序都是通过USB线连接到电脑的主机上,实际的传输过程是基于USB协议的,这个过程还是比较麻烦的...每个Arduino源程序,即sketch文件
  • hex文件反编译程序

    热门讨论 2010-07-21 10:58:08
    很好用的反编译软件!可以将hex文件进行反编译。
  • hex文件格式学习记录

    千次阅读 2018-12-25 11:57:03
    .hex文件.hex文件是什么.hex文件的数据结构 .hex文件是什么 它是由一行行符合Intel HEX 文件格式的文本所构成的ASCII 文本文件。每一行包含一 个 HEX 记录 ,由对应机器语言码和/或常量数据的十六进制编码数字组成。...
  • Hex文件解读

    千次阅读 2016-01-20 13:49:10
    在实际工作中会遇到.bin/.par/.hex类型的文件。并不是说如何使用,只是对于文件本身进行解读而已。 前面两种总体来说就是简单的...今天主要讲将对于.hex文件的理解,其实网上到处都是说的,有的说的简单,有的说的复杂
  • HEX文件合并工具

    2018-06-22 23:18:10
    博文 基于PyQt5的HEX文件合并工具 链接 https://blog.csdn.net/yy123xiang/article/details/80779583
  • hex文件数据修改程序

    热门讨论 2008-10-30 16:25:13
    一个好工具,用于hex文件数据修改.试试看.
  • HEX文件和BIN文件是我们经常碰到的2种文件格式。下面简单介绍一下这2种文件格式的区别: 1 -HEX文件是包括地址信息的,而BIN文件格式只包括了数据本身。在烧写或下载HEX文件的时候,一般都不需要用户指定地址,因为...
  • 把BootLoader hex文件和app hex文件合并为一个hex文件,烧录到嵌入式系统里面,亲自测试好用
  • intel hex文件格式浅析

    千次阅读 2012-06-17 02:10:42
    intel hex文件格式浅析  最近学习EZ-USB FX2LP CY7C68013A固件和上位机程序的开发,通过Keil uVision2开发的固件烧写程序有两种,一种为hex文件格式,可以烧写到USB芯片内部RAM中;另一种为iic文件,可以烧写到CY...
  • CCS6创建hex文件

    2017-03-02 20:54:15
    本文文档教你如何生成可以用c2prog下载的hex文件有图片有文字

空空如也

1 2 3 4 5 ... 20
收藏数 224,570
精华内容 89,828
关键字:

hex