第三篇 ARM C 高效编程 - 除法以及求余
除法以及求余运算
/*** 结论:* 1. 大部分arm都有除法指令,但需要指定相应的编译标志,不然就会直接调用 c 库函数* 2. 指定相应的体系架构,可以生成更优的代码* compile with arm-linux-gnueabihf-gcc v8.3* flags: -O3 -mcpu=cortex-a7 -mtune=cortex-a7 -mfloat-abi=hard -mfpu=neon* 000103d8 :* 103d8: e713f110 sdiv r3, r0, r1 ; 除法指令* 103dc: e0600391 mls r0, r1, r3, r0 ; 乘减指令* 103e0: e0830000 add r0, r3, r0* 103e4: e12fff1e bx lr* flags: -O3* 00010410 :* 10410: e92d4010 push {r4, lr}* 10414: eb000089 bl 10640 <__aeabi_idivmod> ; 调用 c 库提供的除法函数,同时返回商和余数* 10418: e0800001 add r0, r0, r1* 1041c: e8bd8010 pop {r4, pc}*/ int combined_div_mod(int a, int b)
{return (a / b) + (a % b);
}
/*** 结论:* 1. 尽量将求余操作转为加法操作* compile with arm-linux-gnueabihf-gcc v8.3* flags: -O3 -mcpu=cortex-a7 -mtune=cortex-a7 -mfloat-abi=hard -mfpu=neon* 000103d8 :* 103d8: e2800001 add r0, r0, #1* 103dc: e3083889 movw r3, #34953 ; 0x8889* 103e0: e3483888 movt r3, #34952 ; 0x8888* 103e4: e3a0203c mov r2, #60 ; 0x3c* 103e8: e0831093 umull r1, r3, r3, r0 ; 无符号长乘法* 103ec: e1a032a3 lsr r3, r3, #5* 103f0: e0600392 mls r0, r2, r3, r0 ; 乘减指令* 103f4: e12fff1e bx lr* 000103f8 :* 103f8: e2800001 add r0, r0, #1* 103fc: e350003c cmp r0, #60 ; 0x3c* 10400: 23a00000 movcs r0, #0* 10404: e12fff1e bx lr*/ uint32_t counter1(uint32_t count)
{return (++count % 60);
}uint32_t counter2(uint32_t count)
{if (++count >= 60)count = 0;return (count);
}
/*** 结论:* 1. 无符号数比有符号数除法更快* 2. 除数如果为 2 的幂。将转为超快的移位操作* 3. 除数如果为常数,也可以转为移位操作,不过要多一些指令,尤其是多了一条乘法指令* 4. 其余情况就只能调用除法指令* compile with arm-linux-gnueabihf-gcc v8.3* flags: -O3 -mcpu=cortex-a7 -mtune=cortex-a7 -mfloat-abi=hard -mfpu=neon* 00010410 :* 10410: e1a00220 lsr r0, r0, #4* 10414: e12fff1e bx lr* 00010424 :* 10424: e280300f add r3, r0, #15* 10428: e3500000 cmp r0, #0* 1042c: b1a00003 movlt r0, r3* 10430: e1a00240 asr r0, r0, #4* 10434: e12fff1e bx lr* 000103e0 :* 103e0: e730f110 udiv r0, r0, r1 ; 除法指令* 103e4: e12fff1e bx lr* 000103e8 :* 103e8: e30f30f1 movw r3, #61681 ; 0xf0f1* 103ec: e34f30f0 movt r3, #61680 ; 0xf0f0* 103f0: e0803093 umull r3, r0, r3, r0 ; 长乘法指令* 103f4: e1a00220 lsr r0, r0, #4* 103f8: e12fff1e bx lr*/uint32_t div16u(uint32_t a)
{return a / 16;
}int div16s(int a)
{return a / 16;
}uint32_t div_xx_u(uint32_t a, uint32_t b)
{return a / b;
}uint32_t div17u(uint32_t a)
{return a / 17;
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
