perlでIntel HEXのチェックサムを再計算

Intel HEXを書き換えた時の、チェックサム再計算するスクリプトを作ってみます。
まずは変更前HEXです。

~$ cat a.hex
:100000000102030405060708090A0B0C0D0E0F1068
:100010001112131415161718191A1B1C1D1E1F2058
:100020002122232425262728292A2B2C2D2E2F3048
:100030003132333435363738393A3B3C3D3E3F4038
:100040004142434445464748494A4B4C4D4E4F5028
:100050005152535455565758595A5B5C5D5E5F6018
:100060006162636465666768696A6B6C6D6E6F7008
:080070007172737475767778E4
:00000001FF
~$ 

1行目の先頭データ01を削除してb.hexを作成します。このHEXのチェックサム値を更新します。

~$ sed '1s/\(:.\{8\}\)01/\1/' a.hex | tee b.hex
:1000000002030405060708090A0B0C0D0E0F1068
:100010001112131415161718191A1B1C1D1E1F2058
:100020002122232425262728292A2B2C2D2E2F3048
:100030003132333435363738393A3B3C3D3E3F4038
:100040004142434445464748494A4B4C4D4E4F5028
:100050005152535455565758595A5B5C5D5E5F6018
:100060006162636465666768696A6B6C6D6E6F7008
:080070007172737475767778E4
:00000001FF
~$ 

データ数、チェックサムを除いた固定データ部分だけ抽出します。

~$ perl -ne 's/[\r\n]//;/:..(.*)..$/;print"$1\n"' b.hex
00000002030405060708090A0B0C0D0E0F10
0010001112131415161718191A1B1C1D1E1F20
0020002122232425262728292A2B2C2D2E2F30
0030003132333435363738393A3B3C3D3E3F40
0040004142434445464748494A4B4C4D4E4F50
0050005152535455565758595A5B5C5D5E5F60
0060006162636465666768696A6B6C6D6E6F70
0070007172737475767778
000001
~$ 

スクリプトが長くなりそうなので、t.plというファイルにまとめていきます。
次は固定データ部分を2Byte毎に配列に格納します。

~$ cat t.pl
s/[\r\n]//;
/:..(.*)..$/;
$fixed = $1;
@tmp = $fixed =~ /.{2}/g;
print "@tmp\n";

~$ perl -n t.pl b.hex
00 00 00 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10
00 10 00 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20
00 20 00 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30
00 30 00 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40
00 40 00 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50
00 50 00 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60
00 60 00 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70
00 70 00 71 72 73 74 75 76 77 78
00 00 01
~$ 

配列はチェックサムが計算しやすいように10進数にしておきます。

~$ cat t.pl
s/[\r\n]//;
/:..(.*)..$/;
$fixed = $1;
@arr = map { hex $_ } @tmp = $fixed =~ /.{2}/g;
print "@arr\n";

~$ perl -n t.pl b.hex
0 0 0 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
0 16 0 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
0 32 0 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
0 48 0 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
0 64 0 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
0 80 0 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
0 96 0 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
0 112 0 113 114 115 116 117 118 119 120
0 0 1
~$ 

データ数と、チェックサムを算出します。

~$ cat t.pl
s/[\r\n]//;
/:..(.*)..$/;
$fixed = $1;
@arr = map { hex $_ } @tmp = $fixed =~ /.{2}/g;
$num = $#arr - 2;
$sum = ~ ($num + eval join "+",@arr)+1 & 0xff;
print "$num $sum\n";

~$ perl -n t.pl b.hex
15 106
16 88
16 72
16 56
16 40
16 24
16 8
8 228
0 255
~$ 

できあがったスクリプトです。ファイル名をそれっぽくしました。

~$ cat -n update-hex.pl 
     1	s/[\r\n]//;
     2	/:..(.*)..$/;
     3	$fixed = $1;
     4	@arr = map { hex $_ } @tmp = $fixed =~ /.{2}/g;
     5	$num = $#arr - 2;
     6	$sum = ~ ($num + eval join "+",@arr)+1 & 0xff;
     7	printf ":%02X$fixed%02X\n",$num,$sum;
~$ 

使ってみます。

~$ perl -n update-hex.pl b.hex | tee b-new.hex
:0F00000002030405060708090A0B0C0D0E0F106A
:100010001112131415161718191A1B1C1D1E1F2058
:100020002122232425262728292A2B2C2D2E2F3048
:100030003132333435363738393A3B3C3D3E3F4038
:100040004142434445464748494A4B4C4D4E4F5028
:100050005152535455565758595A5B5C5D5E5F6018
:100060006162636465666768696A6B6C6D6E6F7008
:080070007172737475767778E4
:00000001FF

生成されたHEXを確認してみましょう。

~$ srec_info b-new.hex -intel
Format: Intel Hexadecimal (MCS-86)
Data:   0000 - 000E
        0010 - 0077
~$ 

問題なさそうです。

コメント

タイトルとURLをコピーしました