登录 免费注册 首页 | 行业黑名单 | 帮助
维库电子市场网
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统
驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe

请问下面的代码如何优化

作者:hswqs 栏目:单片机
请问下面的代码如何优化
这是TCP/IP协议中的校验和计算代码,使用中反复调用,KEIL C51编译后的汇编指令一大堆,谁能帮忙做个优化,汇编也行,不甚感激!

unsigned int CHECKSUM(unsigned int xdata *check,unsigned int length)
{
    //计算校验和
    unsigned LONG data sum =0;
    unsigned int data i;
    for (i=0;i<(length)/2;i++)
    {
        sum+=*check++;
    }
    if(length&0x01)//表示长度为单数
    {
        sum=sum+((*check)&0xff00);
    }
    sum=(sum&0xffff)+((sum>>16)&0xffff);//高16位和低16位相加
    if(sum&0xffff0000)
    {//表示有进位
        sum++;
    }
    return ( (unsigned int)(~((sum)&0xffff))  );
}

2楼: >>参与讨论
hswqs
上面程序KEIL编译后的代码如下
   714: unsigned int CHECKSUM(unsigned int xdata *check,unsigned int length)
C:0x3C01    903778   MOV      DPTR,#0x3778
C:0x3C04    EE       MOV      A,R6
C:0x3C05    F0       MOVX     @DPTR,A
C:0x3C06    A3       INC      DPTR
C:0x3C07    EF       MOV      A,R7
C:0x3C08    F0       MOVX     @DPTR,A
C:0x3C09    AB05     MOV      R3,0x05
C:0x3C0B    AA04     MOV      R2,0x04
   715: {
   716:         //&frac14;&AElig;&Euml;&atilde;&ETH;&pound;&Ntilde;é&ordm;&Iacute;
   717:         unsigned LONG data sum =0;
   718:         unsigned int data i;
C:0x3C0D    E4       CLR      A
C:0x3C0E    F515     MOV      0x15,A
C:0x3C10    F514     MOV      0x14,A
C:0x3C12    F513     MOV      0x13,A
C:0x3C14    F512     MOV      0x12,A
   719:         for (i=0;i<(length)/2;i++)
C:0x3C16    F516     MOV      0x16,A
C:0x3C18    F517     MOV      0x17,A
C:0x3C1A    EA       MOV      A,R2
C:0x3C1B    C3       CLR      C
C:0x3C1C    13       RRC      A
C:0x3C1D    FE       MOV      R6,A
C:0x3C1E    EB       MOV      A,R3
C:0x3C1F    13       RRC      A
C:0x3C20    FF       MOV      R7,A
C:0x3C21    C3       CLR      C
C:0x3C22    E517     MOV      A,0x17
C:0x3C24    9F       SUBB     A,R7
C:0x3C25    E516     MOV      A,0x16
C:0x3C27    9E       SUBB     A,R6
C:0x3C28    5035     JNC      C:3C5F
   720:         {
   721:                 sum+=*check++;
C:0x3C2A    903778   MOV      DPTR,#0x3778
C:0x3C2D    E4       CLR      A
C:0x3C2E    75F002   MOV      B(0xF0),#0x02
C:0x3C31    122D7B   LCALL    C?ILDIX(C:2D7B)
C:0x3C34    85F082   MOV      DPL(0x82),B(0xF0)
C:0x3C37    F583     MOV      DPH(0x83),A
C:0x3C39    E0       MOVX     A,@DPTR
C:0x3C3A    FE       MOV      R6,A
C:0x3C3B    A3       INC      DPTR
C:0x3C3C    E0       MOVX     A,@DPTR
C:0x3C3D    FF       MOV      R7,A
C:0x3C3E    E4       CLR      A
C:0x3C3F    FC       MOV      R4,A
C:0x3C40    FD       MOV      R5,A
C:0x3C41    E515     MOV      A,0x15
C:0x3C43    2F       ADD      A,R7
C:0x3C44    F515     MOV      0x15,A
C:0x3C46    E514     MOV      A,0x14
C:0x3C48    3E       ADDC     A,R6
C:0x3C49    F514     MOV      0x14,A
C:0x3C4B    ED       MOV      A,R5
C:0x3C4C    3513     ADDC     A,0x13
C:0x3C4E    F513     MOV      0x13,A
C:0x3C50    EC       MOV      A,R4
C:0x3C51    3512     ADDC     A,0x12
C:0x3C53    F512     MOV      0x12,A
   722:         }
C:0x3C55    0517     INC      0x17
C:0x3C57    E517     MOV      A,0x17
C:0x3C59    70BF     JNZ      C:3C1A
C:0x3C5B    0516     INC      0x16
C:0x3C5D    80BB     SJMP     C:3C1A
   723:         if(length&0x01
3楼: >>参与讨论
hswqs
这段是循环体的代码,时间重点消耗区,如何改进?
for (i=0;i<(length)/2;i++)
C:0x3C16    F516     MOV      0x16,A
C:0x3C18    F517     MOV      0x17,A
C:0x3C1A    EA       MOV      A,R2
C:0x3C1B    C3       CLR      C
C:0x3C1C    13       RRC      A
C:0x3C1D    FE       MOV      R6,A
C:0x3C1E    EB       MOV      A,R3
C:0x3C1F    13       RRC      A
C:0x3C20    FF       MOV      R7,A
C:0x3C21    C3       CLR      C
C:0x3C22    E517     MOV      A,0x17
C:0x3C24    9F       SUBB     A,R7
C:0x3C25    E516     MOV      A,0x16
C:0x3C27    9E       SUBB     A,R6
C:0x3C28    5035     JNC      C:3C5F
   720:         {
   721:                 sum+=*check++;
C:0x3C2A    903778   MOV      DPTR,#0x3778
C:0x3C2D    E4       CLR      A
C:0x3C2E    75F002   MOV      B(0xF0),#0x02
C:0x3C31    122D7B   LCALL    C?ILDIX(C:2D7B)
C:0x3C34    85F082   MOV      DPL(0x82),B(0xF0)
C:0x3C37    F583     MOV      DPH(0x83),A
C:0x3C39    E0       MOVX     A,@DPTR
C:0x3C3A    FE       MOV      R6,A
C:0x3C3B    A3       INC      DPTR
C:0x3C3C    E0       MOVX     A,@DPTR
C:0x3C3D    FF       MOV      R7,A
C:0x3C3E    E4       CLR      A
C:0x3C3F    FC       MOV      R4,A
C:0x3C40    FD       MOV      R5,A
C:0x3C41    E515     MOV      A,0x15
C:0x3C43    2F       ADD      A,R7
C:0x3C44    F515     MOV      0x15,A
C:0x3C46    E514     MOV      A,0x14
C:0x3C48    3E       ADDC     A,R6
C:0x3C49    F514     MOV      0x14,A
C:0x3C4B    ED       MOV      A,R5
C:0x3C4C    3513     ADDC     A,0x13
C:0x3C4E    F513     MOV      0x13,A
C:0x3C50    EC       MOV      A,R4
C:0x3C51    3512     ADDC     A,0x12
C:0x3C53    F512     MOV      0x12,A
   722:         }
C:0x3C55    0517     INC      0x17
C:0x3C57    E517     MOV      A,0x17
C:0x3C59    70BF     JNZ      C:3C1A
C:0x3C5B    0516     INC      0x16
C:0x3C5D    80BB     SJMP     C:3C1A


4楼: >>参与讨论
农民讲习所
sam改用联合
 
5楼: >>参与讨论
农民讲习所
length/2用变量代替
 
6楼: >>参与讨论
农民讲习所
unsigned LONG data sum 中data描述去掉
 
7楼: >>参与讨论
hswqs
所长可否帮忙稍作改动贴出来,上面说的不能全理解
 
8楼: >>参与讨论
xwj
8位机不要用32位加法,改成16位
 
9楼: >>参与讨论
xwj
真要优化建议用汇编重新写过,要注意进位哦
 
10楼: >>参与讨论
hswqs
是否如下所示,具体计算应该怎么写?
union crc
{
    unsigned LONG dwords;
    struct {unsigned int high;unsigned int low;}words;
    struct {unsigned CHAR byte3;unsigned CHAR byte2;unsigned CHAR byte1;unsigned CHAR byte0;}bytes;
};

crc sum;
unsigned int CHECKSUM(unsigned int xdata *check,unsigned int length)
{
    //计算校验和
................
}


11楼: >>参与讨论
hswqs
xwj,能用汇编优化当然最好,可惜偶功力不足啊
 
12楼: >>参与讨论
农民讲习所

union VarStruct{
    unsigned LONG mLong;
    unsigned int mInt[2];
    unsigned CHAR mChar[4];
};

unsigned int CHECKSUM(unsigned int xdata *check,unsigned int length)
{
    //计算校验和
    union VarStruct sum;
    unsigned int i;
    
    sum.mLong = 0;
    
    i = length/2;
    while( i-- )
    {
        sum.mLong += *check++;
    }
    
    if(length&0x01)//表示长度为单数
    {
        sum.mLong += (unsigned CHAR)(*check);
    }
    
    sum.mLong = sum.mInt[0] + sum.mInt[1];//高16位和低16位相加
    if(sum.mChar[1] )                     //51是高位在前。
    {//表示有进位
        sum.mInt[1] ++;
    }
    return sum.mInt[1];
}


* - 本贴最后修改时间:2006-12-27 15:27:54 修改者:农民讲习所

13楼: >>参与讨论
tj_zhaozq
我在楼上的基础上再来优化一下
    如果length可以最大小于512的话
unsigned CHAR i;
i = (unsigned CHAR)(length/2);
    do
    {
        sum.mLong += *check++;
    }while(--i);

这个方面很有效果;


* - 本贴最后修改时间:2006-12-30 16:32:36 修改者:tj_zhaozq

14楼: >>参与讨论
sharks
用自动产生CRC的网络芯片,如CP2200
 
15楼: >>参与讨论
xwj
27号就试好了,用汇编可以快3倍
看到没人关注我也就懒得发了

所长的代码有错误,结果不对哦

//这是TCP/IP协议中的校验和计算代码,使用中反复调用,KEIL C51编译后的汇编指令一大堆,
//谁能帮忙做个优化,汇编也行,不甚感激!

extern unsigned int CHECKSUM(unsigned int xdata *check,unsigned int length);
extern unsigned int CHECKSUMx(unsigned int xdata *check,unsigned int length);

/********************************************/
unsigned int CHECKSUM1(unsigned int xdata *check,unsigned int length)
{
    //计算校验和
    unsigned LONG data sum =0;
    unsigned int data i;
    for (i=0;i<(length)/2;i++)
    {
        sum+=*check++;
    }
    if(length&0x01)//表示长度为单数
    {
        sum=sum+((*check)&0xff00);
    }
    sum=(sum&0xffff)+((sum>>16)&0xffff);//高16位和低16位相加
    if(sum&0xffff0000)
    {//表示有进位
        sum++;
    }
    return ( (unsigned int)(~((sum)&0xffff))  );
}

/********************************************/
union Varstruct{
    unsigned LONG mLONG;
    unsigned int mInt[2];
    unsigned CHAR mCHAR[4];
};

unsigned int CHECKSUM2(unsigned int xdata *check,unsigned int length)
{
    //计算校验和
    union Varstruct sum;
    unsigned int i;
    
    sum.mLONG = 0;
    
    i = length/2;
    do
    {
        sum.mLONG += *check++;
    }
    while( --i );
    
    if(length&0x01)//表示长度为单数
    {
        sum.mLONG +=((*check)&0xff00);
    }
    
    sum.mLONG = sum.mInt[0] + sum.mInt[1];//高16位和低16位相加
    if(sum.mCHAR[0] )                     //51是高位在前。
    {//表示有进位
        sum.mInt[1] ++;
    }
    return ~(sum.mInt[1]);
}

/********************************************/
void main(void)
{
    unsigned int xdata *check;
    unsigned int sum,i;
    check=0;
    for (i=0;i<10000.html">10000;i++)
    {
          *check++ = -i;
    }
    while(1)
    {
        sum=CHECKSUM(10,1000);             //11531
        sum=CHECKSUMx(10,1000);             //9301
        sum=CHECKSUM1(10,1000);             //27347
        sum=CHECKSUM2(10,1000);             //21554
        sum=CHECKSUM(20,1001);             //11542
        sum=CHECKSUMx(20,1001);             //9292
        sum=CHECKSUM1(20,1001);             //27370
        sum=CHECKSUM2(20,1001);             //21573
        sum=CHECKSUM(2000,100);             //1181
        sum=CHECKSUMx(2000,100);         //964
        sum=CHECKSUM1(2000,100);         //3046
        
16楼: >>参与讨论
xwj
...
 

* - 本贴最后修改时间:2006-12-31 21:37:39 修改者:xwj

参与讨论
昵称:
讨论内容:
 
 
相关帖子
请问TMDMG12864A是那个厂家的液晶屏阿? 我怎么没有找到资料:)
请问高手:如何申请MAC地址
求csi1161技术资料
常数强制转换问题
AT89S58-IM烧写问题求助
免费注册为维库电子开发网会员,参与电子工程师社区讨论,点此进入


Copyright © 1998-2006 www.dzsc.com 浙ICP证030469号