아두이노 헥사파일 위치와 해석

HEX 파일

일반적으로 아두이노를 사용할 때 소스코드외에 만들어지는 파일에 대해서는 관심이 없다. 사실 관심을 가질 필요가 거의 없다. 다만, 강의자료를 만드는 입장에서 아두이노라는 임베디드 시스템에 프로그램이 들어가는 과정, 그 안에 있는 프로그램을 밖으로 꺼내는 과정등을 설명할 때 아주 잠간이지만 hex 파일이라는 것을 소개하게 된다.

이 글은 hex 파일에 대해 간략한 소개와 함께 아두이노 사용시 만들어지는 hex 파일에 대한 겉핧기식의 정보를 제공한다.

아두이노 HEX 파일 위치

아두이노 IDE 를 실행시킨 후 다음과 같은 간단한 프로그램을 만들어서 컴파일 한 후 만들어지는 hex 파일을 찾도록 한다.

윈도우10 운영체제를 사용하고 있다면 [윈도우]키를 누른다음 %temp% 를 입력하면 폴더가 검색된다. 내 컴퓨터의 경우 C:\Users\event\AppData\Local\Temp 폴더가 나온다.

폴더를 찾아 간 다음 수정한 날짜를 최신으로 설정하면 방금 만든 파일과 폴더가 나온다. 폴더를 찾아서 내부에 보면 아두이노로 만든 파일들이 나온다.

파일 중 확장자가 hex 인 것이 헥사파일이다. 즉 아두이노에 들어갈 이진파일의 내용이다.

HEX 파일 내용 (Format)

hex 파일은 소스파일을 제대로 컴파일 했을때만 만들어진다. 즉, 오류가 발생하거나 아직 컴파일하지 않은 소스파일에 대해서는 hex 파일이 만들어지지 않는다.

hex 파일은 다음과 같은 규칙을 가진다. (LINK)

  1. Start code, one character, an ASCII colon ‘:’.
  2. Byte count, two hex digits (one hex digit pair), 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.

위의 소스코드로 만들어진 hex 파일은 다음과 같다.

