CSAPP笔记-第二章 信息的表示和处理

前言

我在读书时养成的习惯,先读目录,了解文章大体结构,知道每章每节主要讲了哪些内容,把每个章节的结构理清楚,我必须得让自己的逻辑清楚,要不就觉得知识点很乱,必须理清!本科期间,在课上听老师讲完后,课下根据自己的思路理清书本后,记一遍笔记(本人喜欢动手记笔记),大部分知识点都能记住。现在,改用博客的形式记笔记,还有点不习惯,个人感觉效果不如动手记笔记好。可能每个人的学习方法不同吧。
博客记笔记有个优点就是可以随意查阅,并且不害怕丢,也不占地方,有想法的时候或者自己认为有意义的内容都可以在这里记录,就像一个电子笔记本。
废话说了这么多,进入正题。
最近在忙毕业论文的事,抽空读点书,接下来会继续在本篇博客更新第二章的学习内容。

第二章 信息的表示和处理

这一章主要讲信息在计算机中的存储(通过编码的方式把不同的数据转换成机器能识别的形式),以及各种类型的数在计算机中如何运算。
主要介绍三种重要的数字表示:
(1)无符号编码基于传统的二进制表示法,表示大于或者等于零的数字
(2)补码编码是表示有符号整数的最常见的方式,有符号整数就是可以为正或者为负的数字
(3)浮点数编码是表示实数的科学计数法的以2为基数的版本

现代计算机存储和处理的信息以二值(即0和1)信号表示。
二值信号能够很容易地被表示、存储和传输。
二进制数字被称为“位”。
通常,单个的位不是非常有用,可以用位的组合来编码文档中的字母和符号。
计算机的表示法是用有限数量的位来对一个数字编码,所以,当结果太大以至于不能表示时,某些运算就会溢出。

本章结构:

  • 信息存储(寻址、字符串与代码的表示、c语言的位级运算、逻辑运算和移位运算)
  • 整数表示(有符号数、无符号数,补码表示)
  • 整数运算(无符号加法、补码的加法、补码的非、无符号乘法、补码乘法、乘以常数、除以2的幂)
  • 浮点数(浮点表示、舍入、浮点运算、C语言中的浮点数)

信息存储

大多数计算机使用字节(8个二进制位)作为最小的可寻址的内存单元,而不是访问内存中单独的位。内存的每个字节都由一个唯一的数字来标识,称它为地址。

  1. 十六进制表示法

一个字节由8位组成。
二进制表示法的值域:00000000-11111111
十进制表示法的值域:0-255
十六进制表示法的值域:00-FF
为什么用十六进制?
答:二进制表示法太冗长,十进制表示法与位模式的互相转化很麻烦,所以用十六进制数来表示位模式。
十六进制数字在C语言中一般以0x或者0X开头,字符‘A’-‘F’不区分大小写。

  1. 字数据大小

计算机的字长决定了系统的地址空间大小,比如对于一个字长为n位的机器而言,虚拟地址的范围是0-2^n-1,程序最多访问2^n个字节。

【疑问】:一个字长是n位,就是说系统一次可以处理的数据位数是n位,那么就又2^n个01表示方式,即有2^n个地址,那为什么说程序最多访问2^n个字节呢???1字节=8位,那不就是2^n*8位了吗????


20190511更
继昨天的内容:今天查看了一下之前学的计算机组成原理关于这部分的内容,机器字长是指CPU一次能处理数据的位数,字长越长,数的表示范围越大,精度越高。寻址范围与存储容量有关。
【例如】:
计算机字长16位,其存储容量为4MB,若按字节编址的寻址范围是多少?
存储容量转成位:4MB=2^22B=2^22*8b
按字节寻址即一个字节为一个地址,1字节=8位,则寻址范围是:(2^22*8)/8=2^22

大多数64位机器也可以运行32位机器编译的程序,这是一种向后兼容。
【举例】
当程序prog.c用如下伪指令编译后
Linux> gcc -m32 prog.c
该程序就可以在32位或64位机器上正确运行。若程序用下述伪指令编译:
linux> gcc -m64 prog.c
那就只能在64位机器上运行。
将程序称为“32位程序”或“64位程序”时,区别在于该程序是如何编译的而不是其机器运行。

  1. 寻址和字节顺序

(1)一个程序对象是多字节时,必须建立两个规则:
a.这个对象的地址是什么?
b.内存中如何排列这些字节?
答:
a.在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址。
【例如】
假设数据类型int为32位表示,x的地址为0x100,那么x的四个字节将被存储在内存的0x100、0x101、0x102、0x103位置。
b.内存中存储对象时分为小端法和大端法。(字节顺序)
小端法:按照从最低有效字节到最高有效字节的顺序存储对象
大端法:按照从最高有效字节到最低有效字节的顺序存储对象
【例如】
假设变量x的类型为int,位于地址0x100处,它的十六进制值为0x01234567。地址范围0x100-0x103的字节顺序如下:
小端法:
0x100:67 0x101:45 0x102:23 0x103:01
大端法:
0x100:01 0x101:23 0x102:45 0x103:67
(2)字节顺序的重要性
a.在不同类型的机器之间通过网络传送二进制数据时。
字节顺序对于程序员来说是不可见的,但是在不同类型的机器之间通过网络传送二进制数据时,当小端法机器产生的数据被发送到大端法的机器或者反过来时,接收程序会发现,字里的字节成了反序的。解决办法是网络应用程序的编写必须遵守已建立的关于字节顺序的规则,发送方和接收方的机器都得将它们的内部表示转换成网络标准。
b.当阅读表示整数数据的字节序列时(通常发生在检查机器级程序时)
【举例】
给出了一个机器级代码的文本表示
4004d3: 01 05 43 0b 20 00 add %eax,0x200b43(%rip)
意思是:十六进制字节串 01 05 43 0b 20 00 是一条指令的字节级表示,这条指令是进行加法运算,把一个字长的数据加到一个值上,该值的存储地址由0x200b43加上当前PC的值得到。如果取出这个序列的最后四个字节:43 0b 20 00,并且将其反序,得到00 20 0b 43,去掉开头的0,得到值0x200b43,这就是右边的值。
当阅读像此类小端法机器生成的机器级程序表示时,经常会将字节按照相反的顺序显示。
c.当编写规避正常的类型系统的程序时
C语言中可以通过使用强制类型转换或联合来允许以一种数据类型引用一个对象,而这种数据类型与创建这个对象时定义的数据类型不同。
在不同的系统上,除了字节顺序不同外,数值的结果是一样的。

  1. 表示字符串

C语言中字符串被编码为一个以null(值为0)字符结尾的字符数组。每个字符都由某个标准编码来表示,最常见的是ASCII字符码。

  1. 表示代码

同一个C函数在不同机器上编译时,生成的机器代码都是不一样的。
【举例】

1
2
3
int sum(int x,int y){
return x+y
}

生成的机器码:
Linux 32:55 89 e5 8b 45 0c 03 45 08 c9 c3
Windows: 55 89 e5 8b 45 0c 03 45 08 5d c3
Linux 64:55 48 89 e5 89 7d fc 89 75 f8 03 45 fc c9 c3
说明不同的机器类型使用不同的且不兼容的指令和编码方式。即时是完全一样的进程,运行在不同的操作系统上也会有不同的编码规则,因此,二进制代码是不兼容的。


文章目录
  1. 1. 前言
  2. 2. 第二章 信息的表示和处理
    1. 2.1. 信息存储