Assembly 寄存器一次可以保存多个值吗?
在64位x86寄存器的情况下,如果一个值的大小足够小,以至于一个寄存器可以容纳多条指令,那么在同一寄存器中一次可以容纳多个值吗?例如,将两个32位整数装入一个寄存器。如果可能的话,这会是一件坏事吗?我一直在读寄存器的书,对这个概念我很陌生。寄存器不倾向于保存指令,而是保存要由指令处理的数据 然而,如果您想将指令存储为数据,我相信最长的x86指令大约是15个字节,或120位。所以,不,它不能装入单个64位寄存器 就在单个寄存器中保存多个数据值而言,这当然是可能的。这甚至得到了硬件的支持,即使是最早的x86芯片也有Assembly 寄存器一次可以保存多个值吗?,assembly,x86-64,simd,cpu-registers,swar,Assembly,X86 64,Simd,Cpu Registers,Swar,在64位x86寄存器的情况下,如果一个值的大小足够小,以至于一个寄存器可以容纳多条指令,那么在同一寄存器中一次可以容纳多个值吗?例如,将两个32位整数装入一个寄存器。如果可能的话,这会是一件坏事吗?我一直在读寄存器的书,对这个概念我很陌生。寄存器不倾向于保存指令,而是保存要由指令处理的数据 然而,如果您想将指令存储为数据,我相信最长的x86指令大约是15个字节,或120位。所以,不,它不能装入单个64位寄存器 就在单个寄存器中保存多个数据值而言,这当然是可能的。这甚至得到了硬件的支持,即使是最早
ah
和al
,它们共同构成了ax
寄存器
即使没有这一点,您也可以通过使用逐位操作(如
和,或,非和异或和异或以及位移位操作(如shl
,shr
,rol
)将“子寄存器”插入/从寄存器中提取.寄存器不包含指令,但我假设您的意思是将多个值装配到一个寄存器中,这样您就可以用一条指令同时添加它们
是的,在x86-64上称为,SSE2(数据流单指令多数据扩展指令集)保证可用,因此您有16个不同的16字节寄存器(xmm0..15)。还有一些指令可以对字节、字、dword和qword操作数大小进行4x 32位浮点、2x 64位双精度、压缩整数的压缩FP add/sub/mul/div/sqrt/cmp/等操作
(有一些间隙;SSE2不是非常正交,例如,最窄的移位是16位,压缩最小值/最大值仅适用于某些尺寸。其中一些间隙由SSE4.1填补)
以及元素宽度不相关的位布尔值(直到带有掩码寄存器的AVX512…)
看p..
指令,如paddw
是压缩整数..ps
和pd
是浮点压缩单精度或压缩双精度
编译器经常使用SSE/SSE2指令,如将内存归零或复制为16字节块,以及对数组上的循环进行“矢量化”(使用SIMD计算)。GCC 7或8以及更高版本都知道如何使用RAX将相邻结构成员或数组元素的加载/存储合并为标量加载或存储
e、 g.数组的这个和:
int sumarr(const int *arr)
{
int sum = 0;
for(int i=0; i < 10240; i++) {
sum += arr[i];
}
return sum;
}
矢量化有点像并行化,对于这样的缩减(将数组求和为标量)需要关联操作。e、 g.FP版本只能使用-ffast math
或OpenMP进行矢量化
在像RAX这样的通用寄存器中,没有在字节边界之间不进位的情况下进行SIMD加法的指令(就像这样),它被称为SWA(寄存器中的SIMD)
在过去,这种技术在没有适当的SIMD指令集(如Alpha或MIPS64)的ISA上更有用。但这仍然是可能的,SWAR技术可以作为popcount的一部分,而不使用popcnt
指令,例如,屏蔽每一位并进行移位,这样就可以有效地对2位累加器进行32个单独的加法(不能互相溢出)
图中所示的popcnt bithack就是这样做的,先扩展到4位计数器,然后扩展到8位,然后使用乘法移位,再加上4个不同的移位,生成高字节的和。对不起,是的,你说得对,我将编辑这个问题。但不管怎样,它们能同时保存多个不同的数据值吗?这取决于您如何看待它。它们只存储一定数量的位。这些位对您意味着什么,如果您将它们解释为1个值、2个值,或者甚至64个独立的值(1位标志),则取决于您/您的程序。当然,是的。一个64位寄存器可以容纳64个不同的布尔值。都是二进制数据。是的,将多个值打包到一个寄存器中是很常见的。mmx和xmm(包括ymm和zmm)寄存器是专门为此设计的。64位寄存器包含64位、64项,这64位的含义完全由程序员所有,处理器不知道。因此,在一个值和64之间的任何位置都可以保存一个64位寄存器。处理内存的速度较慢,因此在寄存器中保存两个32位值可能会更快,从内存中读取64位比读取两个32位项快(尽管x86开销通常会掩盖这一点)。同时,需要更多的指令来维护寄存器中的多个项。一般来说,x86具有RAX/EAX/AX/AH/AL功能,可以帮助但不能完全解决此问题。因此,这是一种权衡。对于x86,尝试这样做通常没有好处。也许是其他架构。具体取决于要解决的问题。一个包含多个字段的结构,只要其总大小为64位或更少,就可以完全放在一个寄存器中。
sumarr:
lea rax, [rdi+40960] # endp = arr + size
pxor xmm0, xmm0
.L2: # do {
movdqu xmm2, XMMWORD PTR [rdi] # v = arr[i + 0..3]
add rdi, 16 # p += 4
paddd xmm0, xmm2 # sum += v // packed addition of 4 elements
cmp rax, rdi
jne .L2 # }while(p != endp)
... then a horizontal vector sum ...
MOVD eax, xmm0
ret