:100000000C9435000C945D000C945D000C945D0024
:100010000C945D000C945D000C945D000C945D00EC
:100020000C945D000C945D000C945D000C945D00DC
:100030000C945D000C945D000C945D000C945D00CC
:100040000C94C2010C945D000C9432020C940C02CE
:100050000C945D000C945D000C945D000C945D00AC
:100060000C945D000C945D00000311241FBECFEFC3
:10007000D8E0DEBFCDBF11E0A0E0B1E0EEEAF6E0EF
:1000800002C005900D92A631B107D9F721E0A6E193
:10009000B1E001C01D92AC3BB207E1F710E0C5E34F
:1000A000D0E004C02197FE010E944F03C433D10762
:1000B000C9F70E9464020C9455030C940000AF929F
:1000C000BF92CF92DF92EF92FF920F931F93CF9345
:1000D000DF936C017B018B01040F151FEB015E01A7
:1000E000AE18BF08C017D10759F06991D601ED913C
:1000F000FC910190F081E02DC6010995892B79F7DB
:10010000C501DF91CF911F910F91FF90EF90DF908C
:10011000CF90BF90AF900895FC01538D448D252F53
:1001200030E0842F90E0821B930B541710F0CF9691
:10013000089501970895FC01918D828D981761F0C3
:10014000A28DAE0FBF2FB11D5D968C91928D9F5FDA
:100150009F73928F90E008958FEF9FEF0895FC01B9
:10016000918D828D981731F0828DE80FF11D858D6C
:1001700090E008958FEF9FEF0895FC01918D228DFF
:10018000892F90E0805C9F4F821B91098F73992784
:1001900008958FE191E00E94BD0021E0892B09F4D0
:1001A00020E0822F089580E090E0892B29F00E94C2
:1001B000C90081110C9400000895FC01A48DA80FC2
:1001C000B92FB11DA35ABF4F2C91848D90E0019699
:1001D0008F739927848FA689B7892C93A089B189B9
:1001E0008C91837080648C93938D848D981306C05A
:1001F0000288F389E02D80818F7D80830895EF92BE
:10020000FF920F931F93CF93DF93EC0181E0888FD0
:100210009B8D8C8D98131AC0E889F989808185FFA0
:1002200015C09FB7F894EE89FF896083E889F98942
:1002300080818370806480839FBF81E090E0DF9144
:10024000CF911F910F91FF90EF900895F62E0B8D97
:1002500010E00F5F1F4F0F731127E02E8C8D8E1152
:100260000CC00FB607FCFACFE889F989808185FFB9
:10027000F5CFCE010E94DD00F1CFEB8DEC0FFD2F0D
:10028000F11DE35AFF4FF0829FB7F8940B8FEA8974
:10029000FB8980818062CFCFCF93DF93EC01888D83
:1002A0008823B9F0AA89BB89E889F9898C9185FDF1
:1002B00003C0808186FD0DC00FB607FCF7CF8C917F
:1002C00085FFF2CF808185FFEDCFCE010E94DD005A
:1002D000E9CFDF91CF9108958F929F92AF92BF9215
:1002E0000F931F93CF93DF93CDB7DEB7A1970FB6D0
:1002F000F894DEBF0FBECDBF19A2423008F44AE029
:100300008E010F5D1F4F842E912CB12CA12CA501C5
:1003100094010E942D03E62FB901CA01EA3044F589
:10032000E05DD801EE938D01232B242B252B79F74B
:1003300090E080E0109769F0FD0101900020E9F75E
:100340003197AF014A1B5B0BBD018FE191E00E9429
:100350005F00A1960FB6F894DEBF0FBECDBFDF9150
:10036000CF911F910F91BF90AF909F908F90089564
:10037000E95CD7CF42E050E062E171E08FE191E0CB
:100380000C945F001F920F920FB60F9211242F93BF
:100390003F938F939F93AF93BF9380911B01909155
:1003A0001C01A0911D01B0911E0130911A0123E0A2
:1003B000230F2D3758F50196A11DB11D20931A0169
:1003C00080931B0190931C01A0931D01B0931E010B
:1003D0008091160190911701A0911801B091190117
:1003E0000196A11DB11D8093160190931701A09352
:1003F0001801B0931901BF91AF919F918F913F91D7
:100400002F910F900FBE0F901F90189526E8230F85
:100410000296A11DB11DD2CF1F920F920FB60F925F
:1004200011242F933F934F935F936F937F938F93F9
:100430009F93AF93BF93EF93FF938FE191E00E945F
:10044000DD00FF91EF91BF91AF919F918F917F91CF
:100450006F915F914F913F912F910F900FBE0F9031
:100460001F9018951F920F920FB60F9211242F9381
:100470008F939F93EF93FF93E0912F01F0913001C1
:100480008081E0913501F091360182FD1BC09081A1
:10049000809138018F5F8F7320913901821741F06D
:1004A000E0913801F0E0E15EFE4F958F80933801D6
:1004B000FF91EF919F918F912F910F900FBE0F9011
:1004C0001F9018958081F4CF789484B5826084BDA4
:1004D00084B5816084BD85B5826085BD85B5816048
:1004E00085BD80916E00816080936E0010928100C6
:1004F0008091810082608093810080918100816081
:100500008093810080918000816080938000809141
:10051000B10084608093B1008091B00081608093CD
:10052000B00080917A00846080937A0080917A0094
:10053000826080937A0080917A00816080937A0053
:1005400080917A00806880937A001092C100E091D7
:100550002F01F091300182E08083E0912B01F09136
:100560002C011082E0912D01F0912E018FEC8083FF
:1005700010923701E0913301F091340186E08083DD
:10058000E0913101F0913201808180618083E091BE
:100590003101F0913201808188608083E0913101E6
:1005A000F0913201808180688083E0913101F09187
:1005B000320180818F7D808364E78FE191E00E942A
:1005C000FF000E94BA014AE06EED70E080E090E02A
:1005D0000E946C010E94BA014AE066E174E080E08A
:1005E00090E00E946C010E94BA01C0E0D0E0209728
:1005F000F1F30E94C9008823D1F30E940000F7CFD5
:10060000EFE1F1E01382128288EE93E0A0E0B0E027
:1006100084839583A683B78384E091E0918380836C
:1006200085EC90E09587848784EC90E097878687B7
:1006300080EC90E0918B808B81EC90E0938B828BAF
:1006400082EC90E0958B848B86EC90E0978B868B88
:10065000118E128E138E148E0895A1E21A2EAA1BEB
:10066000BB1BFD010DC0AA1FBB1FEE1FFF1FA21762
:10067000B307E407F50720F0A21BB30BE40BF50B5F
:10068000661F771F881F991F1A9469F760957095E8
:10069000809590959B01AC01BD01CF010895EE0FAF
:0E06A000FF1F0590F491E02D0994F894FFCF10
:1006AE0000000000FF005F008C004C01BD009B00AD
:0606BE00AF000D0A000070
:00000001FF


첫번째 줄에 대해서 해석해보면 다음과 같다. 편의상 의미가 나누어지는 곳을 띄워쓰기로 한다.

