关于在C ++代码中使用内联汇编,我是非常新的。 我想要做的基本上是一种带有模数为32的指针的记忆。
在C ++中,代码使用如下:
void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t& sz)
{
assert((sz%32 == 0));
for(const std::uint8_t* it = beg; it != (beg+sz);it+=32,out+=32)
{
__m256i = _mm256_stream_load_si256(reinterpret_cast<__m256i*>(it));
_mm256_stream_si256(reinterpret_cast<__m256i*>(out),tmp);
}
}
我已经做了一些内联汇编,但每次事先都知道输入选项卡的大小和输出选项卡。
所以我尝试了这个:
void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t& sz)
{
assert((sz%32 == 0));
__asm__ volatile(
"mov %1, %%eax \n"
"mov $0, %%ebx \n"
"L1: \n"
"vmovntdqa (%[src],%%ebx), %%ymm0 \n"
"vmovntdq %%ymm0, (%[dst],%%ebx) \n"
"add %%ebx, $32 \n"
"cmp %%eax, %%ebx \n"
"jz L1 \n"
:[dst]"=r"(out)
:[src]"r"(in),"m"(sz)
:"memory"
);
}
G ++告诉我:
Error: unsupported instruction `mov'
Error: `(%rdi,%ebx)' is not a valid base/index expression
Error: `(%rdi,%ebx)' is not a valid base/index expression
Error: operand type mismatch for `add'
所以我尝试了这个:
void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t& sz)
{
assert((sz%32 == 0));
__asm__ volatile(
"mov %1, %%eax \n"
"mov $0, %%ebx \n"
"L1: \n"
"vmovntdqa %%ebx(%[src]), %%ymm0 \n"
"vmovntdq %%ymm0, (%[dst],%%ebx) \n"
"add %%ebx, $32 \n"
"cmp %%eax, %%ebx \n"
"jz L1 \n"
:[dst]"=r"(out)
:[src]"r"(in),"m"(sz)
:"memory"
);
}
我从G ++获得:
Error: unsupported instruction `mov'
Error: junk `(%rdi)' after register
Error: `(%rdi,%ebx)' is not a valid base/index expression
Error: operand type mismatch for `add'
在每种情况下,我试图找到一个没有成功的解决方案。 我也遇到了这个解决方案:
void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t& sz)
{
__asm__ volatile (
".intel_syntax noprefix;"
"mov eax, [SZ];"
"mov ebx, 0;"
"L1 : "
"vmovntdqa ymm0, [src+ebx];"
"vmovntdq [dst+ebx], ymm0;"
"add ebx, 32 \n"
"cmp ebx, eax \n"
"jz L1 \n"
".att_syntax;"
: [dst]"=r"(out)
: [SZ]"m"(sz),[src]"r"(in)
: "memory");
}
G ++:
undefined reference to `SZ'
undefined reference to `src'
undefined reference to `dst'
这个消息看起来很常见,但我不知道在这种情况下如何修复它。
我知道我的尝试并不严格代表我在C ++中编写的代码。
我想了解我尝试过的错误,以及如何尽可能接近我的C ++函数。
提前感谢。
答案 0 :(得分:2)
您的第一个示例是最正确的并且有以下错误:
dst
被声明为输出,应该是输入。add
指令的参数是错误的方式,在AT&amp; T语法中,目标寄存器是最后一个。以下表现问题:
sz
参数通过引用传递。 (也可能会影响调用函数的优化)这是一个固定版本,它不比具有内在函数的等效C ++快:
void my_memcpy(const std::uint8_t* in,std::uint8_t* out,const std::size_t sz)
{
std::size_t count = 0;
__m256i temp;
assert((sz%32 == 0));
__asm__ volatile(
"1: \n"
"vmovntdqa (%[src],%[count]), %[temp] \n"
"vmovntdq %[temp], (%[dst],%[count]) \n"
"add $32, %[count] \n"
"cmp %[sz], %[count] \n"
"jz 1b \n"
:[count]"+r"(count), [temp]"=x"(temp)
:[dst]"r"(out), [src]"r"(in), [sz]"r"(sz)
:"memory", "cc"
);
}
源和目标参数是memcpy
的另一种可能混淆的方式。
您的英特尔语法版本添加也无法使用正确的语法来引用参数(例如%[dst]
)。