信息安全系统设计基础第三周学习总结

信息的表示和处理

一、gcc 编译

使用C99特性时 gcc -std=c99 xxx.c 实验楼环境为64位,编译为32位机器码: gcc -m32 xxx.c

二、 教材导读

三种数字:

无符号(unsigned)编码基于传统的二进制表示法,表示大于或者等于零的数字。

补码(two’s-complement)编码是表示有符号整数的最常见的方式,有符号整数就是可以为正或者为负的数字。

浮点数(?oating-point)编码是表示实数的科学记数法的以二为基数的版本。

信息安全系同学从逆向角度考虑为什么会产生漏洞?

会产生溢出。

溢出:计算机的表示法是用有限数量的位来为一个数字编码,因此当结果太大就会导致某些运算溢出。

整数和浮点数会有不同的数学属性是因为:处理数字表示有限性的方法不同:

      整数:编码相对较小的数值范围,但精确度高

      浮点数:编码较大范围的数,但这种表示是近似的

信息的存储:

十六进制,二进制,十进制的转换:学过了。

字:台计算机都有一个字长(word size),指明整数和指针数据的标称大小(nominal size)。因为虚拟地址是以这样的一个字来编码的,所以字长决定的最重要的系统参数就是虚拟地址空间的最大大小。也就是说,对于一个字长为w位的机器而言,虚拟地址的范围为0~2w-1,程序最多访问2w个字节。现在计算机多为32和64位。

gcc -m32 可以在64位机上(比如实验楼的环境)生成32位的代码。

寻址和字节顺序

按照从最高有效字节到最低有效字节的顺序存储。前一种规则—最低有效字节在最前面的方式,称为小端法。大端法与之相反。

 字节顺序是网络编程的基础,记住小端是“高对高、低对低”,大端与之相反就可以了。

使用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语言还提供了一组逻辑运算符 ||、&&和!,分别对应于命题逻辑中的OR、AND和NOT运算。

C语言中的移位运算

C语言还提供了一组移位运算,以便向左或者向右移动位模式。对于无符号数据(也就是以限定词unsigned声明的整型对象),右移必须是逻辑的。而对于有符号数据(默认的声明的整型对象),算术的或者逻辑的右移都可以。

与移位运算有关的操作符优先级问题

常常有人会写这样的表达式1<<2+3<<4,其本意是(1<<2)+(3<<4)。但是在C语言中,前面的表达式等价于1<<(2+3)<<4,这是由于加法(和减法)的优先级比移位运算要高。然后,按照从左至右结合性规则,括号应该是这样打的(1<<(2+3))<<4,因此得到的结果是512,而不是期望的52。

补码编码

利用补码可以把数学运算统一成加法,只要一个加法器就可以实现所有的数学运算。

有符号数还有两种标准的表示方法:

反码(Ones’ Complement):除了最高有效位的权是-(2w-1-1)而不是-2w-1,它和补码是一样的。

原码(Sign-Magnitude):

最高有效位是符号位,用来确定剩下的位应该取负权还是正权。

C语言中的有符号数和无符号数

由于C语言对同时包含有符号和无符号数表达式的这种处理方式,出现了一些奇特的行为。当执行一个运算时,如果它的一个运算数是有符号的而另一个是无符号的,那么C语言会隐式地将有符号参数强制类型转换为无符号数,并假设这两个数都是非负的,来执行这个运算。就像我们将要看到的,这种方法对于标准的算术运算来说并无多大差异。

.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位的表示。

 学习中的问题:

(1)关于溢出:

由于C/C++语言所固有的缺陷,既不检查数组边界,又不检查类型可靠性,且用C/C++语言开发的程序由于目标代码非常接近机器内核,因而能够直接访问内存和寄存器,只要合理编码,C/C++应用程序在执行效率上必然优于其它高级语言。然而,C/C++语言导致内存溢出问题的可能性也要大许多。

改进方法:在输出时检测是否溢出。

 

posted on 2015-10-03 21:26  20135237朱国庆  阅读(186)  评论(0编辑  收藏  举报