IP数据包的校验和算法

合集下载

IP数据包的校验和算法(载))

IP数据包的校验和算法(载))

IP数据包的校验和算法(载)2007-11-02 10:52IP数据包的头信息格式:+-------------------------------------------------+| 版本(4位) |+-------------------------------------------------+| 首部长度(4位) |+-------------------------------------------------+| 服务类型(TOS)8位|+-------------------------------------------------+| 数据包总长度(16位) |+-------------------------------------------------+| 标识ID号(16位) |+-------------------------------------------------+| 标志位(3位) |+-------------------------------------------------+| 片偏移(13位) |+-------------------------------------------------+| 生存时间(TTL)(8位) |+-------------------------------------------------+| 协议类型(8位) |+-------------------------------------------------+| 首部校验和(16位) |+-------------------------------------------------+| 源IP地址(32位) |+-------------------------------------------------+| 目的IP地址(32位) |+-------------------------------------------------+* IP选项(若有)(32位) *+-------------------------------------------------+* 数据*+-------------------------------------------------+这里要说的是首部校验和字段。

java ip校验和计算方法

java ip校验和计算方法

java ip校验和计算方法
IP校验和计算主要是用于验证IP头部的完整性。

这是一种简单的校验方式,只检查IP头部是否在传输过程中被修改。

IP头部校验和的计算方法如下:
1. 将IP头部的所有16位分为多个部分。

2. 将这些部分反转(即0变1,1变0)。

3. 将反转后的每个部分相加。

4. 如果结果为0,则头部是正确的;如果结果为0xFFFF,则头部在传输过
程中被修改过。

以下是Java中实现IP校验和计算的代码:
```java
public class IPChecksum {
public static int calculateChecksum(byte[] bytes) {
int sum = 0;
for (int i = 0; i < ; i += 2) {
sum += (bytes[i] << 8) (bytes[i + 1] & 0xFF);
}
while (sum >> 16 > 0) {
sum = (sum & 0xFFFF) + (sum >> 16);
}
return ~sum & 0xFFFF;
}
}
```
以上代码将一个字节数组(假设是IP头部)作为输入,并返回一个16位的整数,表示计算出的校验和。

如果输入的头部在传输过程中被修改过,那么返回的值将为0xFFFF。

ip校验和计算方法

ip校验和计算方法

ip校验和计算方法
ip校验和计算方法
一、IP校验和的概念
在了解IP校验和之前,我们先来了解一下IP协议包的基本结构,IP协议包的最顶层就是IP数据报头,一个IP数据报头有20个字节,其中有一个字节是校验和,它是用来验证IP数据报头中的其他19个字节是否出错的。

二、IP校验和的计算方法
IP校验和的计算方法用到的是二进制算术,该算法可以有效的检测IP数据报头中的错误,它采用的是和校验的方式,校验和的计算步骤如下:
第一步:将IP数据报头中的19个字节的每个字节看作16进制,先把它们从左到右相加,然后取得其二进制结果。

第二步:将上述加和结果的每一位取反,然后取得其二进制结果,取反后的结果就是校验和。

第三步:将最终的二进制校验和转换成16进制,即可得到IP数据报头中的校验和字节。

注:在计算过程中,如果出现某一字节的加和结果超出8位二进制的最大值,则将其超出的部分与下一字节相加,直至最后得到一个不超过8位的二进制数据。

三、IP校验和的优点
1、IP校验和可以有效的检测IP数据报头中的错误,当发现数
据报头中存在错误时,便会将其丢弃,从而起到一定的安全作用。

2、它不需要太多的计算复杂度,计算过程简单,速度快。

四、IP校验和的缺点
1、只能检测数据的一种类型的错误,即出现在IP数据报头中的错误,而不能检测其他类型的错误。

2、不能发现重复的数据包,因为当检测到重复的数据包时,校验和的值也是相同的,所以无法检测到。

3、只能检测低级的传输错误,对于高级的传输错误,无法进行检测。

IP首部检验和算法

IP首部检验和算法

IP⾸部检验和算法原创博⽂,转载请注明。

在学习TCP/IP 详解的过程中遇到了不⽌⼀次的关于检验和的概念,在吸取了他⼈理解的前提下,我决定⽤Wireshark 进⾏抓包分析。

⾸先我们得知道IP数据包格式⾸先把检验和字段置为 0 。

然后,对⾸部中每个 16 bit 进⾏⼆进制反码求和(整个⾸部看成是由⼀串 16 bit的字组成),结果存在检验和字段中。

当收到⼀份I P数据报后,同样对⾸部中每个 16 bit进⾏⼆进制反码的求和。

由于接收⽅在计算过程中包含了发送⽅存在⾸部中的检验和,因此,如果⾸部在传输过程中没有发⽣任何差错,那么接收⽅计算的结果应该为全 1。

如果结果不是全1 (即检验和错误),那么I P就丢弃收到的数据报。

但是不⽣成差错报⽂,由上层去发现丢失的数据报并进⾏重传。

再来看看Wireshark抓取结果观察此图,我们可以看到这是⼀个源地址为123.151.152.231 ⽬的地址为10.22.66.206即为本机地址的IP数字报传送。

注意图中标深蓝颜⾊的数字,每当我们点击分类信息时,下⽅的数字就会跟随着发⽣变化,因此我们就可以得到IP数据报的内容。

、解释如下:(本内容部分取⾃)版本号4,占了4位,表⽰ipv4.接下来是包头长度,⼜占了4位,指明ipv4协议包头长度的字节数包含多少个32位。

由于IPv4的包头可能包含可变数量的可选项,所以这个字段可以⽤来确定IPv4数据报中数据部分的偏移位置。

IPv4包头的最⼩长度是20个字节,因此IHL这个字段的最⼩值⽤⼗六进制表⽰就是5(5x4(4个字节32位) = 20字节)。

就是说,它表⽰的是包头的总字节数是4字节的倍数。

图中即为header length为20表⽰是20个字节,所以经过计算此处⽤⼗六进制表⽰为5,⼆进制表⽰为1001。

再往下是服务类型为0x00。

