理解为 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等)
下面的汇编在简单的 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等)