TL:DR:您基本上不需要地址大小的前缀。使用 64 位寻址模式。
我听说过 (CACHE),最好使用“32 位”而不是“64 位”
您将地址大小与操作数大小混为一谈。 32 位整数占据了一半的空间,因此更多的整数适合一个高速缓存行。更好的空间局部性,更少的内存带宽。
选择 64 位模式的默认值是有原因的,并且是您在方便时应该首选的,以在其他条件相同时节省代码大小 (The advantages of using 32bit registers/instructions in x86-64):
所以像mov ecx, [rdi] 这样的例子是最有效的;其他尺寸需要 REX 或其他前缀。字节操作数大小使用不同的操作码而不是前缀,但写入 8 位寄存器可能会对完整寄存器的旧值产生错误的依赖性。首选movzx 加载;对于 2 字节的操作码,这通常值得多出一个字节的代码大小。
如果您的号码正确地零扩展为 64 位,请避免使用地址大小前缀并使用
movzx ecx, byte [rbx + .DATA]
写入 32 位寄存器会隐式零扩展为 64 位,因此您可以通过在内存中使用 32 位数据来节省缓存占用空间。
如果索引可能不正确地以零或符号扩展为地址大小,您可能需要额外的指令来实现这一点(movsxd rcx, ebx 或mov ecx, ebx),这样您就可以使用 64 位寻址模式。
[reg + sign_extended_disp32] 寻址模式是一个有趣的例子:它们只适用于所有适合 32 位的符号地址。如果您知道整个数组位于虚拟地址空间的低 4GiB 中,您可能会使用[ebx + .DATA] 来避免额外的指令扩展到 64 位,如果您知道 RBX 的高半部分可能存在垃圾. (所以用户空间中的静态地址,但可能不在高半内核中,您可能在 high 32 位的 64 位虚拟地址空间中有静态数据。)
如果您知道指针可以安全地截断为 32 位(例如 mmap(MAP_32BIT) 或使用 x32 ABI),您甚至可以在循环中使用 mov edi, [rdi] 之类的指令遍历链表或树。可能对指针繁重的数据结构有用。
(您的问题是关于数组索引,而不是指针;在 asm 中,您通常希望将它们视为 32 位无符号整数,或者如果数组很大,则为 64。
或者使用指针而不是[reg+disp32] 来循环数组; disp32 绝对地址仅适用于 Linux 位置相关的可执行文件,或 Windows LARGEADDRESSAWARE=no。)