服务类型此处⼀共占了8位,涵义如下:过程字段: 3位,设置了数据包的重要性,取值越⼤数据越重要,取值范围为:0(正常)~ 7(⽹络控制)延迟字段: 1位,取值:0(正常)、1(期特低的延迟)流量字段: 1位,取值:0(正常)、1(期特⾼的流量)可靠性字段: 1位,取值:0(正常)、1(期特⾼的可靠性)成本字段: 1位,取值:0(正常)、1(期特最⼩成本)未使⽤: 1位接着是总长度total length:⼗六进制是0x0028标识字段:占16位。

ip校验规则

ip校验规则

ip校验规则
【最新版】
目录
1.IP 校验规则的定义和作用
2.IP 校验规则的分类
3.IP 校验规则的具体实现方式
4.IP 校验规则的应用场景
5.IP 校验规则的优缺点分析
正文
一、IP 校验规则的定义和作用
IP 校验规则,是指在网络通信中,对数据包的源 IP 地址和目标 IP 地址进行校验的一种规则。

其主要作用是确保数据包在网络中的传输安全,防止非法的访问和攻击。

二、IP 校验规则的分类
IP 校验规则主要分为两种:一种是基于 IP 地址的校验,另一种是
基于 IP 地址和端口号的校验。

三、IP 校验规则的具体实现方式
IP 校验规则的具体实现方式主要有两种:一种是通过防火墙进行 IP 地址的过滤和校验,另一种是通过 IP 地址和端口号的校验来实现。

四、IP 校验规则的应用场景
IP 校验规则广泛应用于网络安全和访问控制等领域。

例如,在企业
内部网络中,可以通过设置 IP 校验规则,限制外部访问,保护企业内部网络的安全。

五、IP 校验规则的优缺点分析
IP 校验规则的优点在于可以有效地保护网络的安全,防止非法的访问和攻击。

ip校验规则

ip校验规则

ip校验规则一、IP校验规则简介IP校验规则是指用于验证IP地址格式和范围的规则,以确保网络通信的顺畅进行。

IP地址是互联网上设备之间互相通信的唯一标识,因此IP校验规则在保证网络稳定运行中起着至关重要的作用。

二、IP地址分类与表示方法1.IPV4地址IPV4地址是互联网最常用的地址类型,它采用32位二进制表示,总共分为A、B、C、D、E五类。

其中,A类地址范围为1.0.0.0至126.255.255.255,B类地址范围为128.0.0.0至191.255.255.255,C类地址范围为192.0.0.0至223.255.255.255,D类地址为组播地址,范围为224.0.0.0至239.255.255.255,E类地址为保留地址,范围为240.0.0.0至255.255.255.255。

2.IPV6地址IPV6地址是下一代互联网地址,采用128位二进制表示。

相较于IPV4,IPV6具有更多的地址空间,提高了网络安全性和隐私保护能力。

IPV6地址分为单播、组播和任播三种类型,用于不同场景的通信。

三、IP校验算法1.子网掩码子网掩码是一种用于划分IP地址的网络部分和主机部分的算法。

通过子网掩码,可以将一个大型网络划分为多个较小的子网,提高IP地址的利用率。

子网掩码通常用一个32位的二进制数表示,其中网络部分为1,主机部分为0。

2.CIDR(无类别域间路由)CIDR是一种用于表示网络地址的编码方式,它将IP地址和子网掩码合并为一个统一的表示形式。

CIDR地址格式为“IP地址/子网掩码”,如“192.168.1.0/24”。

CIDR有效地简化了网络地址的表示和计算,便于网络管理和规划。

3.网络层协议校验网络层协议校验是指对IP数据报进行校验,确保数据在传输过程中不被篡改。

主要方法有校验和算法、加密算法等。

这些算法可以检测到数据报在传输过程中的错误,保证数据完整性。

四、IP校验实例与应用1.网络诊断与故障排查通过IP校验规则,可以快速定位网络故障,如IP地址冲突、子网划分不当等问题。

ip校验和计算方法

ip校验和计算方法

计算ip首部校验和
1.发送IP数据报计算checksum
(1)将校验和字段置为0;
(2)对首部中(一般为20B)每个16位字进行二进制反码求和;
(3)将(2)中得到的和再取反码,即得checksum,写入校验和字段中。

抓个IP数据包,取IP数据报报头部分(20B),数据如下:
45 00 00 30 80 4c 40 00 80 06 b5 2e d3 43 11 7b cb 51 15 3d
下面我来计算一下校验和:
(1)将校验和字段置为0:
将b5 2e置为00 00,即变成:
45 00 00 30 80 4c 40 00 80 06 00 00 d3 43 11 7b cb 51 15 3d
(2)反码求和
4500+0030+804c+4000+8006+0000+d343+117b+cb51+153d=34ace 将将进位(3)加到低16位(4ace)上:0003+4ace=4ad1
(3)取反码
将4ad1取反得:checksum=b52e
2.接收IP数据报检验IP校验和
(1)对首部中每个16 bit进行二进制反码求和;
(2)将(1)中得到的和再取反码,看是否为0.
接收到的IP数据报首部:
45 00 00 30 80 4c 40 00 80 06 b5 2e d3 43 11 7b cb 51 15 3d
下面来验证下:
(1)反码求和
4500+0030+804c+4000+8006+b52e+d343+117b+cb51+153d=3fffc 0003+fffc=ffff
(2)取反码:~ffff=0 正确。

IP 首部校验和的计算 zz

IP 首部校验和的计算 zz

IP 首部校验和的计算zz1IP数据包的头信息格式:+-------------------------------------------------+| 版本 (4位) |+-------------------------------------------------+| 首部长度(4位) |+-------------------------------------------------+| 服务类型(TOS)8位 |+-------------------------------------------------+| 数据包总长度(16位) |+-------------------------------------------------+| 标识ID号(16位) |+-------------------------------------------------+| 标志位(3位) |+-------------------------------------------------+| 片偏移(13位) |+-------------------------------------------------+| 生存时间(TTL)(8位) |+-------------------------------------------------+| 协议类型 (8位) |+-------------------------------------------------+| 首部校验和(16位) |+-------------------------------------------------+| 源IP地址(32位) |+-------------------------------------------------+| 目的IP地址 (32位) |+-------------------------------------------------+* IP选项(若有) (32位) *+-------------------------------------------------+* 数据 *+-------------------------------------------------+这里要说的是首部校验和字段。

TCP,UDP完整数据包校验和通用计算

TCP,UDP完整数据包校验和通用计算

