Skip to main content

属性:pack_mode

pragma 定义了在分配期间如何打包数据结构。该属性必须插入到数据结构之上并影响整个结构的打包。

句法:

{attribute 'pack_mode' := ' <pack mode value> '}

插入位置:数据结构声明的上方

表 27. 可能的值 <pack mode value>

<打包模式值>

相关包装方式

描述

0

对齐

所有变量都分配给字节地址。没有记忆空白。

1

1 字节对齐

2

2 字节对齐

. 有
  • 字节地址处的 1 字节变量

  • 可被 2 整除的地址处的 2 字节变量。结果的最大间隙为 1 字节。

  • 可被 2 整除的地址处的 4 字节变量。结果的最大间隙为 1 字节。

  • 可被 2 整除的地址处的 8 字节变量。结果最大间隙为 1 字节。

  • 字符串始终位于字节地址。没有间隙结果。

4

4 字节对齐

. 有
  • 字节地址处的 1 字节变量

  • 可被 2 整除的地址处的 2 字节变量。结果的最大间隙为 1 字节。

  • 可被 4 整除的地址处的 4 字节变量。结果的最大间隙为 3 字节。

  • 可被 4 整除的地址处的 8 字节变量。结果的最大间隙为 3 字节。

  • 字符串始终位于字节地址。没有间隙结果。

8

8 字节对齐

. 有
  • 字节地址处的 1 字节变量

  • 可被 2 整除的地址处的 2 字节变量。结果的最大间隙为 1 字节。

  • 可被 4 整除的地址处的 4 字节变量。结果的最大间隙为 3 字节。

  • 可被 8 整除的地址处的 8 个字节变量。结果的最大间隙为 7 个字节。

  • 字符串始终位于字节地址。没有间隙结果。



提示

根据结构的不同,各个模式的内存映射可能没有差异。例如,具有以下结构的内存分布 {attribute 'pack mode' := '4'} pragma 可以对应于 {attribute 'pack mode' := '8'}。

提示

结构数组

如果将结构组合成数组,则在结构的末尾添加字节,以便对齐下一个结构。

重要

如果 兼容性布局 在符号配置中选择了选项,同时属性 'pack_mode' 在代码中使用,则可能由于无意的内存未对齐而出现问题。

示例 1

{attribute 'pack_mode' := '1'}

TYPE myStruct:
STRUCT
  Enable: BOOL;
  Counter: INT;
  MaxSize: BOOL;
  MaxSizeReached: BOOL;
  END_STRUCT
END_TYPE

数据类型变量的内存范围 myStruct 被分配“对齐”。如果其组件的存储地址 Enable 是 0x0100,例如,那么组件 Counter 跟随地址 0x0101, MaxSize 在地址 0x0103 和 MaxSizeReached 在地址 0x0104.如果是 'pack_mode':=2, Counter 会在 0x0102, MaxSize 在 0x0104 和 MaxSizeReached 在 0x0105.

示例 2

STRUCT
  Var1 : BOOL  := 16#01;
  Var2 : BYTE  := 16#11;
  Var3 : WORD  := 16#22;
  Var4 : BYTE  := 16#44;
  Var5 : DWORD := 16#88776655;
  Var6 : BYTE  := 16#99;
  Var7 : BYTE  := 16#AA;
  Var8 : DWORD := 16#AA;
END_TYPE

pack_mode = 8

pack_mode = 0

pack_mode = 1

pack_mode = 2

pack_mode = 4

多变的

价值

多变的

价值

多变的

价值

多变的

价值

多变的

价值

0

Var1

01

Var1

01

Var1

01

Var1

01

Var1

01

1

Var2

11

Var2

11

Var2

11

Var2

11

Var2

11

2

Var3

22

Var3

22

Var3

22

Var3

22

Var3

22

3

…

00

…

00

…

00

…

00

…

00

4

Var4

44

Var4

44

Var4

44

Var4

44

Var4

44

5

Var5

55

Var5

55

6

…

66

…

66

Var5

55

7

…

77

…

77

…

66

8

Var5

55

…

88

…

88

…

77

Var5

55

9

…

66

Var6

99

Var6

99

…

88

…

66

10

…

77

Var7

AA

Var7

AA

Var6

99

…

77

11

…

88

Var8

AA

Var8

AA

Var7

AA

…

88

12

Var6

99

…

00

…

00

Var8

AA

Var6

99

13

Var7

AA

…

00

…

00

