6. 对齐

优质
小牛编辑
135浏览
2023-12-01

内存里的所有数据都必须按照下表将地址对齐到可以被 2,4,8 或 16 整除的位置:

操作数据长度PPlain 及 PMMXPPro, PII 及 PIII
1 (byte)11
2 (word)22
4 (dword)44
6 (fword)48
8 (qword)88
10 (tbyte)816
16 (oword)n.a.16

在 PPlain 和 PMMX 上,在4字节边界线交错的时候,访问未对齐数据将至少有 3 个时钟周期的额外消耗。 当cache边界线被交错的时候损耗更大。

在 PPro,PII 和 PIII 上,当cache边界线交错时,未对齐数据将消耗掉 6-12 个时钟周期。 尺寸小于 16 字节的未对齐操作数,没有在 32 字节边界上交错时将没有额外的损耗。

在 dword 堆栈上以 8 或 16 对齐数据可能会有问题。常用的方法是设置对齐的结构指针。对齐本地数据的函数可以是这样:

_FuncWithAlign PROC NEAR
PUSH EBP ; 前续代码
MOV EBP, ESP
AND EBP, -8 ; 以 8 来对齐帧指针
FLD DWORD PTR [ESP+8] ; 函数参数
SUB ESP, LocalSpace + 4 ; 分配本地空间
FSTP QWORD PTR [EBP-LocalSpace] ; 在对齐了的空间保存一些东西
...
ADD ESP, LocalSpace + 4 ; 结束代码。 恢复 ESP
POP EBP ; (PPlain/PMMX 上有 AGI 延迟)
RET
_FuncWithAlign ENDP

虽然对齐数据永远是重要的,但是在 PPlain 和 PMMX 上对齐代码却没有必要。 PPro,PII 及 PIII 上对齐代码的原则在第15章阐述。