TCP,UDP完整数据包校验和通用计算TCP,UDP完整数据包校验和通用计算ICMP,IP,UDP,TCP报头部分都有checksum(检验和)字段。

ICMP和IP报头校验和的计算都很简单,使用RFC1071中给出的方法即可完成(如下)。

//计算校验和USHORT checksum(USHORT *buffer,int size){unsigned long cksum=0;while(size>1){cksum+=*buffer++;size-=sizeof(USHORT);}if(size){cksum+=*(UCHAR *)buffer;}//将32位数转换成16while (cksum>>16)cksum=(cksum>>16)+(cksum & 0xffff);return (USHORT) (~cksum);}UDP/TCP报头中的校验和的计算比较复杂的,要用到UDP/TCP伪首部:先要填充伪首部各个字段,然后再将UDP/TCP报头以后(包括报头)的数据附加到伪首部的后面,再对位首部使用上述校验和计算,所得到的值才是UDP/TCP报头部分的校验和。

位首部可以用如下的结构体表示:typedef struct{ULONG sourceip; //源IP地址ULONG destip; //目的IP地址BYTE mbz; //置空(0)BYTE ptcl; //协议类型USHORT plen; //TCP/UDP数据包的长度(即从TCP/UDP报头算起到数据包结束的长度单位:字节)}Psd_Header;这个过程是一个很繁琐的过程,计算过几次后再也忍受不了做这样重复的工作,于是写了一个通用的计算函数。

这个函数使用起来我感觉非常方便:先封装好你的数据包(完整的,包括以太头),然后将数据包的首地址作为参数,调用该函数即可。

函数将帮你完成IP报头以及UDP/TCP报头部分校验和的计算。

IP校验和计算方法

IP校验和计算方法

IP校验和计算⽅法
简介
计算IP数据报的检验和⽅法:
1.把检验和字段置为0.
2.对⾸部中每个16bit进⾏⼆进制反码求和
3.结果存在检验和字段中
当收到⼀份IP数据报后,同样对⾸部中每个16bit进⾏⼆进制反码的求和。

由于接收⽅在计算过程中包含了发送⽅存在⾸部中的检验和,
因此如果⾸部在传输过程中没有发⽣任何差错,那么接收⽅计算的结果应该为全1.
如果结果不不是全1,那么IP久丢弃收到的数据报,但是不⽣成差错报⽂,
由上层去发现丢失的数据报并进⾏重传
发送⽅例⼦
IP检验和检查的是IP头部字段,所以先拿到IP⾸部的16进制码,以16bit为⼀组得到下⾯的数值.并且把校验和字段设置为0.
1.发送⽅1
4510 0054 7e02 4000 4006 【0000】c0a8 031f c0a8 030e
求和值为:2CAE9
⾼位溢出为2,0002+CAE9=CAEB 转换为2进制为:1100101011101011
反码为:11010100010100 转为⼗六进制:3514
接收⽅例⼦
1接收⽅: IP⾸部校验和主要是针对IP⾸部看成16bit为单位的数字组成
,依次进⾏⼆进制求和,然后得出反码
0x4500 0x0040 0x40d2 0x4000 0x8006 0xD272 0xc0a8 0x0301 0x2762 0xfc5c 求和为
3FFFC
⾼位溢出值为3
FFFC+0x0003=FFFF,转换为2进制为:1111111111111111
反码为:0。

解析IPV4报文和IPV6报文的checksum的算法

解析IPV4报文和IPV6报文的checksum的算法

解析IPV4报⽂和IPV6报⽂的checksum的算法校验和(checksum)算法,简单的说就是16位累加的反码运算:计算函数如下:我们在计算时是主机字节序,计算的结果封装成IP包时是⽹络字节序,注意这两者之间的区别,我们在从IP包⾥读取要转化为主机字节序,往IP包⾥存⼊时要转化为⽹络字节序在存⼊。

UINT32 Checksum(UINT32 cksum, VOID *pBuffer, UINT32 size){INT8 num = 0;UINT8 *p = (UINT8 *)pBuffer;if ((NULL == pBuffer) || (0 == size)){return cksum;}while (size > 1){cksum += ((UINT16)p[num] << 8 & 0xff00) | (UINT16)p[num + 1] & 0x00FF;2个字节累加,先取⽹络字节序低位左移8位(变成主机字节序⾼位),与(加)上 ⽹络字节序中的⾼位(主机字节序地位),即⽹络字节序要先变成主机字节序在进⾏累加,size -= 2;num += 2;}if (size > 0)如果长度为奇数{cksum += ((UINT16)p[num] << 8) & 0xFFFF;如果总的字节数为奇数,则最后⼀个字节单独相加num += 1;}while (cksum >> 16){cksum = (cksum & 0xFFFF) + (cksum >> 16);累加完毕将结果中⾼16位再加到低16位上,重复这⼀过程直到⾼16位为全0}return cksum;}注意:UINT32 cksum的类型,这⾥是4个字节的,防⽌在累加的过程中,数据溢出,(例如0xFF累加时就会内存溢出)详细的计算过程和原理如下⼀:ip头的计算:直接对头部数据进⾏累加(不包括原来的checksum值):1、ipv4包头ipHeadLen = (pIpHeader->ver_ihl & 0x0F) << 2;在ipv4头中,版本类型和头长度加在⼀起是1个字节(8位),各占4位,版本类型在前,长度在后,所以要取长度只能取低4位,pIpHeader->chksum = 0;因为不包括原来的checksum值,所以在每次计算前先把checksum的值置0,然后计算sum = Checksum(0, (VOID *)pIpHeader, ipHeadLen);对整个ip包头的累加pIpHeader->chksum = HTONS((UINT16)(~sum));结果为计算值的反码,(别忘转化为⽹络字节序)2、ipv6包头在ipv6中已经省略了checksum部分,但在后⾯的部分要有的,⽐如TCP/UDP包,别⾼兴的太早⼆、TCP/UDP报⽂的计算(举例UDP):这⾥的checksum包含两部分,⼀部分是伪头的累加,还有⼀部分是UDP包的累加(不包括原来的checksum值)伪头有分ipv4和ipv6两种,分别包含如下⼏部分,这⾥做下⽐较IPV4IPV6⽬的地址4字节(32位)16字节(128位)源地址4字节(32位)16字节(128位)协议类型1字节(8位)(Protocol)1字节(8位)(nextheader)(TCP/UDP)长度2字节(16位)2字节(16位)1、ipv4类型的:第⼀部分,伪头部分的计算:sum = 0;udpLen = sizeof(UDP_HEADER_T) + dhcpLen;UDP的长度= UDP的包头长度+ UDP的数据长度sum += udpLen;或者,下⾯也是⼀样的,这⾥就是⽹络字节序和主机字节序的区别了,上⾯的是(主机字节序)直接累加,下⾯的是⽹络字节序,⼀定要变成主机字节序后累加pUdpHeader->len = HTONS(udpLen);主机字节序转化为⽹络字节序,存⼊数据包中,⼀定要注意,我们做的所有累加也是⽹络字节序,这⾥⼀定要搞清楚,以防混淆搞错了sum += (pUdpHeader->len >> 8 & 0x00FF);2个字节的累加,先取⽹络字节序的⾼位,右移8位,变成主机字节序的低位,累加sum += (pUdpHeader->len << 8 & 0xFF00);在取⽹络字节序的低位,左移8位,变成主机字节序的⾼位,累加sum = Checksum(sum, (VOID *)&pIpHeader->saddr, 4);sum = Checksum(sum, (VOID *)&pIpHeader->daddr, 4);对4位的地址进⾏累加sum += ((UINT16)pIpHeader->proto & 0x00FF);对1位的协议类型进⾏累加伪头部分计算完成第⼆部分,UDP数据包的计算pUdpHeader->chksum = 0;注意:每次计算前别忘先把checksum的值置0,然后计算sum = Checksum(sum, (VOID *)pUdpHeader, udpLen);对整个UDP包的累加pUdpHeader->chksum = HTONS((UINT16)(~sum));结果为计算值的反码,(别忘转化为⽹络字节序)UDP数据包部分计算完成2、ipv6类型的:第⼀部分,伪头部分的计算:sum = 0;udpLen = sizeof(UDP_HEADER_T) + dhcpLen;sum += udpLen;或者pUdpHeader->len = HTONS(udpLen);sum += (pUdpHeader->len >> 8 & 0x00FF);sum += (pUdpHeader->len << 8 & 0xFF00);sum = Checksum(sum, (VOID *)&pIpHeader->saddr, 16); sum = Checksum(sum, (VOID *)&pIpHeader->daddr, 16);对16位的地址进⾏累加sum += ((UINT16)pIpHeader->proto & 0x00FF); 伪头部分计算完成第⼆部分,UDP数据包的计算pUdpHeader->chksum = 0;注意:每次计算前别忘先把checksum的值置0,然后计算sum = Checksum(sum, (VOID *)pUdpHeader, udpLen);对整个UDP包的累加pUdpHeader->chksum = HTONS((UINT16)(~sum));结果为计算值的反码,(别忘转化为⽹络字节序)UDP数据包部分计算完成。

ip首部校验和算法

ip首部校验和算法

实验报告(3)——首部检验和的编程实现一、实验人员二、实验内容和要求(一)实验内容编写一个计算IP报文中首部校验和的程序,并且通过抓包随机选择一个数据报,提取出IP报文首部部分,根据程序计算出校验和的计算值,与报文中检验和对比,检验程序的正确性,计算结果为0保留数据报,否则丢弃。

(二)实验要求1.掌握IP数据报的结构,通过wireshark抓包随机选择一个TCP数据报,提取IP报部分,并找到首部。

2.学习理解并运用IP首部校验和的计算算法,通过程序实现。

三、实验环境Wireshark抓包工具Microsoft visual studio 2010 C#四、实验过程与结果分析(一)实验过程1.利用wireshark抓包分析包格式并提取IP首部(1)IP数据报格式如图1,IP数据报的首部为前20字节。

因为首部校验和的计算只需要IP数据报的首部20个字节即可,数据部分不参加运算。

所以只需要把IP数据包中的前20个16进制数提取出来作为运算的数据即可。

图1 IP数据包格式(2)抓包得到的数据报图2 TCP数据报如图2,通过wireshark抓包,随机选择一个TCP数据报,根据TCP数据报的格式,我们分析数据报内容可以知道:首先开始6个字节为目的mac地址,后面6个字节为目的mac地址,后面2个字节为协议类型为0800,是IP协议包。

所以再后面的20个字节就是IP数据报的首部部分。

也就是实验所需要的数据。

IP首部为:450000280000400034060ab73baf84710a687191并且,通过包的计算的校验和结果,此包被留下,校验和的值为0。

也是座位后面对设计程序计算得到结果的一个验证。

2.设计计算首部校验和的的算法(1)程序设计的函数模块关系输入IP首部string IP0转化为二进制字符串并划分为10个字段IP1~IP10,函数Getziduan()求字段反码,函数FanMa()反码求和函数FanSum();FanSum0();求出由上一布得到的结果的反码,输出结果(2)算法流程首先将IP首部即40位16进制的字符串转化为二进制字符串,然后以每16位为一个字段,分为10个二进制字段。

IP校验和计算

IP校验和计算

IP校验和‎计算下‎面摘自《T‎C P/IP‎协议簇》的‎I P头校验‎和算法:‎发送时:‎1. ‎将校验和字‎段置为0;‎2. ‎将整个首部‎分为16b‎i t的部分‎,求和;‎3. 取‎反码,填入‎到校验和字‎段中;‎接收时:‎1. 直‎接将整个首‎部分为16‎b it的部‎分,求和;‎2. ‎取反码,若‎结果为0,‎取合法;否‎则丢弃;‎这上面有‎两个细节没‎有描述清楚‎:1.‎计算时的‎字节顺序(‎l itte‎r end‎i an和b‎i g en‎d ian)‎问题;‎2. 取和‎溢出时的改‎进计算方法‎;根据‎实验结果,‎及参考网络‎上的资料,‎实际上几乎‎现有所有的‎系统对校验‎和算法已经‎有点小小的‎补充,也许‎《TCP/‎I P协议簇‎》这里没有‎更新罢了,‎自我安慰吧‎,如下:‎◆当发送‎I P包时,‎需要计算I‎P报头的校‎验和:‎1、把‎校验和字段‎置为0;‎2、‎对IP头部‎中的每16‎b it进行‎二进制求和‎;3、‎如果和‎的高16b‎i t不为0‎,则将和的‎高16bi‎t和低16‎b it反复‎相加,直到‎和的高16‎b it为0‎,从而获得‎一个16b‎i t的值;‎4、‎将该16‎b it的值‎取反,存入‎校验和字段‎。

◆当‎接收IP包‎时,需要对‎报头进行确‎认,检查I‎P头是否有‎误,算法同‎上2、3步‎,然后判断‎取反的结果‎是否为0,‎是则正确,‎否则有错。

‎算法:‎‎‎u nsig‎n ed s‎h ort ‎C heck‎S um(u‎n sign‎e d sh‎o rt *‎_pBuf‎f, in‎t _Si‎z e)‎‎ {‎‎‎unsi‎g ned ‎i nt c‎k Sum ‎= 0;‎‎‎ un‎s igne‎d sho‎r t *t‎m pBuf‎f = _‎p Buff‎;‎‎ i‎n t tm‎p Size‎= _S‎i ze;‎‎‎ wh‎i le (‎t mpSi‎z e > ‎1)‎‎‎{‎‎‎ ck‎S um +‎= *tm‎p Buff‎++;‎‎‎‎tmpS‎i ze -‎= siz‎e of(u‎n sign‎e d sh‎o rt);‎‎‎ }‎‎‎ if‎(tmp‎S ize ‎> 0)‎‎‎ {‎‎‎‎c kSum‎+= *‎(unsi‎g ned ‎c har*‎)tmpB‎u ff;‎‎‎ }‎‎‎ ckS‎u m = ‎(ckSu‎m >> ‎16) +‎(ckS‎u m & ‎0xFFF‎F); /‎/将高16‎b it与低‎16bit‎相加‎‎‎c kSum‎+= (‎c kSum‎>> 1‎6); /‎/将进位到‎高位的16‎b it与低‎16bit‎再相加‎‎‎ re‎t urn ‎(unsi‎g ned ‎s hort‎)(~ck‎S um);‎‎ }‎关于计‎算时的字节‎顺序,一般‎以网络字节‎顺序(bi‎g end‎i an)为‎准,但仍然‎有个十分模‎糊的地方,‎就是为什么‎校验和这个‎字段不用进‎行网络转换‎了,如X8‎6系统,直‎接以本地字‎节顺序(l‎i tter‎endi‎a n)发送‎就可以了,‎这也让我十‎分纠结。

IP和TCP包头校验和计算方法

IP和TCP包头校验和计算方法



TCP 伪首部: c0 a8 01 10 源地址 c0 a8 01 67 目的地址 00 06 00 18 置空,协议类型,TCP 长度
计算: c0a8 0110 c0a8 0167 0006 0018 0401 0578 0000 0000 0000 0000 6002 0fca 0000 0000 0204 0fca c0a8 0110 c0a8 0167 0006 0018 0401 0578 0000 0000 0000 0000 6002 0fca F105 0000 0204 0fca

校验和的算法: (如果数据长度为奇数,最后一个字节要先变成 将数据以字为单位进行累加计算,得到一个双字的值。 字,然后在加到原来的双字中) 将得到的双字的值的高 16 位和低 16 位反复相加,直到高 16 位为 0,然后取低 16 位的值,再将这个 16 位的值取反就得到校验和的值。 实例: IP 头: 45 00 00 31 89 F5 00 00 6E 06 00 00(校验字段) DE B7 45 5D -> 222.183.69.93 C0 A8 00 DC -> 192.168.0.220 计算: 4500 0031 89F5 0000 6e06 0000 DEB7 455D C0A8 00DC =7 = DD38 应填充的校验和 在接收端接收到 IP 数据包后,要对 IP 头进行检查看是否有误,所用的算法与上面一致,不同的是最终的结 果要为 0。 计算: 4500 0031 89F5 0000 6E06 DD38 DEB7 455D C0A8 00DC =3 FFFC 0003 FFFC = FFFF ~ FFFF = 00000 正确 TCP 首部检验和与 IP 首部校验和的计算方法相同,在程序中使用同一个函数来计算。 需要注意的是,由于 TCP 首部中不包含源地址与目标地址等信息,为了保证 TCP 校验的有效性,在进行 TCP 校验和的计算时,需要增加一个 TCP 伪首部的校验和。 定义 TCP 伪首部如下: struct{ unsigned long saddr; //源地址 unsigned long daddr; //目的地址 char mbz;//置空,0x00 char ptcl; //协议类型,0x06 unsigned short tcpl; //TCP 长度,0x0018 } psd_header; 然后我们将这两个字段(TCP 伪首部 + TCP 首部)复制到同一个缓冲区 SendBuf 中并计算 TCP 校验 和: memcpy(SendBuf,&psd_header,sizeof(psd_header)); memcpy(SendBuf sizeof(psd_header),&tcp_header,sizeof(tcp_header)); tcp_header.th_sum=checksum((USHORT *)SendBuf,sizeof(psd_header) sizeof(tcp_header)); 实例: TCP 首部: 04 01 05 78 00 00 00 00 00 00 00 00 60 02 0f ca 00 00 00 00 02 04 0f ca

IP首部检验和的算法

IP首部检验和的算法

65536计算对IP首部检验和的算法如下:(1)把IP数据包的校验和字段置为0;(2)把首部看成以16位为单位的数字组成,依次进行二进制求和(注意:求和时应将最高位的进位保存,所以加法应采用32位加法);(3)将上述加法过程中产生的进位(最高位的进位)加到低16位(采用32位加法时,即为将高16位与低16位相加,之后还要把该次加法最高位产生的进位加到低16位)(4)将上述的和取反,即得到校验和。

其中,二进制反码求和的计算方法:首先,计算如图B-1所示的部分和。

把每一列相加,如果有进位,就加到下一列。

注意以下几点:1------------------------第16列的进位1 1------------------------第15列的进位| 1| 1 0| | 1 1| | | 1 0| | | | 1 0| | | | | 1 1| | | | | | | 1 0| | | | | | | | 1 0| | | | | | | | | 1 1| | | | | | | | | | 1 1| | | | | | | | | | 1 0 0-----------第3列的进位| | | | | | | | | | | 1 0 0-----------第2列的进位| | | | | | | | | | | | | 1 1---------第1列的进位| | | | | | | | | | | | | | |1 0 0 1 1 0 0 1 0 0 0 1 0 0 1 00 0 0 0 1 0 0 0 0 1 1 0 1 0 0 11 0 1 0 1 0 1 1 0 0 0 0 0 0 1 00 0 0 0 1 1 1 0 0 0 0 0 1 0 1 00 0 0 0 0 0 0 0 0 0 0 1 0 0 0 10 0 0 0 0 0 0 0 0 0 0 0 1 1 1 10 0 0 0 0 1 0 0 0 0 1 1 1 1 1 10 0 0 0 0 0 0 0 0 0 0 0 1 1 0 10 0 0 0 0 0 0 0 0 0 0 0 1 1 1 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 1 0 1 0 1 0 0 0 1 0 0 0 1 0 10 1 0 1 0 0 1 1 0 1 0 1 0 1 0 00 1 0 0 1 0 0 1 0 1 0 0 1 1 1 00 1 0 0 0 1 1 1 0 0 0 0 0 0 0 0__________________________________1 0 0 1 0 1 1 0 1 1 1 0 1 0 0 1 部分和图B-1 二进制记法的部分和1,当我们加第1列(最右边一列)的时候,我们得到7。

校验和计算

校验和计算
法(载)
2007-11-02 10:52
IP数据包的头信息格式: +-------------------------------------------------+ | 版本 (4位) | +-------------------------------------------------+ | 首部长度(4位) | +-------------------------------------------------+ | 服务类型(TOS)8位 | +-------------------------------------------------+ | 数据包总长度(16位) | +-------------------------------------------------+ | 标识ID号(16位) | +-------------------------------------------------+ | 标志位(3位) | +-------------------------------------------------+ | 片偏移(13位) | +-------------------------------------------------+ | 生存时间(TTL)(8位) | +-------------------------------------------------+ | 协议类型 (8位) | +-------------------------------------------------+ | 首部校验和(16位) | +-------------------------------------------------+ | 源IP地址(32位) | +-------------------------------------------------+ | 目的IP地址 (32位) | +-------------------------------------------------+ * IP选项(若有) (32位) * +-------------------------------------------------+ * 数据 * +-------------------------------------------------+ 这里要说的是首部校验和字段。 在发送数据时,为了计算数IP据报的校验和。应该按如下步骤: (1)把IP数据报的校验和字段置为0。 (2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和。 (3)把得到的结果存入校验和字段中。 在接收数据时,计算数据报的校验和相对简单,按如下步骤: (1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段。 (2)检查计算出的校验和的结果是否等于零。 (3)如果等于零,说明被整除,校验是和正确。否则,校验和就是错误的,协议栈要抛弃这个数据包。 首先,查看了Linux 2.6内核中的校验算法,使用汇编语言编写的,显然效率要高些。代码如下: unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl) { unsigned int sum; __asm__ __volatile__( "movl (%1), %0 ;\n" "subl $4, %2 ;\n" "jbe 2f ;\n" "addl 4(%1), %0 ;\n" "adcl 8(%1), %0 ;\n" "adcl 12(%1), %0 ;\n" "1: adcl 16(%1), %0 ;\n" "lea 4(%1), %1 ;\n" "decl %2 ;\n" "jne 1b ;\n" "adcl $0, %0 ;\n" "movl %0, %2 ;\n" "shrl $16, %0 ;\n" "addw %w2, %w0 ;\n" "adcl $0, %0 ;\n" "notl %0 ;\n" "2: ;\n" /* 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(sum); }

IP数据报首部校验和算法详细非代码

IP数据报首部校验和算法详细非代码

IP数据报⾸部校验和算法详细⾮代码当⽤google搜索IP数据报⾸部校验和算法的时候,总是看到的是代码,没有看到其过程,于是就有了此⽂,如有错误请指正。

⽂章省略⼀点,呵呵IP/ICMP/IGMP/TCP/UDP等协议的校验和算法都是相同的,算法如下:在发送数据时,为了计算数IP据报的校验和。

应该按如下步骤:(1)把IP数据报的⾸部都置为0,包括校验和字段。

(2)把⾸部看成以16位为单位的数字组成,依次进⾏⼆进制反码求和。

(3)把得到的结果存⼊校验和字段中。

在接收数据时,计算数据报的校验和相对简单,按如下步骤:(1)当接收IP包时,需要对报头进⾏确认,检查IP头是否有误,算法同上2、3步,然后判断取反的结果是否为0,是则正确,否则有错。

1、发送⽅ i)将校验和字段置为0,然后将IP包头按16⽐特分成多个单元,如包头长度不是16⽐特的倍数,则⽤0⽐特填充到16⽐特的倍数; ii)对各个单元采⽤反码加法运算(即⾼位溢出位会加到低位,通常的补码运算是直接丢掉溢出的⾼位),将得到的和的反码填⼊校验和字段; iii)发送数据包。

2、接收⽅ i)将IP包头按16⽐特分成多个单元,如包头长度不是16⽐特的倍数,则⽤0⽐特填充到16⽐特的倍数; ii)对各个单元采⽤反码加法运算,检查得到的和是否符合是全1(有的实现可能对得到的和会取反码,然后判断最终值是不是全0);iii)如果是全1则进⾏下步处理,否则意味着包已变化从⽽丢弃之。

需要强调的是反码和是采⽤⾼位溢出加到低位的,如3⽐特的反码和运算:100b+101b=010b(因为100b+101b=1001b,⾼位溢出1,其应该加到低位,即001b+1b(⾼位溢出位)=010b)。

 1.实例请看我⽤ominipeek的抓包I.将校验和字段置为0,然后将IP包头按16⽐特分成多个校验和Header Checksum:0x618D将其重置为0X0000将IP包头分段: 1. 0x4500 2. 0x0029 3. 0x44F1 4. 0x4000 5. 0x8006 6. 0x0000 ------->这个为Header Checksum的值,我们前⾯将其重置为0了 7. 0xC0A8 8. 0x01AE 9. 0x4A7D+ 10. 0x477D-------------------------------------------------------将1⾄10相加求出来的和为:0x29E70II.对各个单元采⽤反码加法运算(即⾼位溢出位会加到低位,通常的补码运算是直接丢掉溢出的⾼位),将得到的和的反码填⼊校验和字段0x0002+0x9E70=0x9E720x9E72⼆进制为:1001 1110 0111 0010反码为:0110 0001 1000 11010110 0001 1000 1101的16进制为:0x618D看看这个是否与IP包头中的Checksum相同==========================================================当接收到IP对其进⾏检测III.对各个单元采⽤反码加法运算,检查得到的和是否符合是全1(有的实现可能对得到的和会取反码,然后判断最终值是不是全0)当收到IP数据局包的时候,要验证IP头是否正确,则可以这样进⾏ 1. 0x4500 2. 0x0029 3. 0x44F1 4. 0x4000 5. 0x8006 6. 0x618D ------->这个为Header Checksum的值 7. 0xC0A8 8. 0x01AE 9. 0x4A7D+ 10. 0x477D-------------------------------------------------------将1⾄10相加求出来的和为:0x2FFD对各个单元采⽤反码加法运算(即⾼位溢出位会加到低位,通常的补码运算是直接丢掉溢出的⾼位),将得到的和的反码填⼊校验和字段:0x0002+0x0FFD=0xFFFF0xFFFF⼆进制为:1111 1111 1111 11111111 1111 1111 1111反码为:0====================================================关于这⼀部的补充说明,将IP包头分段: 1. 0x4500 2. 0x0029 3. 0x44F1 4. 0x4000 5. 0x8006 6. 0x0000 ------->这个为Header Checksum的值,我们前⾯将其重置为0了 7. 0xC0A8 8. 0x01AE 9. 0x4A7D+ 10. 0x477D----------------------------------------------------------------------------------------------------------。

IP头部校验和计算

IP头部校验和计算

IP头部校验和计算unsigned short checksum(unsigned short *buf, int nword) { unsigned long sum;for(sum = 0; nword > 0; nword--)sum += *buf++;sum = (sum>>16) + (sum&0xffff);sum += (sum>>16);return -sum;}让我们假设一个IP头数据,来解cksum的惑IP头数据:01000101 /*ver_hlen*/00000000 /*tos*/00000000 00000010 /*len*/00000000 00000000 /*id*/00000000 00000000 /*offset*/00000100 /*ttl*/00010001 /*type*/00000000 00000000 /*cksum(0)*/ 01111111 00000000 00000000 00000001 /*sip*/ 01111111 00000000 00000000 00000001 /*dip*/(1)16比特分组;(2)校验和清‘0’(3)求所有16比特之和01000101 00000000 /*ver_hlen*/ 00000000 00000010 /*len*/---------------------01000101 0000001000000000 00000000 /*id*/---------------------01000101 0000001000000000 00000000 /*offset*/---------------------01000101 0000001000000100 00010001 /*ttl*//*type*/---------------------01001001 0001001100000000 00000000 /*cksum(0)*/---------------------01001001 0001001101111111 00000000 /*sip*/---------------------11001000 0001001100000000 00000001 /*sip*/---------------------11001000 0001010001111111 00000000 /*dip*/---------------------101000111 0001010000000000 00000001 /*dip*/---------------------101000111 00010101 sum(4)把求得的和模(216-1)00000000 00000001 (sum>>16) 01000111 00010101 (sum&0xffff) ---------------------01000111 00010110(5)在(4)的基础上求二进制反码10111000 11101001 cksum说白了就是循环加,然后在取反!对方机器调用checksum()计算校验和,如果校验和为0表明IP包传输正确----------------------------------------------------------- 01000101 /*ver_hlen*/00000000 /*tos*/00000000 00000010 /*len*/00000000 00000000 /*id*/00000000 00000000 /*offset*/00000100 /*ttl*/00010001 /*type*/10111000 11101001 /*cksum(0)*/01111111 00000000 00000000 00000001 /*sip*/01111111 00000000 00000000 00000001 /*dip*/01000101 0000000000000000 00000010---------------------01000101 0000001000000000 00000000---------------------01000101 0000001000000000 00000000--------------------- 01000101 00000010 00000100 00010001 --------------------- 01001001 00010011 10111000 11101001 --------------------- 100000001 11111100 01111111 00000000--------------------- 110000000 11111100 00000000 00000001--------------------- 110000000 11111101 01111111 00000000--------------------- 111111111 11111101 0000000000000001--------------------- 111111111 11111110 sum00000000 00000001 (sum>>16)11111111 11111110 (sum&0xffff)----------------------11111111 11111111~sum00000000 00000000现在我们所用的机器设备大多数是使用二进制补码算法进行计算的。

ip校验和

ip校验和

Ip数据报首部检验和的算法及验证
原理
发送时:
1. 将校验和字段置为0;
2. 将整个首部分为16bit的部分,求和;
3.进行反码算数运算求和,若结果高于16b,将高出的位数截取,加到剩下的16b中,重复此步骤,直到不多于16b
4.取反码,填入校验和字段中
接收时:
1. 直接将整个首部分为16bit的部分,求和;
2.进行反码算数运算求和,若结果高于16b,将高出的位数截取,加到剩下的16b中,重复此步骤,直到不多于16b
3.取反码,若结果为0则正确,如果结果不为0则说明出现错误

使用wireshark抓包,获得任意一个ip数据报
程序运行结果
计算校验和的结果
检验校验和的结果
#include<stdio.h> main()
{
inti,j,k=1,num,flag;
int
head[10]={0x4500,0x0028,0xbc61,0x4000,0x2d06,0xb99a,0x7b7d,0x735f,0x0a0b,0xdeec};
head[5]=0;
num=head[0];
for(i=1;i<10;i++)
num=num+head[i];
while((num>>16)>0)
num=(num>>16)+(num&0xffff);
num=~num;
printf("%x\n",num);
}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

IP数据包的校验和算法IP数据包的头信息格式:+-------------------------------------------------+| 版本 (4位) |+-------------------------------------------------+| 首部长度(4位) |+-------------------------------------------------+| 服务类型(TOS)8位 |+-------------------------------------------------+| 数据包总长度(16位) |+-------------------------------------------------+| 标识ID号(16位) |+-------------------------------------------------+| 标志位(3位) |+-------------------------------------------------+| 片偏移(13位) |+-------------------------------------------------+| 生存时间(TTL)(8位) |+-------------------------------------------------+| 协议类型 (8位) |+-------------------------------------------------+| 首部校验和(16位) |+-------------------------------------------------+| 源IP地址(32位) |+-------------------------------------------------+| 目的IP地址 (32位) |+-------------------------------------------------+* IP选项(若有) (32位) *+-------------------------------------------------+* 数据 *+-------------------------------------------------+这里要说的是首部校验和字段。

在发送数据时,为了计算数IP据报的校验和。

应该按如下步骤:(1)把IP数据报的校验和字段置为0。

(2)把首部看成以16位为单位的数字组成,依次进行二进制反码求和。

(3)把得到的结果存入校验和字段中。

在接收数据时,计算数据报的校验和相对简单,按如下步骤:(1)把首部看成以16位为单位的数字组成,依次进行二进制反码求和,包括校验和字段。

(2)检查计算出的校验和的结果是否等于零。

(3)如果等于零,说明被整除,校验是和正确。

否则,校验和就是错误的,协议栈要抛弃这个数据包。

首先,查看了Linux 2.6内核中的校验算法,使用汇编语言编写的,显然效率要高些。

代码如下:unsigned short ip_fast_csum(unsigned char * iph,unsigned int ihl){unsigned int sum;__asm__ __volatile__("movl (%1), %0 ;\n""subl $4, %2 ;\n""jbe 2f ;\n""addl 4(%1), %0 ;\n""adcl 8(%1), %0 ;\n""adcl 12(%1), %0 ;\n""1: adcl 16(%1), %0 ;\n""lea 4(%1), %1 ;\n""decl %2 ;\n""jne 1b ;\n""adcl $0, %0 ;\n""movl %0, %2 ;\n""shrl $16, %0 ;\n""addw %w2, %w0 ;\n""adcl $0, %0 ;\n""notl %0 ;\n""2: ;\n"/* Since the input registers which are loaded with iph and ihlare modified, we must also specify them as outputs, or gccwill assume they contain their original values. */: "=r" (sum), "=r" (iph), "=r" (ihl): "1" (iph), "2" (ihl): "memory");return(sum);}在这个函数中,第一个参数显然就是IP数据报的首地址,所有算法几乎一样。

需要注意的是第二个参数,它是直接使用IP数据报头信息中的首部长度字段,不需要进行转换,因此,速度又快了(高手就是考虑的周到)。

使用方法会在下面的例子代码中给出。

第二种算法就非常普通了,是用C语言编写的。

我看了许多实现网络协议栈的代码,这个算法是最常用的了,即使变化,也无非是先取反后取和之类的。

考虑其原因,估计还是C 语言的移植性更好吧。

下面是该函数的实现:unsigned short checksum(unsigned short *buf,int nword){unsigned long sum;for(sum=0;nword>0;nword--)sum += *buf++;sum = (sum>>16) + (sum&0xffff);sum += (sum>>16);return ~sum;}这里我要把我的惨痛的经历也要说一下,为了研究IP校验和的算法,我根据算法也进行了代码编写,可是结果总是有8位不一样,郁闷了好久,最后还是 David L .Stevens给我了答案(不要误会,是在他的书中找到的答案,呵呵)。

那就是现在我们所用的机器设备大多数是使用二进制补码算法进行计算的。

因此,仅仅简单的累加得出的校验和并不是正确的结果。

下面就是IP数据报首部校验和算法的代码示例:#include <stdio.h>#include <stdlib.h>#include <linux/if_ether.h>#include <linux/ip.h>#include <sys/socket.h>#define ETH_P_LENGTH 65535#define ETHERNET_MAX_LEN 1500#define ETHERNET_MIN_LEN 46unsigned short ip_fast_csum(unsigned char * iph, unsigned int ihl);unsigned short checksum(unsigned short *buf,int nword);//--------------------------------------------------------------------// Main function//// Do all if it can do////--------------------------------------------------------------------int main(int argc,char *argv[]){int listenfd;int nbyte;char buf[ETH_P_LENGTH];struct ethhdr *eth = NULL;struct iphdr *ip = NULL;short chk;//// Print banner//printf("\n\tSendArp v1.0 - scan IP and MAC\n");printf("\tNsfocus - \n");printf("\tby David Zhou\n");printf("\tDate : 2006/01/19\n\n");if ((listenfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {printf("Call socket() function error\n");return 1;}for (;;){if ((nbyte = recv(listenfd, buf, ETH_P_LENGTH, 0)) > 0){struct ethhdr *eth = (struct ethhdr *)buf;if(ntohs(eth->h_proto) == ETH_P_IP){ // EtherNet frame// print ip sumip = (struct iphdr *)&buf[14];printf("IP CheckSum = 0x%04X\n",ntohs(ip->check));//verify ip checksumchk = checksum((unsigned short*)ip,10);printf("Verify CheckSum = 0x%04X\n\n",ntohs(chk));//// reset check to calc self//ip->check = 0;// 2.6 kernelchk = ip_fast_csum((unsigned char *)ip,ip->ihl);printf("Calc CheckSum = 0x%04X - %d\n",ntohs(chk),ip->ihl);// coustom calcchk = checksum((unsigned short*)ip,10);printf("Calc CheckSum = 0x%04X\n\n",ntohs(chk));}}}return 0;}unsigned short checksum(unsigned short *buf,int nword){unsigned long sum;for(sum=0;nword>0;nword--)sum += *buf++;sum = (sum>>16) + (sum&0xffff);sum += (sum>>16);return ~sum;}/** This is a version of ip_compute_csum() optimized for IP headers, * which always checksum on 4 octet boundaries.* By Jorge Cwik <jorge@>, adapted for linux by* Arnt Gulbrandsen.*/unsigned short ip_fast_csum(unsigned char * iph,unsigned int ihl){unsigned int sum;__asm__ __volatile__("movl (%1), %0 ;\n""subl $4, %2 ;\n""jbe 2f ;\n""addl 4(%1), %0 ;\n""adcl 8(%1), %0 ;\n""adcl 12(%1), %0 ;\n""1: adcl 16(%1), %0 ;\n""lea 4(%1), %1 ;\n""decl %2 ;\n""jne 1b ;\n""adcl $0, %0 ;\n""movl %0, %2 ;\n""shrl $16, %0 ;\n""addw %w2, %w0 ;\n""adcl $0, %0 ;\n""notl %0 ;\n""2: ;\n"/* Since the input registers which are loaded with iph and ihlare modified, we must also specify them as outputs, or gccwill assume they contain their original values. */: "=r" (sum), "=r" (iph), "=r" (ihl): "1" (iph), "2" (ihl): "memory");return(sum);}。

相关文档
最新文档