…

00

Var7

AA

14

…

00

…

00

…

00

15

…

00

16

Var8

AA

Var8

AA

17

…

00

…

00

18

…

00

…

00

19

…

00

…

00

20

21

22

23

24

25

26

27

28

29

30

31

示例 3

STRUCT
    Var1 : BYTE  := 16#01;
    Var2 : LWORD := 16#11;
    Var3 : BYTE  := 16#22;
    Var4 : BYTE  := 16#44;
    Var5 : DWORD := 16#88776655;
    Var6 : BYTE  := 16#99;
    Var7 : BYTE  := 16#AA;
    Var8 : WORD  := 16#AA;
END_TYPE

pack_mode = 8

pack_mode = 0

pack_mode = 1

pack_mode = 2

pack_mode = 4

多变的

价值

多变的

价值

多变的

价值

多变的

价值

多变的

价值

0

Var1

01

Var1

01

Var1

01

Var1

01

Var1

01

1

Var2

11

Var2

11

2

…

00

…

00

Var2

11

3

…

00

…

00

…

00

4

…

00

…

00

…

00

Var2

11

5

…

00

…

00

…

00

…

00

6

…

00

…

00

…

00

…

00

7

…

00

…

00

…

00

…

00

8

Var2

11

…

00

…

00

…

00

…

00

9

…

00

Var3

22

Var3

22

…

00

…

00

10

…

00

Var4

44

Var4

44

Var3

22

…

00

11

…

00

Var5

55

Var5

55

Var4

44

…

00

12

…

00

…

66

…

66

Var5

55

Var3

22

13

…

00

…

77

…

77

…

66

Var4

44

14

…

00

…

88

…

88

…

77

15

…

00

Var6

99

Var6

99

…

88

16

Var3

22

Var7

AA

Var7

AA

Var6

99

Var5

55

17

Var4

44

Var8

AA

Var8

AA

Var7

AA

…

66

18

…

00

…

00

Var8

AA

…

77

19

…

00

…

88

20

Var5

55

Var6

99

21

…

66

Var7

AA

22

…

77

Var8

AA

23

…

88

…

00

24

Var6

99

25

Var7

AA

26

Var8

AA

27

…

00

28

29

30

31

没有的行为 'pack-mode'

如果 'pack-mode' 不使用,则编译器通常使用打包模式 4 或 8,具体取决于设备描述。在每种情况下,都使用对处理器特别有利的打包模式,以便可以执行内存访问。这也称为自然对齐或数据的自然对齐

使用时的负面影响 'pack-mode'

未对齐的内存访问可能是使用属性的结果 'pack_mode'.这意味着,例如,一个大小为 4 字节的数据类型位于一个不能被 4 整除的地址。通常,在 32 位系统上,一个 32 位数据类型可以用单内存访问。在某些平台上,例如在 ARM 平台上,仅当此值在内存中对齐时才有可能。在其他平台上,可能可以访问,但执行速度要慢得多。

{attribute 'pack_mode':=1}

TYPE DUT
STRUCT
    by1 : BYTE;
    dw1 : DWORD;
END_STRUCT
END_TYPE

在 ARM 平台上,值 dw1 单次访问无法读取。当尝试直接访问此元素时,ARM 处理器将抛出异常。

假设:执行以下读取访问: dwTest := dut1.dw1;

对于这种访问 DWORD dw1,需要四次内存访问,因为每个字节都是单独读取、移位和分离的。该流程与以下示例中的流程有些相同,其中 DWORD 由四个字节的数组生成:

dwHelp := bytes[0];
dwResult := dwHelp;
dwHelp := bytes[1];
dwHelp := SHL(dwHelp, 8);
dwResult := dwResult OR dwHelp;
dwHelp := bytes[2];
dwHelp := SHL(dwHelp, 16);
dwResult := dwResult OR dwHelp;
dwHelp := bytes[3];
dwHelp := SHL(dwHelp, 24);
dwResult := dwResult OR dwHelp;

显然,这种访问比访问一个 DWORD,它在内存中适当地对齐。

pdw := ADR(dut1.dw1);
dwTest := pdw^;

但是,当通过指针访问这种成员时,编译器不会生成示例的访问。这意味着以下代码会在 ARM 平台上导致异常。

pdw := ADR(dut1.dw1);
dwTest := pdw^;

因此,出于性能原因,您应该避免使用未自然对齐的结构。

压缩结构不得包含未压缩结构。