【发布时间】:2020-12-27 21:22:00
【问题描述】:
我一直在玩 this 演示文稿中的示例(幻灯片 41)。
就我而言,它执行 alpha 混合。
MOVQ mm0, alpha//4 16-b zero-padding α
MOVD mm1, A //move 4 pixels of image A
MOVD mm2, B //move 4 pixels of image B
PXOR mm3 mm3 //clear mm3 to all zeroes
//unpack 4 pixels to 4 words
PUNPCKLBW mm1, mm3 // Because B -A could be
PUNPCKLBW mm2, mm3 // negative, need 16 bits
PSUBW mm1, mm2 //(B-A)
PMULHW mm1, mm0 //(B-A)*fade/256
PADDW mm1, mm2 //(B-A)*fade + B
//pack four words back to four bytes
PACKUSWB mm1, mm3
我想用汇编程序用c重写它。
现在,我有这样的事情:
void fade_mmx(SDL_Surface* im1,SDL_Surface* im2,Uint8 alpha, SDL_Surface* imOut)
{
int pixelsCount = imOut->w * im1->h;
Uint32 *A = (Uint32*) im1->pixels;
Uint32 *B = (Uint32*) im2->pixels;
Uint32 *out = (Uint32*) imOut->pixels;
Uint32 *end = out + pixelsCount;
__asm__ __volatile__ (
"\n\t movd (%0), %%mm0"
"\n\t movd (%1), %%mm1"
"\n\t movd (%2), %%mm2"
"\n\t pxor %%mm3, %%mm3"
"\n\t punpcklbw %%mm3, %%mm1"
"\n\t punpcklbw %%mm3, %%mm2"
"\n\t psubw %%mm2, %%mm1"
"\n\t pmulhw %%mm0, %%mm1"
"\n\t paddw %%mm2, %%mm1"
"\n\t packuswb %%mm3, %%mm1"
: : "r" (alpha), "r" (A), "r" (B), "r" (out), "r" (end)
);
__asm__("emms" : : );
}
编译时我收到以下消息:Error: (%dl) is not a valid base/index expression 关于汇编程序中的第一行。
我怀疑这是因为alpha 是Uint8,我尝试转换它,但后来出现分段错误。在示例中,他们谈论的是4 16-b zero-padding α,这对我来说并不是很清楚。
【问题讨论】:
-
将
alpha转换为uint32并删除(%0)中的括号。 -
我会尝试
Uint16 alphaArray[4] = { alpha, alpha, alpha, alpha }或类似的。 -
如果可能,考虑使用内在函数而不是内联汇编。这不太容易出错,并且允许编译器尽可能使用 SSE 指令来实现相同的代码。
-
看起来您连续两次执行
punpcklbw %%mm3, %%mm1,而不是进入 MM1 和 MM2。最初的 intel-syntax 源有 3 个解包,其中一个看起来很额外,就像它被重复以腾出空间来放更长的评论??!? -
您实际上可能最好用纯 C 编写此代码。GCC 可以很好地自动矢量化它。
标签: assembly x86-64 inline-assembly mmx