如何将 XMM 寄存器中的数字存储到 asm 循环中的 char 数组中 -

Posted

技术标签:

【中文标题】如何将 XMM 寄存器中的数字存储到 asm 循环中的 char 数组中 -【英文标题】:How to store numbers from a XMM register into a char array within an asm loop - 【发布时间】:2014-03-28 17:51:07 【问题描述】:

我有一个 xmm 寄存器,其中包含四个 32 位数字。

XMM4 = 00000035000000350000003500000035

我有一个循环反复计算这些数字,然后我需要以某种方式将它们存储在一个数组中。如何在循环的每次迭代中使用 asm 存储 XMM 寄存器中的每个单独的数字?

编辑:

我尝试在我的 __asm 块之外创建一个 char 数组,如下所示:char numbers[20]; 然后我尝试使用movdqa [numbers], xmm4 将我的注册值移入其中。这适用于循环的第一次迭代,但我不知道如何在顺序迭代中增加数组的索引。

Edit2:这是我的代码

    __m128i stuff = _mm_setr_epi32 ( 87, 137, 202, 222 );

    __m128i zeros = _mm_setr_epi32 ( 0x0, 0x0, 0x0, 0x0 );

    __m128i fives = _mm_setr_epi32 ( 0x5, 0x5, 0x5, 0x5 );

    __m128i fortyEights = _mm_setr_epi32 ( 0x30, 0x30,0x30, 0x30 );

    __m128i magicNumber = _mm_setr_epi32 ( 0x66666667, 0x66666667, 0x66666667, 0x66666667 );

        __asm  
                movdqa      xmm0, stuff         //Move data into xmm0
                movdqa      xmm1, magicNumber   //Move magic numbers into xmm1
                movdqa      xmm2, xmm0          //Copy data into xmm2
                vpcmpeqb    xmm2, xmm0, xmm2    //Compare data against zeros
                je          bail            //if data is all zeros then bail

    nextdigit:  pmulhw      xmm2, xmm1          //Multiply data in xmm2 by the magic numbers in xmm1
                psrad       xmm2, 2             //Divide [wip]data by 4 
                movdqa      xmm3, fives         //Copy the fives into xmm3
                pmullw      xmm3, xmm2          //Multiply [wip]data in xmm2 by the fives in xmm3
                paddd       xmm3, xmm3          //Multiply the [wip]data by 2
                movdqa      xmm4, xmm0          //Copy the original into xmm4
                psubd       xmm4, xmm3          //Subtract the [wip]data from the original data
                paddd       xmm4, fortyEights   //Add 48 to the [wip]data in xmm4 in order to get the ascii value

    // HERE IS WHERE I WANT TO SAVE THE VALUES TO AN ARRAY

                comiss      xmm0, zeros
                jne         nextdigit
bail:
                mov         eax, 0
    

【问题讨论】:

向我们展示您的代码,您将获得帮助。 如果您在 C++ 中执行此操作,为什么要使用内部函数而不是内联汇编? @Mysticial: ITYM“为什么使用内在函数...”? 该死,来不及编辑我的评论。是的,这就是我的意思,“为什么使用内在函数?” 我已经用代码编辑了我的帖子。 【参考方案1】:

使用通用寄存器之一进行索引,例如:

  movdqa [oword ptr numbers + edx], xmm4      //Store xmm4 to numbers array
  add     edx, 16                              //Increment index

【讨论】:

嗨@GJ.,感谢您的回答。当我将您的代码段放入上面显示的代码中时 // HERE IS WHERE... 我得到的错误是“context”中 PTR 运算符的非法类型 @Ste Prescott:抱歉,在 C++ 中使用 OWORD PTR 感谢您的回复。但是,当我这样做时,寄存器值会附加到每个循环的数组末尾,并且我最终会在每个字符之间添加一堆“0”。理想情况下,我想要的是递增和索引,以便我控制填充数组中的哪些位置。知道怎么做吗? @Ste Prescott:据我了解,您有 16 字节对齐的数组,每个成员都是 16 字节长或四个 32 位数字。因此,如果 edx 为 0,则您将寻址数组的第一个成员,如果您将 16 与 add edx, 16 指令添加到 edx,而不是索引指向第二个成员,依此类推!【参考方案2】:

这段代码有很多错误。我不知道你甚至想做什么,但这些都是大问题:

您只想在 16B 寄存器的底部字节中存储一两个字符?为什么需要向量?

pcmpeqb 生成 0 或 0xff 字节的掩码,并且不为 jcc 设置标志。 (为此使用 SSE4.1 PTEST)。

comiss xmm0, zeros 对保存整数数据的 xmm0 的低 4 个字节进行 浮点 比较。 (ss = 标量单精度)。我不确定当整数数据恰好是NaN 时会发生什么。与零比较是唯一有希望的比较。

您可以使用_mm_set1_epi32(0x66666667)进行广播。

扔掉你当前的所有代码,重新开始整个事情的内在函数。查看https://***.com/tags/x86/info的一些资源

【讨论】:

以上是关于如何将 XMM 寄存器中的数字存储到 asm 循环中的 char 数组中 -的主要内容,如果未能解决你的问题,请参考以下文章

将单个浮点数移动到 xmm 寄存器

将XMM寄存器推入堆栈

ASM x86_64 AVX:xmm 和 ymm 寄存器差异

内联 ASM:使用 MMX 在计时器上返回 NaN 秒

在 Assembler 中调试 xmm 寄存器

XMM 寄存器中的取消引用指针(收集)