切换到宽版
爱科技/爱创意/爱折腾;电子/数码爱好者的家!欢迎访问新版数码之家网站
  • 4846阅读
  • 10回复

[C51]讨论,位移运算好还是除法好 [复制链接]

上一主题 下一主题
离线11211
 

发帖
2055
M币
1919
专家
23
粉丝
98
只看楼主 倒序阅读 我要置顶 楼主  发表于: 2013-07-16
要把一个无符号长整形数据保存到单片机数据Flash EPROM中,需要将其拆分成4个字节进行保存
但是发现位移操作编译后的字节数要比除法运算要多很多个字节,如果不考虑字节消耗量,是选用位移运算好还是除法呢?
        m1=jishu_n;m1=m1>>24;          irEEP[2]=m1;
        m1=jishu_n;m1=m1<<8;m1=m1>>24; irEEP[3]=m1;
        m1=jishu_n;m1=m1<<16;m1=m1>>24;irEEP[4]=m1;
        m1=jishu_n;m1=m1<<24;m1=m1>>24;irEEP[5]=m1;
编译后的代码Program Size: data=45.1 xdata=0 code=6581。

        irEEP[2]=jishu_n/0x1000000;
        irEEP[3]=jishu_n%0x1000000/0x10000;
        irEEP[4]=jishu_n%0x10000/0x100;
        irEEP[5]=jishu_n%0x100;
编译后的代码Program Size: data=45.1 xdata=0 code=6442。
离线fang3

发帖
4445
M币
22967
专家
44
粉丝
211
只看该作者 1楼 发表于: 2013-07-16
反汇编比较一下知道了
本帖最近打赏记录:共1条打赏M币+5
离线wb.chn

发帖
503
M币
3854
专家
2
粉丝
18
只看该作者 2楼 发表于: 2013-07-16
联合体最快,不需要通过运算:

typedef union _unType_
{
    long i;
    char str[4];
} UNTYPE;

UNTYPE unData = {0};

unData.i = jishu_n;
irEEP[2] = unData.str[0];
irEEP[3] = unData.str[1];
irEEP[4] = unData.str[2];
irEEP[5] = unData.str[3];
本帖最近打赏记录:共2条打赏M币+18
离线wb.chn

发帖
503
M币
3854
专家
2
粉丝
18
只看该作者 3楼 发表于: 2013-07-16
或是通过指针类型强转:
char *pstr = (char *)&jishu_n;
irEEP[2] = pstr[0];
irEEP[3] = pstr[1];
irEEP[4] = pstr[2];
irEEP[5] = pstr[3];
本帖最近打赏记录:共1条打赏M币+6
离线wb.chn

发帖
503
M币
3854
专家
2
粉丝
18
只看该作者 4楼 发表于: 2013-07-16
上面的代码可以直接用,我没用keil新建工程看code段多少,直接用gcc编译过,lz试下给个验证结果吧。
可以肯定的是执行速度必然比你上面计算的方法要快,效率至少是10倍以上。
离线cmheia

发帖
11646
M币
6479
专家
9
粉丝
117
只看该作者 5楼 发表于: 2013-07-16
%%%不是除法,不是蜗速能够描述;位运算速度很快的;联合体跟指针没什么差别,巨快。
不过话说有的编译器开优化能把除法“/”编译成位运算的汇编……
本帖最近打赏记录:共1条打赏M币+5
离线jkj

发帖
1320
M币
6765
专家
7
粉丝
39
只看该作者 6楼 发表于: 2013-07-17
1. 对于楼主的这种需求,用联合体、指针都是比较好的方法,执行速度快、占用空间小。上面已经有热心人给出了示例代码。
2. 用移位运算时,因为51是8位机,对于大于8位数据的移位,会比较麻烦,效率低。而且楼主的移位中使用了m1这个中间变量,可能进一步降低效率。
3. 移位和除法的关系,特殊的除数可以用移位表示,比如除以2可以表示为右移一位,除以8可以表示为右移3位等等。

代码编译/优化/效率有一些通用原则,但还有一些方面是跟具体编译器有关的,最好看下生成的汇编代码(因为是源码编译生成的,不需要反汇编),以keil c51来说,可以在编译选项中设置生成lst文件来查看。
本帖最近打赏记录:共1条打赏M币+8
离线devcang

发帖
18104
M币
9199
专家
20
粉丝
97
只看该作者 7楼 发表于: 2013-07-17
        m1=jishu_n;m1=m1>>24;          irEEP[2]=m1;
        m1=jishu_n;m1=m1<<8;m1=m1>>24; irEEP[3]=m1;
        m1=jishu_n;m1=m1<<16;m1=m1>>24;irEEP[4]=m1;
        m1=jishu_n;m1=m1<<24;m1=m1>>24;irEEP[5]=m1;


好像是这样写的

irEEP[5]=jishu_n & 0xff;
irEEP[4]=(jishu_n >>8) & 0xff;
irEEP[3]=(jishu_n >>16) & 0xff;
irEEP[2]=(jishu_n >>24) & 0xff;


当然,指针还是最好的。较低级的语言,这些方面才是优势。


同一段代码,
我修改过的
Program Size: data=65.4 xdata=0 code=4217

LZ 的位
Program Size: data=69.4 xdata=0 code=4363

LZ 的除法
Program Size: data=65.4 xdata=0 code=4531




离线fang3

发帖
4445
M币
22967
专家
44
粉丝
211
只看该作者 8楼 发表于: 2013-07-17
用共同体比指针更好,我试过了

还有
irEEP[5]=jishu_n & 0xff;
irEEP[4]=(jishu_n >>8) & 0xff;
irEEP[3]=(jishu_n >>16) & 0xff;
irEEP[2]=(jishu_n >>24) & 0xff;

其实可以这样的

irEEP[5]=jishu_n ;
irEEP[4]=jishu_n >>8 ;
irEEP[3]=jishu_n >>16;
irEEP[2]=jishu_n >>24;
本帖最近打赏记录:共1条打赏M币+8
离线jkj

发帖
1320
M币
6765
专家
7
粉丝
39
只看该作者 9楼 发表于: 2013-07-18
引用第8楼fang3于2013-07-17 23:49发表的  :
用共同体比指针更好,我试过了
还有
irEEP[5]=jishu_n & 0xff;
irEEP[4]=(jishu_n >>8) & 0xff;
.......


对的,因为irEEP[5]等本身就是8位的,向其赋值时编译器会自动把jishu_n和jishu_n>>8等转换成8位的,且只保留最低8位,其它的舍弃,所以无需再&0xFF。
本帖最近打赏记录:共1条打赏M币+8
快速回复
限80 字节
如果您提交过一次失败了,可以用”恢复数据”来恢复帖子内容
 
上一个 下一个