理解为 gcc 编写的 asm 块

understanding asm blocks written for gcc

下面的汇编在简单的 C 中是什么意思(这意味着要用 gcc 编译):

asm volatile
    (
    "mov.d %0,%4\n\t"
    "L1: bge %2,%3,L2\n\t"
    "gsLQC1 $f2,$f0,0(%1)\n\t"
    "gsLQC1 $f6,$f4,0(%5)\n\t"
    "madd.d %0,%0,$f6,$f2\n\t"
    "madd.d %0,%0,$f4,$f0\n\t"
    "add %1,%1,16\n\t"
    "add %2,%2,2\n\t"
    "add %5,%5,16\n\t"
    "j L1\n\t"
    "L2: nop\n\t" 
    :"=f"(sham)
    :"r"(foo),"r"(bar),"r"(ro),"f"(sham),"r"(bo)
    :"$f0","$f2","$f4","$f6"
    );

经过几个小时的搜索和阅读,我得出了以下 AT&T 语法的汇编代码:

mov.d %xmm0,%xmm1
L1: bge %ebx,%ecx,L2
gsLQC1 $f2,$f0,0(%eax)
gsLQC1 $f6,$f4,0(%esi)
madd.d %xmm0,%xmm0,$f6,$f2
madd.d %xmm0,%xmm0,$f4,$f0
add %eax,%eax,16
add %ebx,%ebx,2
add %esi,%esi,16
jmp L1
L2: nop

我正在 Windows 上寻找 运行 的方法,当我找到方法时会更新(在修复我所有的错误之后我确定我做到了)。

我对x86汇编的经验很少,也就是说,我隐约意识到这是一个循环,但我一直没能找到gsLQC1指令的含义。或者循环的目的是什么。

如果您有任何问题要问我,我很乐意回答。如果您有任何见解,我很想听听。谢谢你的时间。

编辑:

该函数本身正在执行主要与矩阵有关的奇异值分解 (SVD)。

我正在用我自己的一些评论更新下面的内容,程序集的原始作者没有写这些,但鉴于我对 GCC 的 asm 块表示法的研究,我有 80% 的信心认为它们是正确的。

    asm volatile
       (
       "mov.d %0,%4\n\t"
       "L1: bge %2,%3,L2\n\t"
       "gsLQC1 $f2,$f0,0(%1)\n\t"
       "gsLQC1 $f6,$f4,0(%5)\n\t"
       "madd.d %0,%0,$f6,$f2\n\t"
       "madd.d %0,%0,$f4,$f0\n\t"
       "add %1,%1,16\n\t"
       "add %2,%2,2\n\t"
       "add %5,%5,16\n\t"
       "j L1\n\t"
       "L2: nop\n\t" 
       :"=f"(sham) /*Corresponds to %0 in the above code*/
       :"r"(foo) /*Corresponds to %1*/,"r"(bar) /*%2*/,"r"(ro) /*%3*/,"f"(sham) /*%4*/,"r"(bo) /*%5*/
       :"$f0","$f2","$f4","$f6"
       );

我以为这是在 x86 中,但很可能是错误的。我相信上面是为龙芯家族的处理器编写的MIPS64汇编。

感谢您对这个问题的关注。我感谢你的时间。再说一次,如果还有其他问题,我很乐意尽力回答。

P.S。可以找到原始代码here,我问的程序集从第189行开始

这不是真正的答案,但也不适合发表评论。鉴于您省略了几个关键信息(源指令用于哪个处理器、参数的数据类型、代码正在做什么等),很难得出一个好的答案。

一般来说,我会想:

float messy(const float *foo, int bar, int ro, const float *bo)
{
    float sham = 0;

    while (bar < ro)
    {
       __m256 a = _mm256_load_ps(foo);
       __m256 b = _mm256_load_ps(bar);

       __m256 c = _mm256_add_ps(a, a);
       __m256 d = _mm256_add_ps(b, b);

       foo += 2;
       bar += 2;
       bo += 2;
    }

    return sham;
}

这不太正确,因为(除其他事项外)sham 尚未设置。但这是一个开始的地方。没有详细说明 madd.d 的功能(如果不知道我们在谈论什么硬件就很难说),这就是我能告诉你的最接近的。

强调一下我评论里说的,原来的代码好像写得不好(修改只读参数,双跳转,NO COMMENTS等)