《深入理解计算机系统》——信息的表示和处理(个人总结)(第二章)

2.1 信息存储

大多数计算机使用8位的块,或者字节(byte),作为最小的可寻址的内存单位,而不是访问内存中单独的位。机器级程序将内存视为一个非常大的字节数组,称为虚拟内存(virtual memory)。内存的每个字节都有一个唯一的数字来标识,称为它的地址(address),所有可能地址的集合就称为虚拟地址空间(virtual address space )。

计算机每个地址的存储容量是1字节。‌计算机存储器中的每个存储单元都有一个唯一的地址,这个地址用于标识存储单元的位置。每个存储单元存放的数据量,即存储容量,通常以字节(Byte)为单位。比如说一层房子有10个房间,一个房间有10个人,房间号是101到110。房间号就相当于地址,10个人就是内存的字节,10*10=100就是内存的大小。这里说的地址是物理地址。

虚拟地址空间‌,也称为虚拟内存空间,是操作系统为每个进程分配的一个独立的4G虚拟内存空间(从地址0到0xFFFFFFFF)。这个空间并不意味着进程将会有4G的物理内存,而是一个虚拟的地址范围。虚拟内存空间被分为大小相同的页,这些页或者被映射到物理内存,或者被映射到硬盘上的交换文件,或者什么也不映射。虚拟内存的基本思想是将计算机的RAM和硬盘上的临时空间组合在一起,当RAM运行速度缓慢时,虚拟内存可以将数据从RAM移动到称为“分页文件”的空间中,从而释放RAM以便完成工作。这种技术允许操作系统更有效地管理内存资源,尤其是在物理内存不足的情况下。‌

2.2 关于指针和字长

2.2.1 字长

‌字长是计算机系统结构中的一个重要指标,它直接决定了计算机一次能处理的数据量,影响着计算机处理数据的能力、硬件造价及机器运行速度。‌

字长在计算机结构和操作中占据重要位置,它关系到CPU与内存之间的数据传送、寄存器大小以及处理的典型数值等基本单位。字长还与存储字长和指令字长有关。存储字长是计算机存储器中一个存储单元可以存储的位数,而指令字长则是计算机内一条指令的位数。

字长代表了机器的寻址能力,进而限定了寻址空间的大小。具体来说,字长w位的机器可以表示的虚拟内存的范围是0到2w−12w−1。例如,32位字长的机器可以表示的虚拟内存范围是4GB。这是因为32位机器的虚拟地址空间为4GB,这与字长的概念是一致的。此外,长整数(long int)和指针的大小都是字长,意味着在32位机器上,它们的大小是32位,而在64位机器上,它们的大小是64位。

以上面房间为例,字长就是房间号的长度。比如说给出一个数字10607,我们已经知道房间号是三位,那么后面的07就是数据部分(人)。‌字长可以区分内存数据的边界。

2.2.2 数据和数据类型以及指针

数据是指能输入到计算机中并能被计算机处理和加工的对象。它可以包括数值、文字、图像、声音等多种形式,是信息的载体,用于描述客观事物的属性、数量、位置及其相互关系。数据可以是连续的值(如声音、图像)或离散的值(如符号、文字),并且在计算机系统中,数据通常以二进制信息单元0和1的形式表示‌

在计算机科学中,常用的数据类型可以分为以下几类:

数值类型

    • 整数类型:包括有符号整数(如short, int, long, long long)和无符号整数,用于存储正数、负数和零。
    • 浮点类型:分为单精度浮点数(float)和双精度浮点数(double),用于存储具有小数部分的数值。
    • 布尔类型:用于存储逻辑值,即真(true)或假(false)。

字符类型:用于存储单个字符或字母,通常占用一个字节或更少的存储空间。

文本类型

    • 字符串类型:用于存储文本数据或字符序列,可以包含字母、数字、符号和其他字符。

特殊类型

    • 空值或null:表示没有值或没有对象引用的特殊状态。
    • 枚举类型:用于定义一组命名的常量和相关数据类型。
    • 结构体类型:用于组合不同类型的数据元素,形成一个新的数据类型。

其他类型

    • 指针类型:用于存储内存地址的变量,通常用于动态内存分配和函数参数传递。
    • 联合体类型:类似于结构体,但所有成员共享同一块内存空间,只能同时使用其中一个成员。

这里简单说一下指针,在C语言中,指针是一个重要的概念,它指的是内存中的一个地址,这个地址是内存单元的编号。指针变量是用来存放内存地址的变量,通过指针可以间接访问存储在计算机内存中的数据。指针、指针变量和地址三者之间的关系可以理解为:指针其实就是地址,而指针变量是用来保存这个地址的变量。换句话说,指针变量存储的是另一个变量的内存地址,通过这个地址可以访问到该内存地址对应的数据。这种通过地址访问数据的方式在计算机程序中非常常见,它提高了程序的灵活性和效率。

*表示这是一个指针变量

例如:char *P,就是说P是一个指针(即一个地址,就像前面说的房间号),P指向的对象是一个类型为char的数据(char就是地址P的内容,就像前面说的房间里的人)。

