2012-08-16 148 views
4
for (int i = 0; i < 10000; i++) 
    a[i] = b[i] + c[i] 

此高级语言的ARM汇编是什么样的?ARM汇编回路

编辑: 我也假设A的基地址中R8,B的基 地址是在R 9和C的基地址是在R10 和A,B,C均为INT阵列

非常感谢

我尝试:

MOV R0, #0 ; Init r0 (i = 0) 

Loop: 

     a[i] = b[i] + c[i] //How to fix this? 

     ADD R0, R0, #1 ;Increment it 

     CMP R0, #1000 ;Check the limit 

     BLE Loop ;Loop if not finished 
+0

到目前为止您尝试过什么? – 2012-08-16 02:13:55

+0

你可能想澄清你在这里问的问题--ARM风格的Assembly和Android编程是两个完全不同的东西; Android是像Java这样的VM风格环境;你不能使用Assembly,因为代码是由运行时解释的,而不是直接在处理器上运行。 – 2012-08-16 02:20:47

+0

关于你的编辑;你在什么地方尝试了ASM;你使用什么软件/设备? – 2012-08-16 02:23:51

回答

6

假设这个高级语言没有任何与C冲突的东西,你可以使用arm C编译器从你的代码段中创建汇编代码。例如,如果您在在test.c的下面,

void test() { 
     register int i asm("r0"); 
     register int *a asm("r8"); 
     register int *b asm("r9"); 
     register int *c asm("r10"); 

     for (i = 0; i < 10000; i++) { 
       a[i] = b[i] + c[i]; 
     } 
} 

可以运行

arm-linux-androideabi-gcc -O0 -S test.c 

创建test.s文件,其中将包含汇编代码为你的测试功能,以及一些额外的东西。你可以看到你的循环如何被编译到下面的程序集中。

<snipped> 
.L3: 
     mov  r2, r8 
     mov  r3, r0 
     mov  r3, r3, asl #2 
     add  r3, r2, r3 
     mov  r1, r9 
     mov  r2, r0 
     mov  r2, r2, asl #2 
     add  r2, r1, r2 
     ldr  r1, [r2, #0] 
     mov  ip, sl 
     mov  r2, r0 
     mov  r2, r2, asl #2 
     add  r2, ip, r2 
     ldr  r2, [r2, #0] 
     add  r2, r1, r2 
     str  r2, [r3, #0] 
     mov  r3, r0 
     add  r3, r3, #1 
     mov  r0, r3 
.L2: 
     mov  r2, r0 
     ldr  r3, .L5 
     cmp  r2, r3 
     ble  .L3 
     sub  sp, fp, #12 
     ldmfd sp!, {r8, r9, sl, fp} 
     bx  lr 
<snipped> 

现在用这个方法的问题是信任编译器生成你的研究的最佳代码,这可能不是总是如此,但你会得到快速解答您的问题,如上述,而不是等待人:)

- 额外 -

GCC允许你把变量放到特定的寄存器,见related documentation

您可以获取arm指令备忘单here

GCC的较新版本创建更好的代码,如预期的那样。上面的剪切版本是由4.4.3版生成的,我可以确认Linaro的4.7.1版本证明了我的说法。所以,如果你采用我的方法,可以使用最新的工具链。

4

http://www.peter-cockerell.net/aalp/html/ch-5.html

;Print characters 32..126 using a FOR loop-type construct 

;R0 holds the character 
MOV R0, #32 ;Init the character 
.loop 
SWI WriteC ;Print it 
ADD R0, R0, #1 ;Increment it 
CMP R0, #126 ;Check the limit 
BLE loop ;Loop if not finished 
; 
+1

这里需要盐的剂量;这个来源来自于1987年编写的一本书。 theres很可能在2012年不适用于基于ARM的Android设备。 – 2012-08-16 02:22:35

1
for (int i = 0; i < 10000; i++) 
    a[i] = b[i] + c[i] 



mov r0,#0x2700 
orr r0,#0x0010 
top: 
ldr r1,[r9],#4 
ldr r2,[r10],#4 
add r1,r1,r2 
str r1,[r8],#4 
subs r0,#1 
bne top 
1

要建立在@alpera的答案上 - 您还可以展开循环,以便一次执行4个操作 - 尽管您是否获得了性能优势取决于内存访问还是分支周围的管道停顿是更大的影响

mov r11,#0x2700 
orr r11,#0x0010 
top: 
ldmia r9!, {r0-r3} 
ldmia r10!, {r4-r7} 
add r0,r0,r4 
add r1,r1,r5 
add r2,r2,r6 
add r3,r3,r7 
stmia r8!, {r0-r3} 
subs r11,#4 
bne top 

如果你有NEON单元得心应手,我们可以做到这一点这种方式 - 在这种情况下,将并行的加载,存储并增加了 - 这实际上减少了问题,在执行循环的两次迭代5个指令一旦。

默认情况下,AC编译器不会生成这样严密的代码(或者为NEON并行),因为它必须假定用于读写的缓冲区(r8,r10和r11)可能会重叠 - 因此可能会写入r8立即通过r9或r10在循环的下一次迭代中读取。您可以使用restrict(在C++中为__restrict)修饰符来告诉编译器,情况并非如此。