信息的表示和处理
一、gcc 编译
使用C99特性时 gcc -std=c99 xxx.c 实验楼环境为64位,编译为32位机器码: gcc -m32 xxx.c
二、 教材导读
公式可以不看,习题不能不做,考核题目和课后习题类似,重点题目:
2.4、2.6、2.8、2.11、2.13、2.14、2.18、2.19、2.21、2.23、
2.24、2.25、2.27、2.29、2.33、2.34、2.39、2.40、2.42、2.43、
2.44、2.45、2.47、2.50、2.52、2.54
p20: 三种数字:无符号数、有符号数(2进制补码)、浮点数,信息安全系同学从逆向角度考虑为什么会产生漏洞
无符号(unsigned)编码基于传统的二进制表示法,表示大于或者等于零的数字。
补码(two’s-complement)编码是表示有符号整数的最常见的方式,有符号整数就是可以为正或者为负的数字。
浮点数(?oating-point)编码是表示实数的科学记数法的以二为基数的版本。
信息安全系同学从逆向角度考虑为什么会产生漏洞?
会产生溢出。
溢出:计算机的表示法是用有限数量的位来为一个数字编码,因此当结果太大就会导致某些运算溢出。
整数和浮点数会有不同的数学属性是因为:处理数字表示有限性的方法不同:
整数:编码相对较小的数值范围,但精确度高
浮点数:编码较大范围的数,但这种表示是近似的
p22: 进制转换,注意拿二进制作中间结果就好转了
p25: gcc -m32 可以在64位机上(比如实验楼的环境)生成32位的代码
p26: 字节顺序是网络编程的基础,记住小端是“高对高、低对低”,大端与之相反就可以了。
p28: 代码执行一下
p32: 能区分逻辑运算(结果是1或0)和位运算(结果是位向量),所有逻辑运算都可以用与、或、非表达(最大式、最小式),而与或非可以用“与非”或“或非”表达,所以,只要一个与非门,就可以完成所有的逻辑运算。
p33: 掩码是位运算的重要应用,对特定位可以置一,可以清零
p38: 要用C99中的“long long”类型,编译是要用 gcc -std=c99
p39: 补码的利用寄存器的长度是固定的特性简化数学运算。想想钟表,12-1 等价于 12 + 11,利用补码可以把数学运算统一成加法,只要一个加法器就可以实现所有的数学运算。
p44: 注意C语言中有符号数和无符号数的转换规则,位向量不变。想想第一章说的 信息就是“位+上下文”
p48: 怎么样让负数等于正数? 信息安全的逆向思维
p49: 0扩展和符号扩展
p52: 深入思考一下代码和结果
p54: 如何让整数运算溢出?如何避免? p62例子看看
p67: 关于整数运算的最后思考
p67: 浮点数有科学计数法的基础就不难理解,IEEE标准754
p68: 浮点数运算的不精确性与舍入
p70: IEEE浮点标准,float/double类型
p74: 整数与浮点数表示同一个数字的关系
p78: 整数与浮点数转换规则
寻址和字节顺序(汇编中的数据存储方式来寻址)
按照从最高有效字节到最低有效字节的顺序存储。前一种规则—最低有效字节在最前面的方式,称为小端法。
大端法与之相反。
使用typedef命名数据类型
C语言中的typedef声明提供了一种给数据类型命名的方式。
指针的创建和间接引用
C的“取地址”运算符&创建一个指针。在这三行中,表达式&x创建了一个指向保存变量x的位置的指针。这个指针的类型取决于x的类型,因此这三个指针的类型分别为int*、float*和void**。(数据类型void*是一种特殊类型的指针,没有相关联的类型信息。)
布尔代数
与或非,取反运算。位运算。&与门:有零就是零。|或门:有一就是一。^异或门:相同为零,不同为一。
C语言中的位级运算
确定一个位级表达式的结果最好的方法,就是将十六进制的参数扩展成二进制表示并执行二进制运算,然后再转换回十六进制
掩码:某一位置为一,表示信号i有效,0则为信号i是被屏蔽的。
位级运算的一个常见用法就是实现掩码运算,这里掩码是一个位模式,表示从一个字中选出的位的集合。让我们来看一个例子,掩码0xFF(最低的8位为1)表示一个字的低位字节。位级运算x&0xFF生成一个由x的最低有效字节组成的值,而其他的字节就被置为0。比如,对于x=0x89ABCDEF,其表达式将得到0x000000EF。表达式~0将生成一个全1的掩码,不管机器的字大小是多少。尽管对于一个32位机器来说,同样的掩码可以写成0xFFFFFFFF,但是这样的代码不是可移植的。
C语言中的移位运算
C语言还提供了一组移位运算,以便向左或者向右移动位模式。对于无符号数据(也就是以限定词unsigned声明的整型对象),右移必须是逻辑的。而对于有符号数据(默认的声明的整型对象),算术的或者逻辑的右移都可以。
与移位运算有关的操作符优先级问题:加法(和减法)的优先级比移位运算要高。
补码编码
利用补码可以把数学运算统一成加法,只要一个加法器就可以实现所有的数学运算。
.IEEE浮点表示
1.用V = (-1)s * M * 2E的形式来表示一个数:
符号:s决定这个数是负数(s = 1)还是正数(s = 0),而对于数值0的符号位解释作为特殊情况处理。
尾数:M是一个二进制小数,它的范围是1 ~ 2-ε,或者是0 ~ 1-ε。
阶码:E的作用是对浮点数据加权,这个权重是2的E次幂(可能是负数)。
2.将浮点数的位表示划分为三个字段,分别对这些值进行编码:
一个单独的符号位s直接编码符号s。
k位的阶码字段exp = ek-1…e1e0编码阶码E。
n位小数字段frac = fn-1…f1f0编码尾数M,但是编码出来的值也依赖于阶码字段的值是否等于0。
3.两种常见的格式
c语言中的单精度浮点格式float 和双精度浮点格式double。
在float中,s、exp和frac字段分别为1位、k = 8 位和n = 23位,得到一个32位的表示;
在double中,s、exp和frac字段分别为1位、k = 11 位和n = 52位,得到一个64位的表示。
课后作业:
2.69用C语言编写一个程序实现屏蔽与错位组合,规定机器为32位,并且实现循环移位
主要思路:
1.用相应的按位实现需要数值位置以外的屏蔽
2根据题目要求,要实现数据的循环移位就需要将原来屏蔽的字节补到相应的数据前面,在这先设一个移位变量n,对所要进行的数据(设为X)进行x<<n,将保留X的前n位数值
3.将可以进行屏蔽的数据X进行x>>(32-n)操作,因为设定的是32位机器,并且在声明变量的时候用的是unsigned int 长度位32位,所以x必定为32位数据,对其进行移位可以得到要补到前面的数据
4.将得到的X错位相加
5.输出十六进制数Z即可
注意问题:
1.由于机器所要求的是32位,所以在设置数据时,应该注意避免出现溢出的情况,即x应该是小于或等于8位的,在这里有个小瑕疵,并没有对输入的x进行输入正确性的判断,这里可以改进为多加一个if(x>0&&x<100000000)并循环至输入正确,不过x已经被定义为8位,所以即使没有输入判断,系统也会提示报错
2.相与操作为无符号数进行,需要unsigned定义
3.输出需要以16进制输出,需要将10进制结果转换一下
相应代码如下: