[ บทความ : แปลงไฟล์ .HEX ให้เป็นไฟล์ฐานสอง ] |
รูปแบบของไฟล์ฐานสิบหก Intel HEX (แบบ 8 บิต)
:NNAAARRHHHHHH HHHCC
สัญลักษณ์ ความหมาย : เป็นตัวบอกให้เรารู้ว่าเป็นจุดเริ่มของข้อมูลในแต่ละบรรทัด NN เป็นตัวเลขฐานสิบหกจำนวน 2 หลัก ที่บอกว่า ในบรรทัดนั้นมีข้อมูลอยู่กี่ตัว AAAA เป็นเลขฐานสิบหกที่บอกว่า ข้อมูลไบต์แรกของบรรทัดนั้น อยู่ ณ ตำแหน่งใดในหน่วยความจำ RR เป็นตัวบอกประเภทของข้อมูล, 00 - บรรทัดข้อมูล, 01 - บรรทัดสุดท้าย CC เป็น Check Sum หาได้จาก
Sum = จำนวนไบต์+ ไบต์สูงของค่าแอดเดรส + ไบต์ต่ำของค่าแอดเดรส + ค่าชนิดของข้อมูล + ผลรวมของข้อมูล
CC = ค่า 2's complement ของ sum = complement(sum)+1ตัวอย่างโปรแกรม Z80
ORG 8000h main LD A,5 XOR A HALT ENDเมื่อเราทำการคอมไพล์แล้วก็จะได้ไฟล์ LST ออกมาดังนี้
8000 ORG 8000h 8000 main 8000 3e 05 LD A,5 8002 af XOR A 8003 76 HALT 8004 END
และได้ไฟล์ฐานสิบหก (.HEX) เป็นหน้าตาดังนี้ครับ
:048000003E05AF7614 :008004017Bบรรทัดแรก : 04 บอกว่า บรรทัดนั้นมี 4 ไบต์ , เริ่มต้นที่หน่วยความจำตำแหน่งที่ 8000h เป็นบรรทัดข้อมูล (00) ข้อมูลคือ 3E05AF76 ส่วน CC คือ 14 วิธีการคำนวณ เป็นดังนี้ครับ
sum = 4h+80h+00h+00h+3Eh+05h+AFh+76h = ECh (ผลบวกคิดเฉพาะ 8 บิต ส่วนที่เกินตัดทิ้ง) ECh = 11101100b, Complement ของ ECh = 00010011b บวกอีก 1 = 00010100b = 14h <--เป็นค่า check sumบรรทัดที่สอง : 00 บอกว่า บรรทัดนี้ไม่มีข้อมูล เริ่มตำแหน่งข้อมูลที่ 8004h มีรูปแบบข้อมูลเป็น 01 หรือ เป็นบรรทัดจบ ส่วน 7B เป็น CC ซึ่งหลักการคำนวณ คือ
sum = 00h+80h+04h+01h+00h = 85h (10000101b) 2's complement ของ 85h = (01111010b)+1 = (01111011b) = 7Bh <-- เป็นค่าของ check sumคราวนี้เรามาดูซอร์สโปรแกรมที่ทำหน้าที่แปลงไฟล์ฐานสิบหก ให้เป็นไฟล์ไบนารี กันเลยครับ ... โปรแกรม เขียนด้วย Visual C++ version 6.0 ทำงานแบบ Console (Text) Mode ซึ่งเท่ที่ลองกับคอมไพล์เลอร์บน DOS ก็ทำงานได้ปกติดี ... ซอร์สโปรแกรมเป็นดังนี้ครับ
/* * Filename : H2O.C * * Author : Supachai Budsartij (e-mail : raek@se-ed.net) * Date : Dec 10,2000 * Compiler : Visual C++ Version 6 professional edition * * Note : Convert Intel-HEX file(.HEX) to object file(.OBJ). */ #include <stdio.h> #include <string.h> #define BTRUE 1 #define BFALSE 0 char ToUpper(char x); char ToLower(char x); int IsUpper(char x); int IsLower(char x); int IsAlpha(char x); int IsDigit(char x); int IsHexDigit(char x); int Nibble2Bin(char byte); int GetHex(FILE * fp); int GetXByte(FILE *fp); int iHex2Obj(void); unsigned char TwoCPL(unsigned char x); // --- source function char ToUpper(char x) // Change x to upper case. { if (IsLower(x)) { x = 'A'+(x-'a'); } return(x); } char ToLower(char x) // Change x to lower case { if (IsUpper(x)) { x = 'a'+(x-'A'); } return(x); } int IsUpper(char x) // Recognize an upper case. { if ((x>='A')&&(x<='Z')) { return(BTRUE); } return(BFALSE); } int IsLower(char x) // Recognize a lower case. { if ((x>='a')&&(x<='z')) { return(BTRUE); } return(BFALSE); } int IsAlpha(char c) // Recognize an alpha character { char c2; c2 = ToUpper(c); if ((c2>='A')&&(c2<='Z')) { return(BTRUE); } return(BFALSE); } int IsDigit(char c) // Recognize a decimal digit { if ((c >= '0')&&(c<='9')) { return(BTRUE); } return(BFALSE); } int IsHexDigit(char x) // Recognize a hexdecimal digit { x = ToUpper(x); if ((x >= '0')&&(x<='9')||((x >= 'A')&&(x <= 'F'))) { return(BTRUE); } return(BFALSE); } int Nibble2Bin(char byte) // Convert Hex digit to binary { byte = ToUpper(byte); if ((byte >= '0')&&(byte <= '9')) { byte -= '0'; } else if ((byte >= 'A')&&(byte <= 'F')) { byte = (byte-'A')+10; } else { return(-1); } return(byte); } int GetHex(FILE *fp) { unsigned char buffer; buffer = fgetc(fp); if (!IsHexDigit(buffer)) { return(-1); } return(buffer); } int GetXByte(FILE *fp) { unsigned char byte, xbyte; if ((byte = GetHex(fp)) == -1) { return(-1); } xbyte = ((unsigned char)Nibble2Bin(byte))<<4; if ((byte = GetHex(fp)) == -1) { return(-1); } xbyte |= (unsigned char)Nibble2Bin(byte); return(xbyte); } unsigned char TwoCPL(unsigned char x) // Find 2's complement of x. { return((~x)+1); } int iHex2Obj(void) { char done; int num, max_data; unsigned char cc; unsigned int addr; char src[128], tar[128]; FILE * p_src, * p_tar; done = 0; fprintf(stdout,"HEX-Filename ?"); gets(src); fprintf(stdout,"OBJ-Filename ?"); gets(tar); p_src = fopen(src,"rt"); if (p_src == NULL) { fprintf(stdout,"ERROR : Can not open hex-filename /"%s/"/n",src); return(BFALSE); } p_tar = fopen(tar,"wb"); if (p_tar == NULL) { fprintf(stdout,"ERROR : Can not create obj-filename /"%s/"/n",tar); return(BFALSE); } fprintf(stdout,"/n Convert IntelHEX file to object file"); fprintf(stdout," [press ESC for terminated]/n"); while (!done) { /* Step 1 : Read until found ':' */ do { num = (unsigned char)fgetc(p_src); } while ((num != (int)':')&&(num != 27)&&(!feof(p_src))); if (feof(p_src)) { fprintf(stdout,"ERROR : %s is not intel-HEX file/n",src); fcloseall(); return(BFALSE); } if (num == 27) { fprintf(stdout,"/n --- User terminate ---/n"); fcloseall(); return(BFALSE); } cc = 0; /* Step 2 : Get number of data */ num = GetXByte(p_src); if (num < 0) { /* Last record or error (num is a HEX-digit) */ fprintf(stdout,"/nERROR : [num of data] is not a HEX-digit/n"); fcloseall(); return(BFALSE); } if (num == 0) { done = 1; } cc += (unsigned char)num; /* cc = num */ max_data = num; /* Step 3 : Read address */ num = GetXByte(p_src); /* Read HI Byte */ if (num < 0) { fprintf(stdout,"/nERROR : [Hi address] is not a HEX-digit/n"); fcloseall(); return(BFALSE); } cc += (unsigned char)num; /* cc = cc+Addr_HI */ addr = (unsigned int)(num << 8); /* Convert to Hi_Byte */ num = GetXByte(p_src); /* Read LO Byte */ if (num < 0) { fprintf(stdout,"/nERROR : [Lo address] is not a HEX-digit/n"); fcloseall(); return(BFALSE); } cc += (unsigned char)num; /* cc = cc+Addr_Lo */ addr |= (unsigned int)num; /* Step 4 : Read Record-Type */ num = GetXByte(p_src); if (num < 0) { fprintf(stdout,"/nERROR : [Record type] is not a HEX-digit/n"); fcloseall(); return(BFALSE); } cc += (unsigned char)num; /* cc = cc+record_type */ if (num == 1) { done = 1; } else { /* num == 0 */ /* Step 5 : Read data / write and verified. */ while (max_data > 0) { num = GetXByte(p_src); /* Read data */ if (num < 0) { fprintf(stdout,"/nERROR : [Read data] is not a HEX-digit/n"); fcloseall(); return(BFALSE); } cc += (unsigned)num; /* cc = cc+data */ /* write */ fwrite(&(unsigned char)num, sizeof(unsigned char), 1, p_tar); max_data--; addr++; } /* Finis reading */ } /* else { ... num == 0 */ /* Step 6 : CheckSum */ num = GetXByte(p_src); /* Read check sum data*/ if (num < 0) { fprintf(stdout,"/nERROR : [check sum] is not a HEX-digit/n"); fcloseall(); return(BFALSE); } cc = TwoCPL(cc); if (cc != (unsigned char)num) { fprintf(stdout,"/nERROR : [check sum]/n"); fcloseall(); return(BFALSE); } } /* while(!done) ... */ fcloseall(); fprintf(stdout,"...Convert successfull.../n/n"); return(BTRUE); } void main(void) { iHex2Obj(); }