6. 对齐
优质
小牛编辑
135浏览
2023-12-01
内存里的所有数据都必须按照下表将地址对齐到可以被 2,4,8 或 16 整除的位置:
操作数据长度 | PPlain 及 PMMX | PPro, PII 及 PIII |
1 (byte) | 1 | 1 |
2 (word) | 2 | 2 |
4 (dword) | 4 | 4 |
6 (fword) | 4 | 8 |
8 (qword) | 8 | 8 |
10 (tbyte) | 8 | 16 |
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章阐述。