查看: 3747|回复: 7

51中获得长整型高字节的方法的效率对比

[复制链接]
  • TA的每日心情
    无聊
    2016-12-20 15:08
  • 签到天数: 510 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2013-3-4 18:21:20 | 显示全部楼层 |阅读模式
    分享到:
      前两周刚搞好一个labview的作品,这几天又开始忙做单片机课设,没想到开学开始这么忙。不过今天在做课设过程中有所收获,所以特地花点时间和大家分享分享。
      因为课设要做的涉及到SD卡,所以函数参数中长整型用到比较多。51是8位,不知道处理32位数据上效率怎么样,于是今天特地做了下测试,顺便复习下汇编语言。想要知道一条C代码执行效率怎么样,还是得用反汇编窗口看看汇编后的代码是什么。说了这么多好像大家都不知道我在说些什么。额,好像确实没有逻辑。我还是另起一段,有条理的讲述下问题吧。
      我用51实现SPI模式读取SD卡,因为SD卡的函数参数是32位长整型,而SPI以字节为单位传输,于是就涉及到如何获得长整型的各个字节。我目前已知的方法有两种,一种是用移位来获得高位字节,如:SDWriteByte((uint8)(arg >> 24));还有一种是指针的方法,如:SDWriteByte(((unsigned char *)&arg)[0]);以上两句代码实现的是一样的功能(arg是32位无符号长整型,这里其值为0x00000095),但是哪种的效率高呢?我们可以打开keil的反汇编窗口看看汇编后的代码就知道了。
      对于第一种方法,汇编代码如:
    1.    253:         SDWriteByte((uint8)(arg >> 24));
    2. C:0x26A8    7818     MOV      R0,#0x18
    3. C:0x26AA    1228A8   LCALL    C:28A8
    复制代码
    这里调用了地址C:28A8的函数,所以我们转到C:28A8看一下代码:
    1. C:0x28A8    900289   MOV      DPTR,#0x0289
    2. C:0x28AB    E0       MOVX     A,@DPTR
    3. C:0x28AC    FC       MOV      R4,A
    4. C:0x28AD    A3       INC      DPTR
    5. C:0x28AE    E0       MOVX     A,@DPTR
    6. C:0x28AF    FD       MOV      R5,A
    7. C:0x28B0    A3       INC      DPTR
    8. C:0x28B1    E0       MOVX     A,@DPTR
    9. C:0x28B2    FE       MOV      R6,A
    10. C:0x28B3    A3       INC      DPTR
    11. C:0x28B4    E0       MOVX     A,@DPTR
    12. C:0x28B5    FF       MOV      R7,A
    13. C:0x28B6    121118   LCALL    C?ULSHR(C:1118)
    14.   ......(这里是SDWriteByte函数)
    复制代码
    这是0x28A8处的代码,以上部分是参数传递部分,后面省略的是SDWriteByte函数。可以看到前面 12句是将arg复制到寄存器中。(可以看到arg在内存中的地址正是0x0289)
    未命名.jpg
      那最后一句呢?老实说我汇编很烂,看到C?ULSHR还以为那问号是乱码呢?不过等看完代码后终于知道这里调用的是一个函数:无符号长整型右移函数(ULSHR),在C:1118可以看到函数代码:
    1.                  C?ULSHR:
    2. C:0x1118    E8       MOV      A,R0
    3. C:0x1119    600F     JZ       C:112A
    4. C:0x111B    EC       MOV      A,R4
    5. C:0x111C    C3       CLR      C
    6. C:0x111D    13       RRC      A
    7. C:0x111E    FC       MOV      R4,A
    8. C:0x111F    ED       MOV      A,R5
    9. C:0x1120    13       RRC      A
    10. C:0x1121    FD       MOV      R5,A
    11. C:0x1122    EE       MOV      A,R6
    12. C:0x1123    13       RRC      A
    13. C:0x1124    FE       MOV      R6,A
    14. C:0x1125    EF       MOV      A,R7
    15. C:0x1126    13       RRC      A
    16. C:0x1127    FF       MOV      R7,A
    17. C:0x1128    D8F1     DJNZ     R0,C:111B
    18. C:0x112A    22       RET
    复制代码
    17句代码实现了长整型的右移位,老实说,平时没用汇编,看懂了上面的代码后才发现汇编是多么精妙的东西,简单,却强大。
      不过,汇编好归好,要是评估起这个移位传参的方法好像效率不是很高哦。一个右移函数的循环部分有14条指令,像这里移位24,算起来要执行300多条指令才能搞定。一句看起来简单的arg>>24竟然要执行这么多指令来完成,那样速率一定有很大影响。
       我们再来看第二种方法,汇编代码如下:
    1. 254:         SDWriteByte(((unsigned char *)&arg)[0]);
    2. C:0x26A8    900289   MOV      DPTR,#0x0289
    3. C:0x26AB    E0       MOVX     A,@DPTR
    4. C:0x26AC    FF       MOV      R7,A
    5. C:0x26AD    1228AB   LCALL    SDWriteByte(C:28AB)
    复制代码
    可以看到这种方法代码很少,只用了3条指令就完成了参数的传递 ,效率之高就不用说了。
      综上,我个人认为在51在进行长移位并不是一个效率很高的方法,用指针的方法应该更好。不知道大家有什么看法,或者有其他更好的方法可以分享下。


    回复

    使用道具 举报

  • TA的每日心情
    慵懒
    2024-5-20 16:09
  • 签到天数: 665 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2013-3-4 19:25:08 | 显示全部楼层
    这应该还要考虑在不同IDE下的情况
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2016-12-20 15:08
  • 签到天数: 510 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2013-3-4 19:34:18 | 显示全部楼层
    sagitattoo 发表于 2013-3-4 19:25
    这应该还要考虑在不同IDE下的情况

    比较常见的是keil,不知道其他IDE能汇编出效率更高的代码吗
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2023-1-28 16:20
  • 签到天数: 980 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2013-3-4 21:08:11 | 显示全部楼层
    效率bu怎么样
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2016-12-20 15:08
  • 签到天数: 510 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2013-3-4 22:13:12 | 显示全部楼层
    mcp2013 发表于 2013-3-4 21:08
    效率bu怎么样

    ?什么意思?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2023-1-28 16:20
  • 签到天数: 980 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2013-3-4 23:12:03 | 显示全部楼层
    keil里面有一个编译选项 可以调节编译效率等级的
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2014-5-28 19:02
  • 签到天数: 15 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    发表于 2013-3-5 19:49:31 | 显示全部楼层
    恩恩~这个研究很不错~
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2016-12-20 15:08
  • 签到天数: 510 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2013-3-8 19:01:10 | 显示全部楼层
    mcp2013 发表于 2013-3-4 23:12
    keil里面有一个编译选项 可以调节编译效率等级的

    我的是等级8时编译的,应该优化度比较高了
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-11-15 08:50 , Processed in 0.184759 second(s), 29 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.