【转】hex和bin文件格式的区别
hex和bin文件格式的區(qū)別
Intel HEX文件是記錄文本行的ASCII文本文件,在Intel HEX文件中,每一行是一個HEX記錄,由十六進(jìn)制數(shù)組成的機器碼或者數(shù)據(jù)常量。Intel HEX文件經(jīng)常被用于將程序或數(shù)據(jù)傳輸存儲到ROM、EPROM,大多數(shù)編程器和模擬器使用Intel HEX文件。
很多編譯器的支持生成HEX格式的燒錄文件,尤其是Keil c。但是編程器能夠下載的往往是BIN格式,因此HEX轉(zhuǎn)BIN是每個編程器都必須支持的功能。HEX格式文件以行為單位,每行由“:”(0x3a)開始,以回車鍵結(jié)束(0x0d,0x0a)。行內(nèi)的數(shù)據(jù)都是由兩個字符表示一個16進(jìn)制字節(jié),比如”01”就表示數(shù)0x01;”0a”,就表示0x0a。對于16位的地址,則高位在前低位在后,比如地址0x010a,在HEX格式文件中就表示為字符串”010a”。
下面為HEX文件中的一行:
:10000000FF0462FF051EFF0A93FF0572FF0A93FFBC
“:”表示一行的開始。 “:”后的第1,2個字符“10”表示本行包含的數(shù)據(jù)的長度,這里就是0x10即16個。 第3,4,5,6個字符“0000”表示數(shù)據(jù)存儲的起始地址,這里表示從0x0000地址開始存儲16個數(shù)據(jù),其中高位地址在前,低位地址在后。 第7,8個字符“00”表示數(shù)據(jù)的類型。該類型總共有以下幾種: 00 ----數(shù)據(jù)記錄 01 ----文件結(jié)束記錄 02 ----擴(kuò)展段地址記錄 04 ----擴(kuò)展線性地址記錄
這里就是0x00即為普通數(shù)據(jù)記錄。自后的32個字符就是本行包含的數(shù)據(jù),每兩個字符表示一個字節(jié)數(shù)據(jù),總共有16個字節(jié)數(shù)據(jù)跟行首的記錄的長度相一致。最后兩個字符表示校驗碼。每個HEX格式的最后一行都是固定為:
:00000001FF
以上的信息其實就足夠進(jìn)行HEX轉(zhuǎn)BIN格式的程序的編寫。首先我們只處理數(shù)據(jù)類型為0x00及0x01的情況。0x02表示對應(yīng)的存儲地址超過了64K,由于我的編程器只針對64K以下的單片機,因此在次不處理,0x04也是如此。
?
?
記錄格式
一個Intel HEX文件可以包含任意多的十六進(jìn)制記錄,每條記錄有五個域,下面是一個記錄的格式:
:llaaaatt[dd...]cc
每一組字母是獨立的一域,每一個字母是一個十六進(jìn)制數(shù)字,每一域至少由兩個十六進(jìn)制數(shù)字組成,下面是字節(jié)的描述.
:冒號 是每一條Intel HEX記錄的開始
ll 是這條記錄的長度域,他表示數(shù)據(jù)(dd)的字節(jié)數(shù)目。
aaaa 是地址域,他表示數(shù)據(jù)的起始地址<如果是數(shù)據(jù)記錄,這表示將要燒錄的這條記錄中的數(shù)據(jù)在EPROM中的偏移地址,對于不支持?jǐn)U展段地址和擴(kuò)展線性地址的,如89C51,這就是此條記錄的起始地址>
tt 這個域表示這條HEX記錄的類型,他有可能是下面這幾種類型 00 ----數(shù)據(jù)記錄 01 ----文件結(jié)束記錄 02 ----擴(kuò)展段地址記錄 04 ----擴(kuò)展線性地址記錄
dd 是數(shù)據(jù)域,表示一個字節(jié)的數(shù)據(jù),一個記錄可能有多個數(shù)據(jù)字節(jié),字節(jié)數(shù)目可以查看ll域的說明
cc 是效驗和域,表示記錄的效驗和,計算方法是將本條記錄冒號開始的所有字母對<不包括本效驗字和冒號> 所表示的十六進(jìn)制數(shù)字<一對字母表示一個十六進(jìn)制數(shù),這樣的一個十六進(jìn)制數(shù)為一個字節(jié)>都加起來然后模除256得到的余數(shù),最后求出余數(shù)的補碼,即是本效驗字節(jié)cc。
<例如: :0300000002005E9D cc=0x01+NOT((0x03+0x00+0x00+0x00+0x02+0x00+0x5E)%0x100)=0x01+0x9C=0x9D
C語言描述: UCHAR cc; cc=(UCHAR)~(0x03+0x00+0x00+0x00+0x02+0x00+0x5E); cc++; >
?
數(shù)據(jù)記錄
Intel HEX文件由若干個數(shù)據(jù)記錄組成,一個數(shù)據(jù)記錄以一個回車和一個換行結(jié)束<回車為0x0d換行為0x0a> 比如下面的一條數(shù)據(jù)記錄 :10246200464C5549442050524F46494C4500464C33 10 是此行記錄數(shù)據(jù)的字節(jié)數(shù)目 2462 ?是數(shù)據(jù)在內(nèi)存<將要燒寫的eprom地址>中的起始地址 00 ?是記錄類型00(是一個數(shù)據(jù)記錄) 464C ?到 464C 是數(shù)據(jù) 33 ? ? ?是此行記錄的效驗和
?
擴(kuò)展線性地址記錄(HEX386) 擴(kuò)展線性地址記錄也可稱為32位地址記錄/HEX386記錄,這個紀(jì)錄包含高16(16-31位)位數(shù)據(jù)地址,這種擴(kuò)展的線性記錄總是有兩個字節(jié)數(shù)據(jù),像下面這樣: :02000004FFFFFC 02 是記錄的數(shù)據(jù)字節(jié)數(shù)目 0000 是地址域,這在擴(kuò)展地址記錄中總是0000 04 是記錄類型04(擴(kuò)展地址記錄) FFFF 是高16位地址 FC 是記錄效驗和,計算方法如下: 01h + NOT(02h + 00h + 00h + 04h + FFh + FFh) 當(dāng)一個擴(kuò)展線性地址記錄被讀到后,擴(kuò)展線性地址記錄的數(shù)據(jù)區(qū)域?qū)⒈槐4?#xff0c;并應(yīng)用到后面從Intel HEX文件中讀出的記錄,這個擴(kuò)展線性記錄一直有效,直到讀到下一個擴(kuò)展線性記錄。 絕對內(nèi)存地址 = 數(shù)據(jù)記錄中的地址 + 移位后的擴(kuò)展線性地址 下面舉例說明這個過程:從數(shù)據(jù)記錄的地址域得到地址 2462,從擴(kuò)展線性地址記錄的地址域得到地址 FFFF,絕對內(nèi)存地址 FFFF2462
?
擴(kuò)展段地址記錄 (HEX86)
擴(kuò)展段地址記錄也被稱為HEX86記錄,包含 4-19位的數(shù)據(jù)地址段,這個擴(kuò)展段地址記錄總是有兩字節(jié)數(shù)據(jù),如下: :020000021200EA 02 是 記錄中的數(shù)據(jù)字節(jié)數(shù)目 0000 是地址域,在擴(kuò)展段地址記錄中,這個域總是0000 02 是記錄類型,02(擴(kuò)展段地址的標(biāo)示) 1200 是該段的地址 EA 是效驗和 計算如下: 01h + NOT(02h + 00h + 00h + 02h + 12h + 00h). 當(dāng)擴(kuò)展段地址記錄被讀后,擴(kuò)展段地址將被存儲并應(yīng)用到以后從Intel HEX文件讀出的記錄,這個段地址一直有效直到讀到下一個擴(kuò)展段地址記錄 絕對內(nèi)存地址 = 數(shù)據(jù)記錄中的地址 + 移位后的擴(kuò)展段地址 數(shù)據(jù)記錄中的地址域,移位后擴(kuò)展段地址記錄中的地址域。 下面舉例說明這個過程:從數(shù)據(jù)記錄的地址域得到地址 2 4 6 2,從擴(kuò)展段地址記錄的地址域得到地址 1 2 0 0,絕對內(nèi)存地址 0 0 0 1 4 4 6 2
?
文件結(jié)束記錄(EOF) 一個Intel HEX文件必須有一個文件結(jié)束記錄,這個記錄的類型域必須是01, 一個EOF記錄總是這樣: :00000001FF 00是記錄中數(shù)據(jù)字節(jié)的數(shù)目 0000這個地址對于EOF記錄來說無任何意義 01記錄類型是01(文件結(jié)束記錄標(biāo)示) FF是效驗和計算如下:01h + NOT(00h + 00h + 00h + 01h).
?
格式:BBAAAATTHHHH...HHHHCC
BB: Byte AAAA:數(shù)據(jù)記錄的開始地址,高位在前,地位在后。因為這個格式只支持8bits,地址被倍乘。所以,為了得到實際的PIC的地址,需要將地址除以2 TT: Type 00 數(shù)據(jù)記錄 01 記錄結(jié)束 04 擴(kuò)展地址記錄(表示32位地址的前綴,當(dāng)然這種只能在 INHX32) HHHH:一個字(Word)的數(shù)據(jù)記錄,高Byte在前,低Byte在后。TT之后,總共有 BB/2 個字 的數(shù)據(jù) CC: 一個Byte的CheckSum
因為PIC16F873A只有4K的程序空間,所以,不會有 TT=04的 Linear Address Record?
hex和bin文件格式 Hex文件,這里指的是Intel標(biāo)準(zhǔn)的十六進(jìn)制文件,也就是機器代碼的十六進(jìn)制形式,并且是用一定文件格式的ASCII碼來表示。具體格式介紹如下: Intel hex 文件常用來保存單片機或其他處理器的目標(biāo)程序代碼。它保存物理程序存儲區(qū)中的目標(biāo)代碼映象。一般的編程器都支持這種格式。?
Intel hex 文件全部由可打印的ASCII字符組成,如下例所示:
:2000000012014c75a800e4f508f509780a7a78e4f608dafcd283fcfded240af9a7050dbd81 :2000200000010ced2488ec34ff50edc283e4fcfded240af9e76d7013ed33e43c700d0dbd2a :2000400000010ced2488ec34ff50e50509e50970020508e50924a8e50834fd50aee4f50874
Intel hex 由一條或多條記錄組成,每條記錄都由一個冒號“:”打頭,其格式如下:
:CCAAAARR...ZZ
其中: CC ?本條記錄中的數(shù)據(jù)字節(jié)數(shù)
AAAA 本條記錄中的數(shù)據(jù)在存儲區(qū)中的起始地址
RR 記錄類型: 00 數(shù)據(jù)記錄 (data record) 01 結(jié)束記錄 (end record) 02 段記錄 (paragraph record) 03 轉(zhuǎn)移地址記錄 (transfer address record)
... 數(shù)據(jù)域
ZZ 數(shù)據(jù)域校驗和
校驗值:每一行的最后一個值為此行數(shù)據(jù)的校驗和。例如:
:1000000018F09FE518F09FE518F09FE518F09FE5C0 這行中的 0xC0
:1000100018F09FE5805F20B9F0FF1FE518F09FE51D 這行中的 0x1D
校驗和的算法為:計算從0x3A 以后(不包括0x3A)的所有各字節(jié)的和模256的余。即各字節(jié)二進(jìn)制算術(shù)和,不計超過256的溢出值,然后用0x100減去這個算數(shù)累加和,得出得值就是此行得校驗和。
Intel hex文件記錄中的數(shù)字都是16進(jìn)制格式,兩個16進(jìn)制數(shù)字代表一個字節(jié)。CC域是數(shù)據(jù)域中的實際字節(jié)數(shù),地址、記錄類型和校驗和域沒有計算在內(nèi)。校驗和是取記錄中從數(shù)據(jù)字節(jié)計數(shù)域(CC)到數(shù)據(jù)域(...)最后一個字節(jié)的所有字節(jié)總和的2的補碼。
而Bin文件是最純粹的二進(jìn)制機器代碼,沒有格式,或者說是"順序格式"。按assembly code順序翻譯成binary machine code。由于分析出來Hex文件中的數(shù)據(jù)域ASCII碼表示的十六進(jìn)制與二進(jìn)制一一對應(yīng),而且我公司DSP又是16位的,以一個word為最小單位,所以四個十六進(jìn)制ASCII碼代表一條機器指令單位或者地址,借于上面分析,編寫了工具代碼。大體原理是用fscanf函數(shù)在每行的數(shù)據(jù)域讀入四個ASCII碼,以短整形(short int 16bit)形式儲存,在把這個短整形變量順序fwrite到文件流中去即可。
舉一例說明: 表1
ORG 0000H LJMP START ORG 040H START: MOV SP, #5FH ;設(shè)堆棧 LOOP: NOP LJMP LOOP ;循環(huán) END ;結(jié)束 ?表2?
:03000000020040BB :0700400075815F000200431F表3
02 00 40 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 75 81 5F 00 02 00 43 ?表1為源程序,表2是匯編后得到的HEX文件,表3是由HEX文件轉(zhuǎn)換成的目標(biāo)文件,也就是最終寫入EPROM的文件,它由編程器轉(zhuǎn)換得到,也可以由 HEXBIN一類的程序轉(zhuǎn)換得到。學(xué)過手工匯編者應(yīng)當(dāng)不難找出表3與表1的一一對應(yīng)關(guān)系,值得注意的是從02 00 40后開始的一長串‘FF’,直到75 81,這是由于偽指令:ORG 040H造成的結(jié)果。
/* 使用方法 : bin2hex -b adress filename -b : 指示hex文件起始地址 address : hex文件的起始地址(FIXME:當(dāng)前版本只支持k字節(jié)邊界) filename: 待轉(zhuǎn)換的文件名 示例 : bin2hex -b 32k rom.bin */#include <stdio.h> #include <stdlib.h> #include <string.h> FILE *fp_read; /* 待讀取文件句柄 */ FILE *fp_write; /* 待寫入文件句柄 */ unsigned long start_adr; /* 轉(zhuǎn)換成Hex格式的起始地址 */ unsigned short cur_base; /* 轉(zhuǎn)換成Hex格式的當(dāng)前地址高16位 */ unsigned short cur_offset; /* 轉(zhuǎn)換成Hex格式的當(dāng)前地址低16位 */ unsigned char read_buf[16]; unsigned char write_buf[48]; void calc_start_adr (char *buf) { unsigned int len; len = strlen(buf); if ((buf[len-1] != 'k') && (buf[len-1] != 'K')) { printf ("Invalid argument.\n"); exit (-1); } buf[len-1] = 0; start_adr = atoi (buf); start_adr = start_adr * 1024; cur_base = start_adr >> 16; cur_offset = (unsigned short)start_adr; } void start_convert (void) { unsigned char cnt; unsigned char read_num; unsigned char cksum, highc, lowc; /* 設(shè)置當(dāng)前地址高16位 */ highc = cur_base >> 8; lowc = (unsigned char)cur_base; cksum = 2 + 4 + highc + lowc; cksum = 0xFF - cksum; cksum = cksum + 1; sprintf (write_buf, ":02000004%04x%02x", cur_base, cksum); write_buf[15] = 0x0D; write_buf[16] = 0x0A; fwrite (write_buf, 1, 17, fp_write); read_num = fread (read_buf, 1, 16, fp_read); while (read_num == 16) { /* 寫入讀取的16字節(jié) */ highc = cur_offset >> 8; lowc = (unsigned char)cur_offset; cksum = 0x10 + highc + lowc; for (cnt=0; cnt<16; cnt++) { cksum += read_buf[cnt]; } cksum = 0xFF - cksum; cksum = cksum + 1; sprintf ( write_buf, ":10%02x%02x00%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", highc, lowc, read_buf[0], read_buf[1], read_buf[2], read_buf[3], read_buf[4], read_buf[5], read_buf[6], read_buf[7], read_buf[8], read_buf[9], read_buf[10], read_buf[11], read_buf[12], read_buf[13], read_buf[14], read_buf[15], cksum); write_buf[43] = 0x0D; write_buf[44] = 0x0A; fwrite (write_buf, 1, 45, fp_write); /* 計算當(dāng)前地址低16位,當(dāng)越限時寫入當(dāng)前地址高16位 */ if (cur_offset == 65520) { cur_offset = 0; cur_base ++; highc = cur_base >> 8; lowc = (unsigned char)cur_base; cksum = 2 + 4 + highc + lowc; cksum = 0xFF - cksum; cksum = cksum + 1; sprintf (write_buf, ":02000004%04x%02x", cur_base, cksum); write_buf[15] = 0x0D; write_buf[16] = 0x0A; fwrite (write_buf, 1, 17, fp_write); } else { cur_offset += 16; } read_num = fread (read_buf,1,16,fp_read); } /* 寫入剩余的字節(jié) */ if (read_num) { highc = cur_offset >> 8; lowc = (unsigned char)cur_offset; cksum = read_num + highc + lowc; for (cnt=0; cnt<read_num; cnt++) { cksum += read_buf[cnt]; } cksum = 0xFF - cksum; cksum = cksum + 1; sprintf (write_buf, ":%02x%02x%02x00", read_num, highc, lowc); for (cnt=0; cnt<read_num; cnt++) { sprintf (&write_buf[9 + cnt * 2], "%02x", read_buf[cnt]); } sprintf (&write_buf[9 + cnt * 2], "%02x", cksum); write_buf[11 + read_num *轉(zhuǎn)載于:https://www.cnblogs.com/skullboyer/p/7978189.html
總結(jié)
以上是生活随笔為你收集整理的【转】hex和bin文件格式的区别的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。