给Arduino嵌入汇编语言,提高开方效率~

2014-02-282.6万
精华项目
AI 快速预览详细 收起
本文介绍了一种通过嵌入式汇编代码在Arduino上实现高效整数开方运算的方法。相比标准的sqrt()函数,该方法的速度提升了2.5倍。文章提供了详细的代码示例,并解释了其工作原理。对于需要大量开方运算的项目,这是一个非常实用的技术分享。


前两天在做一个软件项目,里面需要用到很多的整数开方运算,即使Mega2560,跑起来也有点累。AVR库文件里面的确提供sqrt()这个函数用于开方,但是由于其为double类型,对于整数开方,很大的程度上浪费了资源。
之后自然而然的就想到了嵌入式汇编,找了一些相关的资料,供大家参考一下:


英文的教程,讲的比较细:http://www.nongnu.org/avr-libc/user-manual/inline_asm.html
中文版教程,特别是其中的汇编语言支持章节:      http://www.chipart.cn/doc/caavrgccv.pdf
汇编代码的源头: http://members.chello.nl/j.beentjes3/Ruud/sqrt32avr.htm#Sqrt32R

最后上代码,实测速度为sqrt()的2.5倍,相当给力~~
  1. #define Sqrt32(intRes, longIn1) \
  2. asm volatile ( \
  3. "ldi   R27,0xc0 \n\t" \
  4. "clr   R26 \n\t" \
  5. "ldi   %B0,0x40 \n\t" \
  6. "sub   %A0,%A0  \n\t" \
  7. "_sq32_1%=:    brcs  _sq32_2%= \n\t" \
  8. "cp    %C1,%A0 \n\t" \
  9. "cpc   %D1,%B0 \n\t" \
  10. "brcs  _sq32_3%= \n\t" \
  11. "_sq32_2%=:    sub   %C1,%A0 \n\t" \
  12. "sbc   %D1,%B0  \n\t" \
  13. "or    %A0,R26 \n\t" \
  14. "or    %B0,R27 \n\t" \
  15. "_sq32_3%=:    lsr   R27 \n\t" \
  16. "ror   R26 \n\t" \
  17. "eor   %B0,R27 \n\t" \
  18. "eor   %A0,R26 \n\t" \
  19. "rol   %A1 \n\t" \
  20. "rol   %B1 \n\t" \
  21. "rol   %C1 \n\t" \
  22. "rol   %D1 \n\t" \
  23. "sbrs  %A1,0 \n\t" \
  24. "rjmp  _sq32_1%= \n\t" \
  25. "brcs  _sq32_4%= \n\t" \
  26. "cp    %A0,%C1 \n\t" \
  27. "cpc   %B0,%D1 \n\t" \
  28. "brcc  _sq32_5%= \n\t" \
  29. "_sq32_4%=:    sbc   %B1,R27 \n\t" \
  30. "sbc   %C1,%A0 \n\t" \
  31. "sbc   %D1,%B0 \n\t" \
  32. "inc   %A0 \n\t" \
  33. "_sq32_5%=:    lsl   %B1 \n\t" \
  34. "rol   %C1 \n\t" \
  35. "rol   %D1 \n\t" \
  36. "brcs  _sq32_6%=  \n\t" \
  37. "cp    %A0,%C1 \n\t" \
  38. "cpc   %B0,%D1 \n\t" \
  39. "_sq32_6%=:    adc   %A0,R27 \n\t" \
  40. "adc   %B0,R27 \n\t" \
  41. : \
  42. "=&r" (intRes) \
  43. : \
  44. "d" (longIn1) \
  45. : \
  46. "r26" , "r27" \
  47. )
  48. int result;
  49. unsigned long num;
  50. int i;
  51. unsigned long timer;
  52. void setup() {
  53.   srandom(analogRead(0));
  54.   Serial.begin(115200);
  55. }
  56. void loop() {
  57.   num=random();
  58.   timer=millis();
  59.   for (i=0; i<1000; i++) {
  60. //      result=sqrt(num);
  61.   Sqrt32(result, num);
  62.   }
  63.   timer=millis()-timer;
  64.   Serial.println(timer);
  65. }
复制代码





创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(9)
Grey
Grey
汇编还能这么玩? 好帖,收下了
Youyou
Youyou回复Grey
汇编玩的好了,程序可以写的很牛逼。是不是很怀念当时学51单片机时的汇编?
微笑的rockets
微笑的rockets
和机器说话很累。
但机器能听懂人说话,干活很快
Youyou
Youyou
看了楼主的帖子,想到刚刚接触51单片机时学的汇编语言,瞬间又激发起了对汇编的兴趣。
在需要高效率的场合,确实需要汇编啊!
phoebe.wang40
phoebe.wang40
想当刚接触单片机,学汇编,真是头疼啊,感谢楼主分享:lol
lauren
lauren
我了个去的神贴啊。。。大师请教运算效率提高多少?
Angleo
Angleo
作者
回复lauren

哥们儿~~
给我回去仔细看贴:curse:[table]
[tr][/tr]
[/table]
Holiday
Holiday
Uno上运行,54对18,好吊:lol:lol:lol
nemon
nemon
\t 是做什么用的?
Angleo
Angleo
作者
回复nemon
这个是“制表符”,内嵌汇编的标准格式~~
lisper
lisper
AT&T格式的啊
Holiday
Holiday
这么好的帖子,话说右斜杠的作用是什么。。。
Angleo
Angleo
作者
回复Youyou
对的,连注释都不行。。。这点很郁闷。。。
但是现在内联函数基本能够和宏定义的效率相当,但是碰到汇编就只能用宏了~
Youyou
Youyou回复Angleo
是不是叫续行符?
貌似要求很严格的,后面连空格都不能有。
共3条回复,已加载2条,点击查看更多共3条回复,已加载全部
- 没有更多了 -