2011-12-23 37 views
7

我正在研究内联汇编。我想在Xcode 4 LLVM 3.0 Compiler下编写一个简单的例程。我成功地编写了基本的内联汇编代码。如何在Xcode LLVM中编写关于LOOP的内联汇编代码?

例如:

int sub(int a, int b) 
{ 
    int c; 
    asm ("sub %0, %1, %2" : "=r" (c) : "r" (a), "r" (b)); 
    return c; 
} 

我发现它在stackoverflow.com和它工作得很好。但是,我不知道如何编写关于LOOP的代码。

我需要汇编代码就像

void brighten(unsigned char* src, unsigned char* dst, int numPixels, int intensity) 
{ 
    for(int i=0; i<numPixels; i++) 
    { 
     dst[i] = src[i] + intensity; 
    } 
} 
+2

像这样的功能也可以使用OpenGL ES和片段着色器来实现。如果这适用于您的问题。这会让你免费并行化,就像Matt所说的那样使用NEON。 – Arne 2011-12-23 11:20:33

+0

你肯定可以肯定地使用OpenGL ES。取决于你在做什么,如果你想把它作为一个依赖关系。 – mattjgalloway 2011-12-23 12:25:40

+0

如果OpenGL ES需要将计算的总和返回给CPU,则速度可能不够快。 iPad GPU不是为了有效执行此任务而制造的。 – Etan 2011-12-23 12:35:49

回答

5

这里看看环部分 - http://en.wikipedia.org/wiki/ARM_architecture

基本上你会想是这样的:

void brighten(unsigned char* src, unsigned char* dst, int numPixels, int intensity) { 
    asm volatile (
        "\t mov r3, #0\n" 
        "Lloop:\n" 
        "\t cmp r3, %2\n" 
        "\t bge Lend\n" 
        "\t ldrb r4, [%0, r3]\n" 
        "\t add r4, r4, %3\n" 
        "\t strb r4, [%1, r3]\n" 
        "\t add r3, r3, #1\n" 
        "\t b Lloop\n" 
        "Lend:\n" 
       : "=r"(src), "=r"(dst), "=r"(numPixels), "=r"(intensity) 
       : "0"(src), "1"(dst), "2"(numPixels), "3"(intensity) 
       : "cc", "r3", "r4"); 
} 

更新:

An d这是NEON版本:

void brighten_neon(unsigned char* src, unsigned char* dst, int numPixels, int intensity) { 
    asm volatile (
        "\t mov r4, #0\n" 
        "\t vdup.8 d1, %3\n" 
        "Lloop2:\n" 
        "\t cmp r4, %2\n" 
        "\t bge Lend2\n" 
        "\t vld1.8 d0, [%0]!\n" 
        "\t vqadd.s8 d0, d0, d1\n" 
        "\t vst1.8 d0, [%1]!\n" 
        "\t add r4, r4, #8\n" 
        "\t b Lloop2\n" 
        "Lend2:\n" 
        : "=r"(src), "=r"(dst), "=r"(numPixels), "=r"(intensity) 
        : "0"(src), "1"(dst), "2"(numPixels), "3"(intensity) 
        : "cc", "r4", "d1", "d0"); 
} 

所以这个NEON版本一次只能做8个。但它不检查numPixels是否可以被8整除,所以你肯定会这样做,否则事情就会出错!无论如何,这只是向您展示可以做什么的开始。注意相同数量的指令,但是一次对八个像素的数据采取行动。哦,那里也饱和了,我想你会想要。

+0

这些代码工作得很好!这对我的理解非常有帮助。非常感谢您的意见〜 – 2011-12-27 04:48:16

-2

虽然这个答案是没有直接回答你的问题,它更是关于使用汇编的与现代的编译器的一般建议。

你通常有一个很难击败关于你的C代码优化调度的编译器。当然,通过巧妙地使用关于数据如何表现的某些知识,您可能会调整它几个百分点。

其中的一个原因。这就是现代编译的代码打交道就像一个你描述,例如,当使用一些技巧循环展开,指令重新排序以避免流水线延迟和气泡等。

如果您确实想让该算法尖叫,您应该考虑重新设计算法,而不是使用C语言,以避免最糟糕的延迟。例如,与寄存器访问相比,读取和写入内存相当昂贵。

完成此操作的一种方法可能是通过使用unsigned long,一次加载4个字节的代码,然后在将这4个字节写回到一个存储操作之前,在寄存器中对此进行数学运算。

因此,要回顾一下,让你的算法工作更聪明而不是更辛苦。

+1

也许他想这样做在学习虽然练习?或者想确保NEON的矢量指令正确使用?看起来他想用像素数据来做东西,而且从矢量指令中获益无疑。例如,您可以一次添加并饱和16个像素。 – mattjgalloway 2011-12-23 11:26:55

+2

尤其是在ARM上,编译器还没有达到您想象的水平。 SIMD指令以及位字段操作的优化效果不佳,您可以通过在ARM中直接对其进行编码来获得大幅度的加速。但请注意,AppStore只接受仅使用记录的API的应用程序。不确定内联汇编程序如何影响AppStore资格。 – Etan 2011-12-23 12:38:32

+0

内联汇编,绝不会影响应用程序商店的资格。这不是使用未公开的API。内联汇编是编译器/汇编程序的一个功能,因此与框架的API无关。 – mattjgalloway 2011-12-29 10:20:09

相关问题