ISO 8583 Parser
免费 · 速查 · 约 9 分钟 · 最后更新 2026-08-13
编码 · iso 8583

ASCII、压缩 BCD、EBCDIC:同一个值的三种字节写法

最普通的 MTI 0200,走 ASCII 链路是 30 32 30 30,压缩 BCD 是 02 00,EBCDIC 是 F0 F2 F0 F0——同样四个字符,占 4、2、4 字节。长度一变,报文里每一个字段的边界都跟着挪。下面是三种编码并排、压缩 BCD 的装法,以及完整的 EBCDIC(CP500)↔ ASCII 对照表

同一个值,三种编码

取三个几乎每笔授权报文都有的值,把三种走法各写一遍。重点不在字节的值,在字节数

MTI 0200——4 位数字:

表示线上字节长度
ASCII30 32 30 304 字节
压缩 BCD02 002 字节
EBCDIC(CP500)F0 F2 F0 F04 字节

DE4 金额 000000005000——n 12,按最小货币单位即 50.00:

表示线上字节长度
ASCII30 30 30 30 30 30 30 30 35 30 30 3012 字节
压缩 BCD00 00 00 00 50 006 字节
EBCDIC(CP500)F0 F0 F0 F0 F0 F0 F0 F0 F5 F0 F0 F012 字节

DE2 卡号 5413330089010001——16 位:

表示线上字节长度
ASCII35 34 31 33 33 33 30 30 38 39 30 31 30 30 30 3116 字节
压缩 BCD54 13 33 00 89 01 00 018 字节
EBCDIC(CP500)F5 F4 F1 F3 F3 F3 F0 F0 F8 F9 F0 F1 F0 F0 F0 F116 字节

长度差就是全部的故事。按 ASCII 配置的解析器碰上 BCD 报文,会把两个字段的内容吃进一个字段;按 BCD 配置的碰上 ASCII,读到一半就停——不管哪个方向,从第一个错位字段起,后面所有边界全错。所以在解析失败的排查顺序里,编码排在第二步,紧跟在报文头之后。想亲眼看这几串字节被解出来,把它们贴进十六进制查看器:同一行字节,ASCII 和 EBCDIC 两列并排给你。

上面三张表还顺带说明了一件事:字段格式 n 12 只说这个域装 12 位数字,不说这 12 位占 12 字节还是 6 字节。格式记号和编码是两份互相独立的约定,格式记号那篇只管前一份;后一份按链路定,写在接口规范里。

压缩 BCD:一个字节装两位数字

压缩 BCD(binary-coded decimal)把一位十进制数字装进 4 个比特(一个半字节),一个字节正好装两位,高半字节在前:0200 变成 02 00。BCD 字段的十六进制 dump 读起来就是数字本身——这既是它讨喜的地方,也是认出它最快的办法。

省一半,就是 BCD 存在的理由:n 12 的金额从 12 字节缩到 6 字节,16 位卡号从 16 字节缩到 8 字节。放到百万级的报文和批量记录上,这笔账在这些接口定型的年代很值得算,省钱的约束消失之后惯例留了下来。装包拆包可以在进制与 BCD 转换器里交互着做,字节数一并给出。

半字节这个装法带出两条性质:

符号半字节:部分链路上,金额类 BCD 域会在数字之外带一个符号半字节(大机 packed-decimal 的路数)。哪个半字节值代表什么,各家实现不一样——以对端规范为准,别套任何通用表。

EBCDIC(CP500)↔ ASCII 对照表

EBCDIC 是一族代码页,不是一种编码。CP037、CP500、CP1047 加上几十个国家变体,在数字、字母和大部分标点上一致,但在少数几个位置上各说各话——方括号、感叹号、竖线这几个符号在不同代码页里坐在不同的码位上。下面的表是 CP500(International),和十六进制查看器解码用的是同一张;如果对端声明的是别的代码页,标了「随代码页变」的行就是要拿对方规范重核的那几行。

数字 0–9

用得最多的十行。EBCDIC 数字就是 F 打头、低半字节放数字——所以 EBCDIC 文件里的数字域 dump 出来是一片 F0F9,把每个字节的高半字节剥掉,剩下的正好是同一个数的压缩 BCD。

EBCDIC(CP500)字符ASCII
F0030
F1131
F2232
F3333
F4434
F5535
F6636
F7737
F8838
F9939

大写 A–Z

