CSAPP《深入理解计算机系统》深读笔记2——第二章-信息的表示和处理(上)

本文主要是介绍CSAPP《深入理解计算机系统》深读笔记2——第二章-信息的表示和处理(上),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CSAPP《深入理解计算机系统》深读笔记2——第二章-信息的表示和处理(上)

请添加图片描述
你好我是拉依达,这是我秋招结束后更新的第一个系列。我将争取完成“ 年轻人,你渴望力量吗?”的全套深度笔记。
今天开始进行第一本CSAPP:深入理解计算机系统。

信息存储

最小的可寻址内存单位:8位的块(字节byte)

机器级程序将内存视为一个非常大的字节数组,称为虚拟内存( virtual memory)

内存的每个字节都由一个唯一的数字来标识,称为它的地址(address),所有可能地址的集合就称为虚拟地址空间( virtual address space)

顾名思义,这个虚拟地址空间只是一个展现给机器级程序的概念性映像

实际的实现是将动态随机访问存储器(DRAM)、闪存、磁盘存储器、特殊硬件和操作系统软件结合起来,为程序提供一个看上去统一的字节数组。

十六进制表示法

十六进制(简写为“hex”):使用数字“0’~“9’ 以及字符‘A‘~‘F’来表示16个可能的值。

用十六进制书写,一个字节的值域为0016 ~FF 16。C语言中,以0x或0X开头的数字常量被认为是十六进制的值。字符‘A’~‘F‘ 既可以是大写,也可以是小写。

十六进制表示法

字数据大小

计算机字长(word size),指明指针数据的大小。虚拟地址是用一个字编码,字长决定虚拟地址的空间大小

对一个字长为n的机器,虚拟地址范围0~2n-1,最多访问2n个字节。

32位机器地址空间为4GB,64字节为16EB,实际上64字节使用48位,也就是256TB。

大多数64位机器可以兼容32位程序

//编译成32 64位程序
linux > gcc -m32 prog.c
linux > gcc -m64 prog.c

计算机和编译器支持多种不同方式编码的数字格式,如不同长度的整数和浮点数。

比如,许多机器都有处理单个字节的指令,也有处理表示为2字节、4字节或者8字节整数的指令,还有些指令支持表示为4字节和8字节的浮点数。

C语言数据类型大小

为了避免由于依赖“典型”大小和不同编译器设置带来的奇怪行为,ISOC99引入了一类数据类型,其数据大小是固定的,不随编译器和机器设置而变化。其中就有数据类型int32t和int64t,它们分别为4个字节和8个字节。

使用确定大小的整数类型是程序员准确控制数据表示的最佳途径。

寻址和字节顺序

对于跨越多字节的程序对象,两个规则:

  1. 这个对象的地址是什么
  2. 在内存中如何排列这些字节

在几乎所有的机器上,多字节对象都被存储为连续的字节序列,对象的地址为所使用字节中最小的地址

例如,假设一个类型为int的变量x的地址为0x100,也就是说,地址表达式&x的值为0x100。那么,(假设数据类型int为32位表示)x的4个字节将被存储在内存的0x100、0x101、0x102和0x103位置。

字节排序方式

最低有效字节在最前面的方式,称为小端法( little endian)。
最高有效字节在最前面的方式,称为大端法( big endian)。

假设变量ⅹ的类型为int,位于地址0x100处,它的十六进制值为0x01234567,高字节为0x01,低字节为0x67。地址范围0×100~0x103的字节顺序依赖于机器的类型。

和人类读法相同的是大端

表示字符串

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

“12345”来显示字节,我们得到结果313233343500。在使用 ASCII码作为字符码的任何系统上都将得到相同的结果,与字节顺序和字大小规则无关。因而,文本数据比二进制数据具有更强的平台独立性

表示代码

下面C函数

int sum(int x , int y)
{return x + y;
}

不同编译器,生成如下机器代码:

请添加图片描述

机器代码不同是因为指令编码是不同的。不同的机器类型使用不同的且不兼容的指令和编码方式。即使是完全一样的进程,运行在不同的操作系统上也会有不同的编码规则,因此二进制代码是不兼容的

二进制代码很少能在不同机器和操作系统组合之间移植。从机器的角度来看,程序仅仅只是字节序列。机器没有关于原始源程序的任何信息,除了可能有些用来帮助调试的辅助表以外。

C语言位运算

C语言的一个很有用的特性就是它支持按位布尔运算。以下是一些对char数据类型表达式求值的例子:

C语言逻辑运算

C语言还提供了一组逻辑运算符‖、&&.和!,分别对应于命题逻辑中的OR、AND和NOT运算。
逻辑运算认为所有非零的参数都表示TRUE,而参数0表示 FALSE。它们返回1或者0,分别表示结果为TRUE或者为 FALSE。以下是一些表达式求值的示例:
请添加图片描述

C语言位移运算

C语言还提供了一组移位运算,向左或者向右移动位模式。

  • 向左移动k位,丢弃最髙的k位,并在右端补k个0。
  • 逻辑右移在左端补k个0。
  • 算术右移是在左端补k个最高有效位的值

请添加图片描述

