PER 编码规则
一 名词解释
ASN.1:抽象标记语言
PER:压缩编码规则(Packed Encoding Rules),ASN.1 编码规则之一
Bit:比特位
MIN:ASN.1 中规定为无穷小
MAX:ASN.1 中规定为无穷大
ub:约束上限
lb:约束下限
根列表:约束中第一个扩展标记前的初始约束
扩展列:扩展标记后面的扩展约束值
二 PER 编码规则
PER 编码有两个变体:对齐和非对齐方式,两者的编码过程基本相同,对齐方式下,如果前面的
信息经编码后得到的二进制比特流不是一个八位组的倍数,而后一个信息又是以八位组为单位进行编码
的,那就需要在在前面生成的比特流后面填充 0,使得长度变为八位组的倍数,所以一般补 0 的位数是
0-7bit;而非对齐方式则没有这种要求,所有信息按规则进行编码后得到的比特流数据,按顺序首尾连接,
中间不需要任何填充,编码结束后,最终得到的编码数据如果不是 8 的倍数,则需在后填 0 补全。
不对齐方式则编码更为紧凑,但是在编解码时需要花费更多的处理时间。
2.1 ASN.1 中的符号及定义
::= 定义为
| 或
-- 后面是注释(行)
{} 清单的开始和结束
[] 标签的开始和结束
() 子类型的开始和结束
.. 范围
... 扩展列
在 ASN.1 中,符号的定义没有先后次序:只要能够找到该符号的定义即可,ASN.1 的定义有类型
定义,值定义,信息对象类和信息对象定义,模块定义等。
类型定义:<新类型的名字>::= <类型描述>
其中:
新类型的名字是以大写字母开头,例如:
Msg ::= INTEGER
--定义 Msg 为 INTEGER 类型
--相当于 C 语言中 typedef INTEGER Msg,
值定义:<新的值的名字><该值的类型> ::= <值描述>
其中:
<新的值的名字>是以小写字母开头的标识符;
<该值的类型>可以是一个类型的名字,也可以是类型描述;
<值描述>是基于整数、字符串、标识符的组合。
例如:
msg Msg ::= 45 或者 msg Msg ::= {8,12,40}
--定义变量 msg 为 Msg 类型,其取值为 45 或者 8,12,40
模块定义:<模块名字> DEFINITIONS <缺省 Tag> ::= BEGIN
EXPORTS <导出描述>
IMPORTS <导入描述>
--声明类型,其他模块可以调用该类型
--声明类型,调用其他模块声明的类型
<模块体描述>
END
其中,模块名字是以大写字母开头,例如:
MsgTest DEFINITIONS AUTOMATIC TAGS ::= BEGIN
Msg1 ::= INTEGER(3..MAX),
Msg2 ::= ENUMERATED {red(3), blue, yellow, purple},
Msg3 ::= SEQUENCE{
time INTEGER,
pading INTEGER(1..3)
OPTIONAL,
ret BOOLEAN
}
END
AUTOMATIC TAGS 是指缺省 Tag,说明不关注模块的 Tag。
2.2 编码规则
分组编码规则包括三个部分: preamble (前缀)、 length (长度)、 contents (内容)。
其编码格式如表 1 所示:
表 1 PER 编码组成
Preamble
length
Content
(1)preamble :
它一般只出现在 ENUMERATED 、 SEQUENCE 、 SET、 CHOICE 四种数据结构的编码中。
用来记录结构中有无扩展项(extension)、选择项(optional)或缺省项(default)。
(2)length :
对 STRING、 SEQUENCE OF 、 SET OF 等数据类型进行编码时,需对其长度按对齐方式进
行编码。
(3)contents :
若数据是基本结构类型,如: BOOLEAN 、 INTERGER、 REAL、 BITSTRING 等,即可直
接进行编码; 若数据是复合结构类型, 如 SEQUENCE 、 SET、 CHOICE、 SEQUENCE OF 等,
则属嵌套编码,此时 contents 中也包含有 preamble 、 length 、 contents 三个部分(注:在以下举
例中,为对齐需要插入 0 的地方,以 (pad) 表示)。
2.3 ASN 基本类型
ASN 基本类型如下图 1 所示:
图 1 基本类型
2.4 PER 可见子类型约束
为了最大限度的压缩编码,PER 需要依赖 ASN.1 描述中的子类型约束。约束增加的越具体,PER
越能得到更优化的编码(压缩越多)。而且 PER 会使用到的约束都是经常使用的约束,这样也使得 PER
编译器容易实现。此外,这些约束都是编译器在编译过程中“静态”使用的,不会增加实际编解码过程
处理时间。
这类约束被称为 PER 可见约束(PER-Visible Constraints),如图 2 所示:
图 2 PER 可视约束
三 整型编码(INTEGER)
整型的 PER 编码主要分为全约束、半约束、无约束三种方式进行编码,其中全约束和半约束是按
照非负二进制整数的编码方式编码,无约束是按照 2 的补码二进制整数的编码方式编码;在 2 的补码二
进制整数的编码中,由于存在负数的编码表示,为保证编码的唯一性,因此在 ASN.1 中规定,整个数的
编码应具有八位整数倍的字段宽度,且满足该字段引导的 9 个位不全为 1,也不全为 0;(主要表达为内
容八位组编码的最高位为符号位,如果正数的内容八位组最高位(bit8)为 1 时,应该在前端填充一个
00 字节的八位组,如果负数的最高位(bit8)是 0 时,应在前端填充一个 FF 字节的八位组。)
3.1 无约束整型编码
无约束整型编码主要由取值的编码和长度 L 的编码两部分组成,其中无约束主要表现有两种:
例如:
Msg ::= INTEGER 或 Msg ::= INTEGER(MIN.. ub)
--定义 Msg 为无约束整型,或者下限为负无穷的整型
编码方式:进行编码时,一般取下限为 0,如果取值为 n,则待编码数值为 d = n - 0,d 以最少的八位组
数目进行编码,例如:
m1 INTEGER(MIN..130) ::= 127
m2 INTEGER ::= 128
m3 INTEGER ::= 129
m4 INTEGER ::= -127
m5 INTEGER ::= -128
m6 INTEGER ::= -129
编码为:
m1:01 7F
--01 为长度域,表明后面有一个八位组表示内容,7F 为 127 编码
m2:02 00 80
--02 表示后面有两个八位组表示内容,00 80 表示正数 128
m3:02 00 81 [比特流为:00000010 00000000 10000001]
--02 表示后面有两个八位组表示内容,00 81 表示正数 129
m4:01 81
--01 表示后面有一个八位组表示内容,81 表示负数-127
m5:01 80
--01 表示后面有一个八位组表示内容,80 表示负数-128
m6:02 FF 7F
--02 表示后面有两个八位组表示内容,FF 7F 表示负数-129
[比特流为:00000010 00000000 10000000]
[比特流为:00000010 11111111 01111111]
[比特流为:00000001 10000001]
[比特流为:00000001 01111111]
[比特流为:00000001 10000000]
3.2 全约束整型编码
全约束整型编码,是指定义的整型具有明确的上下限值 lb 和 ub,范围值 d = ub - lb + 1,若取值
为 n,此时,编码有对齐和非对齐两种变体,在非对齐方式下编码,不需要考虑比特位对齐问题,不需
要对长度 L 进行编码,只需根据所需要的 d2
log 个比特位对 n - lb 进行编码。在对齐方式下编码,则需要
考虑范围值 d 的大小:
d ≤ 255,编码方式与非对齐编码相同;
d = 256,占用一个八位组对 n - lb 进行编码,不需要编码长度 L
257≤d ≤65536,占用两个八位组对 n - lb 进行编码,不需要编码长度 L
d ≥65537,占用
log 个八位组对 n-lb 进行编码,需要对长度 L 进行编码
d256
若约束中出现扩展标记(...),则前缀中出现一个扩展位添加到编码中,若 n 在根列表中,则扩展
位置为 0,其后编码按照无扩展标记情况对数据进行编码;若 n 在扩展列中,则扩展位置为 1,其后编码
按照无约束情况进行编码。例如:
i1 INTEGER(1..10) ::= 9
i2 INTEGER(2..257) ::= 130
i3 INTEGER(0..32000) ::= 31000
i4 INTEGER(1..65538) ::= 65538
i5 INTEGER(1..10,...,15..20) ::= 9
i6 INTEGER(1..10,...,15..20) ::= 19
i7 INTEGER(1..65538,...,65550..66000) ::= 65536
[比特流为:1 00000000 00000001]
[比特流为:00000011 00000001 00000000 00000001]
编码为:
i1:80 [比特流为:1000 0000]
--范围值 d=10,应用 4 个 bit 来表示 n-bl=8,其后将 bit 流补全为 8 的整数倍,即 80
i2:80 [比特流为:1000 0000]
--范围值 d=256,应用 8 个 bit 来表示 n-bl=128
i3:79 18
[比特流为:01111001 00011000]
--范围值 d=32001,应用 2 个八位组(非对齐方式是 15 个 bit)来表示 n-bl=31000
i4:
非对齐方式:80 00 80
对齐方式:03 01 00 01
--范围值 d=65538,非对齐方式下应用 17 个 bit 来表示 n-bl=65538
--对齐方式下,03 表示长度 L,有三个八位组表示内容
i5:40
--存在扩展位,n 在根列表内,扩展位置为 0,其后按无扩展标记进行编码
i6:80 89 80
--存在扩展位,n 在扩展列表内,扩展位置为 1,其后按无约束进行编码,补 0 成 8 的倍数
i7:
非对齐方式:3F FF C0
对齐方式: 01 00 FF FF [比特流为:0 00000010(pad) 11111111 11111111]
--范围值 d=65538,存在扩展标志,取值在根列表中,扩展位置为 0
--非对齐方式下,i5 共使用 d2
--011111111 11111111,前面有一个 0 扩展位,故编码为 3F FF C0
--对齐方式下,范围值 d>65536,故编码以 8 位组对齐且存在长度编码和 0 扩展标志,
--根据对齐原则,在 pad 处填充 7bits 的 0 以保证内容八位组对齐,故编码为 0100FFFF
[比特流为:0 011111111 11111111(pad)]
log
=16.000044027≈17bits,因此 n-lb 表示为
[比特流为:0 1000 0000]
[比特流为:1 00000001 00010011]
3.3 半约束整型编码
半约束整型编码是指具有明确的下限 lb,其上限为 MAX,可使用此方式进行编码,若取值为 n,
则范围值 d=n-lb。此类型编码由长度 L 和编码内容组成,其中编码内容 n-lb 应由
log 个八位组来表示,
d256
八位组的个数即为 L 的值。例如:
x1 INTEGER(0..MAX) ::= 128
x2 INTEGER(10..MAX) ::= 65547
编码为:
x1:01 80
[比特流为:00000001 10000000]
--01 表示后面有 1 个八位组内容,80 表示 128 的编码
x2:03 01 00 01
--03 表示后面有 3 个八位组内容,01 00 01 表示(65547-10)的编码
[比特流为:00000011 00000001 00000000 00000001]
3.4 非负小整个数
如果 0≤n≤63,前同步码为 0,后面六位为 n 的编码。
编码形式为: 0 nnnnnn
如果 n≥64,前同步码位 1,L 为长度域, n 作为一个半约束的整数来编码( bmin 看作 0)。
编码形式为: 1 ··L·· n
例: 5 L: 0 000101 C:(5 items of content)
60 L: 0 111100 C:(60 items of content)
254 L: 1 P00000001 11111110 C:(254 items of content)
99000 L: 1 P11000100 C:(64K items of content)
L:11000010 C:(32K items of content)
L:10000010 10111000 C:(696 items of content)
四 长度编码
长度域 L 可以表示比特串长度,也可以表示八位组长度;
如果 L 为一个位图的长度,则对 L-1 按照非负小整个数进行编码。
在对齐方式下:
当 Lmax ≤65535,L 编码按照对齐受限整数进行编码;
当 Lmax >65535,时:
长度 L≤127,L 使用一个八位组编码,bit8 置为 0;
长度 128≤L≤16383,L 以两个八位组编码,最高两位为 10;
长度 L>16383,L 进行分片编码,(具体看 X.680 文档)
在非对齐方式下:
当 Lmax ≤65535,L-Lmin 编码占
L
max L
长度 L≤127,L 使用 8bits 编码,bit8 置为 0;
长度 128≤L≤16383,L 以 16bits 编码,最高两位为 10;
≥65536 时,
bit 位;
(
L
max
)1
log
2
L
min
min