和 ASCII 不同,EBCDIC 的字母表不连续:分三段,C1C9(A–I)、D1D9(J–R)、E2E9(S–Z),段与段之间夹着不相干的码位。按字节值判「在 A 到 Z 之间」的代码,遇到 EBCDIC 数据必翻车。

EBCDIC(CP500)字符ASCII
C1A41
C2B42
C3C43
C4D44
C5E45
C6F46
C7G47
C8H48
C9I49
D1J4A
D2K4B
D3L4C
D4M4D
D5N4E
D6O4F
D7P50
D8Q51
D9R52
E2S53
E3T54
E4U55
E5V56
E6W57
E7X58
E8Y59
E9Z5A

小写 a–z

同样的三段式,往下错一格:81899199A2A9。注意小写字母的最高位全是 1——放在 ASCII 里全在可打印范围之外。

EBCDIC(CP500)字符ASCII
81a61
82b62
83c63
84d64
85e65
86f66
87g67
88h68
89i69
91j6A
92k6B
93l6C
94m6D
95n6E
96o6F
97p70
98q71
99r72
A2s73
A3t74
A4u75
A5v76
A6w77
A7x78
A8y79
A9z7A

常见符号

按 EBCDIC 码位排序。标「随代码页变」的行是跨代码页的经典坑:这几个字符在 CP037、CP1047 里坐在别的码位上,代码页选错时别的都好好的,就括号、竖线这几个换成了别的符号。

EBCDIC(CP500)字符ASCII备注
40空格20EBCDIC 里成片的填充是 40,不是 20
4A[5B随代码页变
4B.2E
4C<3C
4D(28
4E+2B
4F!21随代码页变
50&26
5A]5D随代码页变
5B$24
5C*2A
5D)29
5E;3B
5F^5E随代码页变
60-2D
61/2F
6B,2C
6C%25
6D_5F
6E>3E
6F?3F
79`60
7A:3A
7B#23
7C@4040 在 ASCII 是 @,在 EBCDIC 是空格
7D'27
7E=3D
7F"22
A1~7E
BB|7C随代码页变
C0{7B
D0}7D
E0\5C

控制字符和未分配的码位这里有意不列——它们本来就不该出现在报文正文里。表里没有的字节,把十六进制贴进十六进制查看器直接从 dump 里读:256 个码位它逐字节全解。

拿到一段 dump,怎么判断是哪种编码

从第 0 个字节看起。MTI 是每条报文的第一个字段,取值就那么几个,三种编码各有各的长相:

dump 开头是……读出来是结论
30 31 / 30 32 / 30 38……ASCII 数字的 0108xxASCII
01 00 / 02 00 / 08 00……两个字节,就是 MTI 本身压缩 BCD
F0 F1 / F0 F2 / F0 F8……EBCDIC 数字的 0108xxEBCDIC

开头之后,看整段 dump 的「成分」通常一眼就能定:

成分看不出来的时候——dump 太短、或者逐域混编码——三种都解一遍,留下 MTI 像样、位图的置位又和正文对得上的那种。在十六进制查看器里贴一次就能同时看 ASCII 和 EBCDIC 两列,BCD 交给进制与 BCD 转换器,三把加起来两分钟——比在接口文档里翻编码条款快得多。解析失败的排查顺序里,「三种都试」正是编码这一步的标准做法:排在报文头之后、一切字段级问题之前。

实际在哪遇到哪种

批量清算偏 EBCDIC。Mastercard IPM(T112)清算文件是最典型的一例:大机时代建的清算平台,用的自然是大机原生字符集,之后一直没变。一份「乱码」文件在 hex dump 的 EBCDIC 列里突然能读了,说明你拿的就是它——逐字段解码交给 IPM 文件解析器

联机授权链路大多是 ASCII,在乎报文长度的链路常见压缩 BCD——而且往往按域分:数字域压缩、文本域不压。你这条链路用哪种组合,是这条链路接口规范的属性,不是某家卡组织的属性——以对端规范为准,或者按上面的办法实测,通常更快。

带注释的示例报文用的是最好相处的形态——纯 ASCII 文本——就是为了让你直接贴进解析器看完整解码,不用先跟字节级编码缠斗。那一页的编码说明里也写了同一批样例换到压缩链路上会变成什么样。


👉 手上正好有一段 dump?先贴进十六进制查看器看 ASCII、EBCDIC 两列谁能读,再把能读的那份交给解析器逐字段拆开。

延伸阅读