gcc中的内联汇编

我对一些内联汇编代码有些麻烦。 我知道应该做些什么,但我想念“怎么样”!

我有这个“几乎”工作的校验和function:

static unsigned long cksum_unroll( unsigned short **w, int *mlen) { int len; unsigned short *w0; unsigned long sum=0; len = *mlen; w0 = *w; while( len >= 8) { asm volatile ( "ldmia %[w0]!, {v1, v2}\n\t" "adds %[sum], %[sum], v1\n\t" "adcs %[sum], %[sum], v2\n\t" "adcs %[sum], %[sum], #0" : [sum] "+r" (sum) : [w0] "r" (w0) ); len -= 8; } *mlen = len; *w = w0; return (sum); } 

我相信,我的问题在于:“[sum]”+ r“(sum):[w0]”r“(w0) ”在第一条assembly线上, w0ldmia正确处理(当行是执行后,数据在r4,r5和w0递增)。 但是w0的递增值没有保存在某处,当代码循环时,w0的原始值再次被加载(参见下面的汇编代码)。 我的猜测是我应该将w0的值存储在“:[sum]”+ r“(sum):[w0]”r“(w0)”但我不知道如何……

这是函数的内联汇编部分的反汇编代码:

注意 :

 len is stored at r11, #-16 w0 is stored at r11, #-20 sum is stored at r11, #-24 

编译,以下代码:

 asm volatile ( "ldmia %[w0]!, {v1, v2}\n\t" "adds %[sum], %[sum], v1\n\t" "adcs %[sum], %[sum], v2\n\t" "adcs %[sum], %[sum], #0" : [sum] "+r" (sum) : [w0] "r" (w0) ); len -= 8; 

生成:

 00031910: ldr r3, [r11, #-20] 00031914: ldr r2, [r11, #-24] 00031918: mov r4, r2 0003191c: ldm r3!, {r4, r5} 00031920: adds r4, r4, r4 00031924: adcs r4, r4, r5 00031928: adcs r4, r4, #0 0003192c: str r4, [r11, #-24] 00031930: ldr r3, [r11, #-16] 00031934: sub r3, r3, #8 00031938: str r3, [r11, #-16] 

正如您所看到的,我想在第31928行和第3192c行之间添加类似“str r3,[r11,# – 20]”的内容,因为当程序循环到第31910行时,r3加载了初始值r3 .. 。

我认为对于堆栈溢出社区的内联汇编专家来说这是一个简单的方法!

顺便说一下,我正在研究ARM7TDMI处理器(但这可能与这个问题无关……)

提前致谢!

编辑:

为了validation我的想法,我测试了以下内容:

 asm volatile ( "ldmia %[w0]!, {v1, v2}\n\t" "adds %[sum], %[sum], v1\n\t" "adcs %[sum], %[sum], v2\n\t" "adcs %[sum], %[sum], #0\n\t" "str %[w0], [r11, #-20]" : [sum] "+r" (sum) : [w0] "r" (w0) ); 

这很有效。 也许这是解决方案,但是如果我修改函数,我可以用什么来代替“r11,#20”?

问题似乎是你指定w0作为INPUT操作数,当它实际应该是一个读写OUTPUT操作数,如sum 。 此外,当您使用这些寄存器时,您需要指定它为clobbers v1和v2(否则,gcc可能会将一些其他var放入这些reg并期望它们被保留。)

所以你应该:

 asm volatile ( "ldmia %[w0]!, {v1, v2}\n\t" "adds %[sum], %[sum], v1\n\t" "adcs %[sum], %[sum], v2\n\t" "adcs %[sum], %[sum], #0" : [sum] "+r" (sum) , [w0] "+r" (w0) : : "v1", "v2" ); 

也就是说,两个读写输入/输出操作数,没有专门的输入操作数,以及两个寄存器clobbers