C语言标准并没有明确定义对于有符号数应该使用哪种类型的右移。
实际上,几乎所有的编译器/机器组合都对有符号数使用算术右移、无符号数右移必须是逻辑的。(为了不因为移动变化符号

移动K位,k很大情况:

请添加图片描述

实际上C语言进行取余数运算

因此最后得到如下:

请添加图片描述

整数表示

C语言支持多种整型数据类型。每种类型都能用关键字来指定大小,这些关键字包括charshortlong

唯一一个与机器相关的取值范围是大小指示符long的。大多数64位机器使用8个字节的表示,比32位机器上使用的4个字节的表示的取值范围大很多。

无符号整数编码:

整数编码中,每个位x 都取值为0或1,后一种取值意味着数值2应为数字值的一部分。我们用一个函数B2Uw( Binary to unsigned 的缩写,长度为w)来表示。

补码编码:

表示负数值,编码就是补码(two’ s-complement)形式。将字的最高有效位解释为负权( negativeweight)。我们用函数B2Tw( Binary to Two’ s-complement的缩写,长度为w)来表示。

原码、反码和补码,不同的规则来表示正负号。

  1. 原码(sign-magnitude representation):最高位表示符号位,0表示正数,1表示负数,其余位表示数值大小。例如,+5的原码是00000101,-5的原码是10000101。
  2. 反码(ones’ complement):正数的反码和原码相同,负数的反码是将原码中除符号位外的所有位按位取反。例如,+5的反码是00000101,-5的反码是11111010。
  3. 补码(two’s complement):正数的补码和原码相同,负数的补码是将原码中除符号位外的所有位按位取反后加1。例如,+5的补码是00000101,-5的补码是11111011。

为什么计算机运算基于补码进行,而不是反码?

  1. 加法和减法都是通过对二进制数的补码进行运算来实现的,这样可以将加法和减法转化为相同的运算。
  2. 补码的表示范围与原码相同,而且可以避免原码的符号位运算问题,使得运算更加方便。
  3. 补码还有一个特点,就是它只有一个零,而原码和反码有正零和负零之分
  4. 还能够多表示一个最低数。这就是为什么8位二进制,使用原码或反码表示的范围为[ -127, +127 ],而使用补码表示的范围为[ -128, 127 ]。

原码、反码、补码 详解!_原码反码补码-CSDN博客

有符号和无符号之间转换

short int v = -12345;
unsigned short uv = (unsigned short) v;
printf(" %d %d",v,uv);
// -12345 53191

强制类型转换的结果保持位值不变,只是改变了解释这些位的方式。-12345的16位补码表示与53191的16位无符号表示是完全一样的。将short强制类型转换为 unsigned short改变数值,但是不改变位表示。

C语言中TMin的写法问题?

#define INT_MAX 2147483647
#define INT_MIN      (-INT_MAX -1)

INT_MIN这样写的原因是:

虽然-2147483648 这个数值能够用int类型来表示,但在C语言中却没法写出对应这个数值的int类型常量

因为按照c语言的类型推导,-2147483648被写成常量形式的时候,对于c90,其会转成unsigned类型来表示为2147483648,对于c99,其会被表示为long long类型,值为-2147483648。

这篇关于CSAPP《深入理解计算机系统》深读笔记2——第二章-信息的表示和处理(上)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/549726

相关文章

python处理带有时区的日期和时间数据

《python处理带有时区的日期和时间数据》这篇文章主要为大家详细介绍了如何在Python中使用pytz库处理时区信息,包括获取当前UTC时间,转换为特定时区等,有需要的小伙伴可以参考一下... 目录时区基本信息python datetime使用timezonepandas处理时区数据知识延展时区基本信息

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

一文详解Java异常处理你都了解哪些知识

《一文详解Java异常处理你都了解哪些知识》:本文主要介绍Java异常处理的相关资料,包括异常的分类、捕获和处理异常的语法、常见的异常类型以及自定义异常的实现,文中通过代码介绍的非常详细,需要的朋... 目录前言一、什么是异常二、异常的分类2.1 受检异常2.2 非受检异常三、异常处理的语法3.1 try-

Python使用getopt处理命令行参数示例解析(最佳实践)

《Python使用getopt处理命令行参数示例解析(最佳实践)》getopt模块是Python标准库中一个简单但强大的命令行参数处理工具,它特别适合那些需要快速实现基本命令行参数解析的场景,或者需要... 目录为什么需要处理命令行参数?getopt模块基础实际应用示例与其他参数处理方式的比较常见问http

Java Response返回值的最佳处理方案

《JavaResponse返回值的最佳处理方案》在开发Web应用程序时,我们经常需要通过HTTP请求从服务器获取响应数据,这些数据可以是JSON、XML、甚至是文件,本篇文章将详细解析Java中处理... 目录摘要概述核心问题:关键技术点:源码解析示例 1:使用HttpURLConnection获取Resp

使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)

《使用Python从PPT文档中提取图片和图片信息(如坐标、宽度和高度等)》PPT是一种高效的信息展示工具,广泛应用于教育、商务和设计等多个领域,PPT文档中常常包含丰富的图片内容,这些图片不仅提升了... 目录一、引言二、环境与工具三、python 提取PPT背景图片3.1 提取幻灯片背景图片3.2 提取

Java中Switch Case多个条件处理方法举例

《Java中SwitchCase多个条件处理方法举例》Java中switch语句用于根据变量值执行不同代码块,适用于多个条件的处理,:本文主要介绍Java中SwitchCase多个条件处理的相... 目录前言基本语法处理多个条件示例1:合并相同代码的多个case示例2:通过字符串合并多个case进阶用法使用

Java实现优雅日期处理的方案详解

《Java实现优雅日期处理的方案详解》在我们的日常工作中,需要经常处理各种格式,各种类似的的日期或者时间,下面我们就来看看如何使用java处理这样的日期问题吧,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言一、日期的坑1.1 日期格式化陷阱1.2 时区转换二、优雅方案的进阶之路2.1 线程安全重构2