术语字长或machine word,通常是指寄存器的大小,以及本机加载/存储的大小。维基百科文章提到了我在这个答案中写的一些相同的东西。
对于 64 位系统,一个字可能意味着 8 个字节,但是对于 64 位 RISC 机器来说,通常使用字 = 32 位。它们中的大多数都是从 32 位 RISC ISA 演变而来的,因此保持相同的术语并将 64 位称为双字是很自然的。
(请注意,GDB 使用自己的“词”概念,与 ISA 不同。)
但是 x86 是从 16 位 8086 演变而来的,其中 word = 16 位。当 x86 扩展为具有 32 位模式 (i386) 时,每个人最简单的选择就是为所有内容保持相同的名称。 x86 dword 仍然是 32 位,x86 字仍然是 16 位。即使是原始的 8086 + 8087 也可以加载和存储 dword 和 qword 整数、浮点数和双精度数,并且 8086 中存在像 cwd(符号扩展字到 dword)这样的指令来设置 idiv,所以这些术语已经完整在 386 之前使用将寄存器宽度扩展到 dword。
还请注意,重命名所有内容会非常混乱,因为当 386 是新的时,它们中的大多数仍然在 16 位模式下用于运行 DOS 程序。即使是现代 x86-64 CPU 也完全支持在 16 位实模式下运行,因此在英特尔手册的不同部分中使用 word 表示不同的含义会非常令人困惑。
字节总是是一个 8 位的八位字节,除了在某些历史计算机体系结构中。有些是 9 位字节。 C 标准仍然不要求 CHAR_BIT = 8,因此要编写完全可移植的代码,您不能假设或 2 的补码有符号整数。
所以在 x86 文档和 asm 助记符/语法中:
- B = 字节 = 8 位(
PADDB 在向量中添加压缩的 8 位整数)
- W = word = 16 位(
PADDW 在向量中添加压缩的 16 位整数)
- D = long 或 dword(双字)= 32 位(
PADDD 在向量中添加压缩的 32 位整数)
- Q = 四字 = 64 位(
PADDQ 在向量中添加压缩的 64 位整数)
- DQ = 双四进制(有时也是八字)= 128b(
movdqa 复制对齐的 128b。PUNPCKLQDQ:交错 L两个 64 位 Q 128b src 和 dest 的词放入 DQ dest。)
AVX movdqa ymm0, [rdi] 是一个 32B 负载,尽管它仍然使用相同的助记符。 AVX 更像是多个 128b 通道,而不是真正的原生 256b 向量,所以这种说法是合理的。
在 NASM 语法中,有时需要像 mov ax, word ptr [rdi] 这样的语法来指定操作数大小,而不是从 dest 寄存器推断它。 AT&T 语法在助记符上使用后缀来指定操作数大小,如果您不想让它隐含并从寄存器的选择中推断:movw (%rdi), %ax。
助记符中的 B/W/D 事物早于向量扩展,以字符串移动指令为例。 STOS 确实 *(rdi+=size) = al/ax/eax/rax。它可以用一个操作数编写,例如
STOS byte pointer [RDI] 告诉汇编器要编码的操作数大小版本。但即使是 Intel / MASM / NASM 语法,你也可以写STOSB / STOSW / STOSD / STOSQ。
x86 非常不是面向单词的架构。
“机器字”的整个概念不适用于 x86。 仅限 32 位的 P5 Pentium CPU 保证高达 64 位的原子加载/存储。 (例如,使用 x87 或 MMX),即使 integer 寄存器宽度仅为 32 位。 (64 位 CAS 在 32 位模式下需要 lock cmpxchg8b)。
使用 x86-64,可以保证对 SSE2 的支持,因此我们有 16 字节的向量寄存器,并且基本上可以有效地支持每条具有 8、16、32 或 64 位操作数大小的整数指令。 (32 位操作数大小是 x86-64 机器代码中的默认值(不需要额外的前缀),因此它对于代码大小和有时还有除此之外的性能是最有效的,例如在某些情况下对于 div 或 imul CPU。)
此外,未对齐的加载和存储是完全有效的,只要不跨越缓存行边界,甚至不需要额外的缓存 RMW 周期来将未对齐或字节存储提交到 L1d 缓存。而且指令格式是字节流,不是对齐的字。
所以说现代 x86-64 有任何特定的“字长”并不是很有意义。这个概念不适合 x86-64 作为 ISA,当然也不适合具有高效未对齐加载/存储的实际现代微架构。