: 10 0000 00 0C943500 0C945D00 0C945D00 0C945D00 24

:    --> 시작코드
10 --> 바이트수(16진수), 16개(0x10)
0000 --> 시작주소, 4자리(16진수)
00 --> 레코드타입, 00 에서 05 중 하나, data field 의미, 00은 데이터, 01은 파일의 끝
0C943500 0C945D00 0C945D00 0C945D00 --> 데이터 16(=4x4)개 바이트(16진수 2개가 1바이트, 16진수 32개, 2진수 128개),
24 --> 체크섬, 2자리

hex 파일을 notepad++ 등의 에디터에서 열어보면 색상으로 구별지어 보여준다.

v1, v2, v3 값을 1씩 크게 만들어 다시 컴파일한 다음 이전과 새로 만들어진 hex 파일을 비교해보면 다음과 같다.

// 원래 값
char v1 = 't';
int v2 = 222;
long v3 = 1046;
// 변경된 부분
char v1 = 't';
int v2 = 222;
long v3 = 1046;

두개의 hex 파일을 비교해보면 전체 110 라인 중 3개 라인만 다르다. 비교를 위해 notepad++ 의 Compare 플러그인을 사용했으며, 그 부분은 다음과 같다.

:1005B000320180818F7D808364E78FE191E00E942A
:1005B000320180818F7D808365E78FE191E00E9429
..........................#..............-- *******(1)

:1005C000FF000E94BA014AE06EED70E080E090E02A
:1005C000FF000E94BA014AE06FED70E080E090E029
..........................#..............-- *******(2)

:1005D0000E946C010E94BA014AE066E174E080E08A
:1005D0000E946C010E94BA014AE067E174E080E089
..............................#..........-- *******(3)

# 표시한 부분이 다르다. 다른 이유는 다음과 같다.

 OLD   NEW      OLD    NEW
==============================
't' 'u' 0x74 0x75
222 223 0xDE 0xDF
1046 1047 0x416 0x417

‘t’ 의 아스키코드는 0x74 고, ‘u’ 의 아스크코드는 0x75 다. 즉 4와 5가 다르다. (1) 에서 이 부분을 확인할 수 있다. 223 을 16진수로 고치면 0xDE 이고, 224를 16진수로 고치면 0xDF 이다. E와 F가 다르가 나오는 부분이 (2)이다. 마찬가지로 1046 을 16진수로 고치면 0x416 이고 1을 더한 값이 0x417 이다. (3)에서 6과 7이 다르게 나온다.

여기까지 아두이노 코드를 PC 에서 아두이노로 넘길 때 avr-gcc 를 사용해서 만들어지는 hex 파일에 대해 간략히 살펴보았다. 이 내용은 추후에 아두이노안에 들어있는 이진 파일을 받아온 후 어셈블리코드로 재구성할 때 도움이 된다.

사실 최근들어 어셈블리코드는 일반적으로 거의 사용되지 않는다. 사용되지 않는 이유는 첫째 C 컴파일러의 성능이 좋아졌기 때문이다. 불과 몇년전만 하더라도 C로 만들어진 8051 이나 AVR 코드를 신뢰하지 못하는 개발자들이 있었다. 그래서 시간이 걸려도 직접 어셈블러로 코드를 만들곤 했다. 하지만 컴파일러의 성능이 좋아지면서 이제는 C로 만들거나 어셈블러로 개발자가 직접 최적화를 한 것이 큰 차이를 가지지 않게 되었다. 또한 MCU 들의 성능이 과거에 비해 좋아지고 있다. 한 비트의 의미가 예전같지 않게 된 것이다.

아두이노가 대표적이다. 아두이노 우노는 Atmega328 AVR 칩을 사용하고 플래시메모리가 32kB 나 된다. SRAM 2kB, EEPROM 1kB 를 가지고 있다. 2000년대 초반에 8051을 사용할 때 저정도의 메모리는 상상하기 힘든 것이었다. 한참 8051 에 빠져있을때 AT89C51 을 사용해서 기존과 다른 8051 보드를 직접 만들어 사용한 적이 있다. AT89C51 은 4kB 플래시메모리를 가지고 있었고, 그 당시 이정도면 매우 훌륭한 MCU 였다. 아두이노 메가는 Atmega2560 칩을 사용하고, 메모리는 플래시 256kB 를 가지고 있다. Atmega2560 칩은 3D 프린터의 제어기로 일반적으로 사용된다.

아두이노용, 임베디드용 C 를 정리하는 중이다.

Categories IT

Leave a Comment