Chinaunix首页 | 论坛 | 博客
  • 博客访问: 133237
  • 博文数量: 38
  • 博客积分: 1277
  • 博客等级: 中尉
  • 技术积分: 450
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-11 23:24
文章分类

全部博文(38)

文章存档

2012年(2)

2011年(7)

2010年(24)

2009年(5)

分类: LINUX

2011-05-29 04:28:16


// linux-2.6.35/arch/x86/include/asm/checksum_64.h


static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl)
{
    unsigned int sum;

    asm(" movl (%1), %0\n"        /* %1初始值为iph指针,先把第1个32bit值赋给 %0 */
     " subl $4, %2\n"        /* %2为ihl,ihl*4才是ip header的实际长度,这里先减去4,因为下面要连续计算4个32bit值*/
     " jbe 2f\n"            /* 当ihl不足4时,跳到下面2处,也就是结束返回了 */
     " addl 4(%1), %0\n"    /* 4(%1)为偏移4byte,也就是第2个32bit,和 %0 相加 */
     " adcl 8(%1), %0\n"    /* adc是带进位相加,8(%1) 为第3个32bit,和 %0 相加 */
     " adcl 12(%1), %0\n"    /* 12(%1) 为第4个32bit,和 %0 相加 */
     "1: adcl 16(%1), %0\n"    /* adc是带进位相加,16(%1) 为第5个32bit,和 %0 相加 */
     " lea 4(%1), %1\n"        /* %1向生偏移4byte,再赋给 %1,也就是说首指针往后偏移4byte */
     " decl %2\n"            /* %2个数自减, 以后每次只计算一个4byte */
     " jne    1b\n"            /* 非0,表示长度还有值,再往上跳回到1处计算一个32bit */
     " adcl $0, %0\n"        /* 为0时,表示所有长度都已算完,剩下就是进位还没算,这里再加0计算进位 */
     " movl %0, %2\n"        /* 把%0值放到%1中 */
     " shrl $16, %0\n"        /* 因为ip 校验位是16bit的,所以这里%0右移16bit,得到高16bit放到%0中 */
     " addw %w2, %w0\n"        /* w表示计算16bit值,%2 + %0 表示再加上上面的高16bit */
     " adcl $0, %0\n"        /* 在上面基础上,再计算进位 */
     " notl %0\n"            /* 取反运算,结果存入%0中,也就是存入sum中 */
     "2:"
    /* Since the input registers which are loaded with iph and ihl
     are modified, we must also specify them as outputs, or gcc
     will assume they contain their original values. */
     : "=r" (sum), "=r" (iph), "=r" (ihl)
     : "1" (iph), "2" (ihl)
     : "memory");
    return (__force __sum16)sum;
}


注:1. ip header checksum计算比较频繁,所以用汇编写可以提高效能。

    2. ip header,长度为20-60 bytes,而且一定是按4-byte对齐的。


阅读(2866) | 评论(0) | 转发(1) |
0

上一篇:Unicode 读写文本

下一篇:object-c for linux

给主人留下些什么吧!~~