Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 寄存器一次可以保存多个值吗?_Assembly_X86 64_Simd_Cpu Registers_Swar - Fatal编程技术网

Assembly 寄存器一次可以保存多个值吗?

Assembly 寄存器一次可以保存多个值吗?,assembly,x86-64,simd,cpu-registers,swar,Assembly,X86 64,Simd,Cpu Registers,Swar,在64位x86寄存器的情况下,如果一个值的大小足够小,以至于一个寄存器可以容纳多条指令,那么在同一寄存器中一次可以容纳多个值吗?例如,将两个32位整数装入一个寄存器。如果可能的话,这会是一件坏事吗?我一直在读寄存器的书,对这个概念我很陌生。寄存器不倾向于保存指令,而是保存要由指令处理的数据 然而,如果您想将指令存储为数据,我相信最长的x86指令大约是15个字节,或120位。所以,不,它不能装入单个64位寄存器 就在单个寄存器中保存多个数据值而言,这当然是可能的。这甚至得到了硬件的支持,即使是最早

在64位x86寄存器的情况下,如果一个值的大小足够小,以至于一个寄存器可以容纳多条指令,那么在同一寄存器中一次可以容纳多个值吗?例如,将两个32位整数装入一个寄存器。如果可能的话,这会是一件坏事吗?我一直在读寄存器的书,对这个概念我很陌生。

寄存器不倾向于保存指令,而是保存要由指令处理的数据

然而,如果您想将指令存储为数据,我相信最长的x86指令大约是15个字节,或120位。所以,不,它不能装入单个64位寄存器

就在单个寄存器中保存多个数据值而言,这当然是可能的。这甚至得到了硬件的支持,即使是最早的x86芯片也有
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