为什么要使用指针呢?指针的用途和有点:

  1. ‌直接访问内存‌:想象你住在一个巨大的公寓楼里,每个房间都有一个独特的门牌号。每个房间代表内存中的一个存储位置,门牌号就像是内存地址。指针就像是一张包含门牌号的纸条,它告诉你怎么找到那个房间。

  2. ‌提高程序效率‌:假设你是一个快递员,需要递送一个非常重的包裹。你可以选择搬运整个包裹,或者仅仅告诉收件人包裹所在的仓库和位置。提供位置信息更加高效。

  3. ‌动态内存分配‌:想象你正在组织一场聚会,但你不确定有多少人会来。使用指针可以在运行时根据需要申请或释放内存空间。

  4. ‌数组和字符串处理‌:字符串实际上是字符数组,通常通过字符指针来操作。数组名在大多数上下文中退化为指向其第一个元素的指针,这使得使用指针遍历数组变得很自然。

2.3 反汇编器和强制类型转换

2.3.1 强制类型转换

当操作数的类型不同,而且不属于基本数据类型时,经常需要将操作数转化为所需要的类型,这个过程即为强制类型转换。强制类型转换具有两种形式:显式强制转换和隐式强制类型转换。

一条指令通常包含两方面的信息:操作码和操作数。‌ 操作码决定要完成的操作,而操作数指参加运算的数据及其所在的单元地址。

1、显式强制类型转换

C中显式强制类型转换很简单,格式如下:

TYPE b = (TYPE) a;

其中,TYPE为类型描述符,如int,float等。经强制类型转换运算符运算后,返回一个具有TYPE类型的数值,这种强制类型转换操作并不改变操作数本身,运算后操作数本身未改变,例如:

int n=0xab65;

char a=(char)n;

上述强制类型转换的结果是将整型值0xab65的高端一个字节删掉,将低端一个字节的内容作为char型数值赋值给变量a,而经过类型转换后n的值并未改变。

C++中强制类型转换函数有4个:const_cast(用于去除const属性),static_cast(用于基本类型的强制转换),dynamic_cast(用于多态类型之间的类型转换),reinterpreter_cast(用于不同类型之间的指针之间的转换,最常用的就是不同类型之间函数指针的转换)。

2、隐式强制类型转换

隐式类型转换发生在赋值表达和有返回值的函数调用表达式中。在赋值表达式中,如果赋值符左右两侧的操作数类型不同,则将赋值符右边操作数强制转换为赋值符左侧的类型数值后,赋值给赋值符左侧的变量。在函数调用时,如果return后面表达式的类型与函数返回值类型不同,则在返回值时将return后面表达式的数值强制转换为函数返回值类型后,再将值返回,如:

int n;

double d=3.88;

n=d;//执行本句后,n的值为3,而d的值仍是3.88。

2.3.2 反汇编器

反汇编器是一种工具程序,可以将机器代码转换为目标处理器专用的汇编代码或汇编指令。将机器代码转换为汇编代码的过程称为反汇编。

反汇编在软件逆向分析中发挥着重要作用。通过将目标代码转换为汇编代码,可以更好地理解软件的运行机制,特别是在破解软件注册、分析病毒和行为、以及修改软件功能方面。

在动态分析和静态分析中,反汇编器也扮演着关键角色。动态分析是在控制的环境下执行程序,并记录其行为,而静态分析则是直接浏览程序代码来理解其行为。这两种方法都需要反汇编器来将机器语言转换为汇编语言,以便进行分析‌。

2.4 有无符号数和补码

在计算机中,有符号数和无符号数的表示方法有所不同,主要区别在于符号位的处理和数值位的表示。

1、有符号数使用最高位作为符号位,其中0表示正数,1表示负数。其余位表示数值大小。有符号数常用的编码方式包括:

  • 原码‌:将符号位放在最高位,正数符号位为0,负数符号位为1。

  • 反码‌:正数的反码与原码相同,负数的反码符号位不变,其余位取反。

  • 补码‌:正数的补码与原码相同,负数的补码是其反码加1。

例如,8位二进制数中:

  • +127的原码为01111111,补码也为01111111。

  • -128的原码为11000000,反码为10111111,补码为10000000。

2、无符号数的所有位都用于表示数值大小,没有专门的符号位。无符号数常用的编码方式包括:

  • 原码‌:无符号数的原码就是其二进制表示,所有位都表示数值大小。

  • 反码‌:无符号数的反码也是其二进制表示。

  • 补码‌:无符号数的补码同样是其二进制表示。

例如,8位二进制数中:

  • 0~255的范围(00000000~1111111)表示所有无符号数的可能值。

计算机中使用补码的主要原因是为了简化计算机的设计。‌补码运算能把减法转化为加法来完成,从而使得运算器中不需要配置减法电路,节省了硬件线路,简化了运算器的设计‌。

补码的使用可以统一处理符号位和数值位,使得加法和减法可以统一处理。在计算机系统中,数值一律用补码来表示和存储。使用补码可以将符号位和数值域统一处理,同时减法也可以通过加法来实现,这样简化了运算器的设计‌。

此外,补码的引入还解决了计算机中表示负数的问题。由于计算机的运算器只有加法器,没有减法器,所以减法需要通过加法来实现。补码通过将负数表示为正数的补码,使得减去一个数可以转化为加上这个数的补码,从而解决了负数的表示和运算问题‌。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值