除法以及求余运算
/**
* 结论:
*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:e713f110sdivr3, r0, r1;
除法指令
* 103dc:e0600391mlsr0, r1, r3, r0 ;
乘减指令
* 103e0:e0830000addr0, r3, r0
* 103e4:e12fff1ebxlr
* flags: -O3
* 00010410 :
* 10410:e92d4010push{r4, lr}
* 10414:eb000089bl10640 <__aeabi_idivmod> ;
调用 c 库提供的除法函数,同时返回商和余数
* 10418:e0800001addr0, r0, r1
* 1041c:e8bd8010pop{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:e2800001addr0, r0, #1
* 103dc:e3083889movwr3, #34953;
0x8889
* 103e0:e3483888movtr3, #34952;
0x8888
* 103e4:e3a0203cmovr2, #60 ;
0x3c
* 103e8:e0831093umullr1, r3, r3, r0 ;
无符号长乘法
* 103ec:e1a032a3lsrr3, r3, #5
* 103f0:e0600392mlsr0, r2, r3, r0 ;
乘减指令
* 103f4:e12fff1ebxlr
* 000103f8 :
* 103f8:e2800001addr0, r0, #1
* 103fc:e350003ccmpr0, #60 ;
0x3c
* 10400:23a00000movcsr0, #0
* 10404:e12fff1ebxlr
*/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:e1a00220lsrr0, r0, #4
* 10414:e12fff1ebxlr
* 00010424 :
* 10424:e280300faddr3, r0, #15
* 10428:e3500000cmpr0, #0
* 1042c:b1a00003movltr0, r3
* 10430:e1a00240asrr0, r0, #4
* 10434:e12fff1ebxlr
* 000103e0 :
* 103e0:e730f110udivr0, r0, r1 ;
除法指令
* 103e4:e12fff1ebxlr
* 000103e8 :
* 103e8:e30f30f1movwr3, #61681;
0xf0f1
* 103ec:e34f30f0movtr3, #61680;
0xf0f0
* 103f0:e0803093umullr3, r0, r3, r0;
长乘法指令
* 103f4:e1a00220lsrr0, r0, #4
* 103f8:e12fff1ebxlr
*/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;
}
推荐阅读
- ARM-高效C编程|第四篇 ARM C 高效编程 - 多条件判断
- 单片机系列|嵌入式STM32开发中关键字_IO
- 单片机系列|第十二届省赛嵌入式设计与开发《停车计费系统》
- PTA乙级 1013数素数(20分)C语言
- lm哈希认证算法|lm哈希认证算法 c语言,LM算法的推导过程
- 简单代码|OI 守望者的逃离 c语言简洁注释 逻辑清晰
- C语言|【C语言】字符函数&字符串函数&内存函数(上)[进阶篇_复习专用]
- C语言|【C语言】字符函数&字符串函数&内存函数(下)[进阶篇_复习专用]
- 寒假刷题特辑|【第四章】 C语言之牛客网刷题笔记 【点进来保证让知识充实你一整天】