Skip to main content

属性:pack_mode

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

句法

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

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

25. 可能的值 <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 被分配“对齐”。如果其组件的存储地址 Enable0x0100,例如,那么组件 Counter 跟随地址 0x0101, MaxSize 在地址 0x0103MaxSizeReached 在地址 0x0104.如果是 'pack_mode':=2, Counter 会在 0x0102, MaxSize0x0104MaxSizeReached0x0105.

示例 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^;

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

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