Lazy loaded image
😃基于《CSAPP》的计算机组成原理内容回顾
字数 2595阅读时长 7 分钟
2024-12-15
2025-1-2
type
status
date
slug
summary
tags
category
icon
password
😀
为了学习计算机组成原理,这里将基于《CSAPP》这本书,回顾从第一章到第四章的内容,外加上自己的一点理解
 

😄第一章: 计算机系统漫游

从最简单的hello, world开始
这里我们跟随hello程序的生命周期 — 创建,在系统运行,输出信息,终止; 来介绍一些关键概念、专业术语和组成部分
 

1.1 信息 = 位 + 上下文

  • 比特和位: 源程序由一个0和1组成的位序列(比特序列), 8个位构成一个字节。每个字节表示程序中的某些字符
  • 上下文: 一个基本思想 → 系统中的所有信息都是由一串比特表示的;区别不同的数据对象唯一办法就是看上下文。因为同样一个字节序列可能可以表示整数、浮点数、字符串或机器指令。
review: 1 byte = 8 bit
所以这里就涉及到了数据的存储,比如整数、浮点数和负数在系统的表现形式;这方面在第二章详细展开。
 

1.2 程序的翻译

当我们想把hello.c在系统上运行时,因为C语言是高级语言,我们人能读懂,但是系统只能看懂二进制的位序列。所以我们要把每一条C语句翻译成低级的机器语言指令,然后将这些指令按照‘可执行目标程序’的格式打包成二进制磁盘文件的格式存放起来。一般所用gcc编译器来实现以上操作。
 
翻译的过程可分为四个阶段: 1.预处理阶段 → .i 2.编译阶段 → .s 3.汇编阶段 → .o 4.链接阶段 → 可执行文件
 
  • 预处理阶段.i(文本)
    • 预处理器(cpp)根据#开头的命令来修改原始的C程序:把#include 的内容插入程序中,生成修改后的文本,通过.i结尾
  • 编译阶段.s(文本)
    • 编译器(ccl)将.i文本翻译成汇编语言.s
  • 汇编阶段.o(二进制)
    • 汇编器(as)将文本.s翻译成二进制的机器语言指令,并且把这些指令打包成‘可重定向目标程序 ’,英文叫‘relocatable object program’。
  • 链接阶段(二进制)
    • 链接器(ld)负责合并一些我们在源代码中调用的系统内置函数(也是.o形式的),然后得到可执行目标文件,之后加载到内存中被系统执行
💡
这里我们看看这些英文缩写是什么?
  • cpp → "C PreProcessor"(C预处理器)
  • ccl → C Compiler
  • as → assembler
  • ld → Linker ld
 

1.3 计算机硬件的基本组成

“存储程序” — 将指令以二进制形式事先输入计算机的主储存器
notion image
冯诺依曼计算机特点:
  • 【计算机硬件五大部件】储存器、运算器、控制器、I/O设备
  • 二进制代码表示指令数据
  • 计算机采用储存程序的工作方式
  • 指令和数据以同等地位存储在存储器内,并且按地址查找
  • 指令由操作码和地址码组成
  • 以运算器为中心
这种计算机的运行是围绕运算器进行的,运算效率不高,存储器和输出设备都要经过运算器
现代计算机特点:
notion image
  • 以存储器为中心
  • 运算器+控制器 = CPU
notion image
  • 主存:也就是我们俗称的运存
  • 辅存:电脑里面的机械硬盘属于I/O设备
  • 程序运行的时候,将代码从辅存读取到主存里面
  • 主机:CPU(运算器+控制器)+ 主存
考点:
notion image
 

 

🤔第二章: 信息的表示和处理

我们在上一章节留了一个坑,也就是整数、负数和浮点数在系统中如何表示?
在这一章节我们主要研究三种重要的数字表示:
  • 无符号(unsigned)编码 → 表示≥0的数字
  • 补码(two’s-complement)编码 → 表示可以是正负(有符号)的整数
  • 浮点(floating-point)数 → 表示实数的科学计数法的二进制版本
 

2.1 信息存储

/导论/ 在大多数的计算机中,一般用8个比特位(1个字节)来表示最小的可寻址的内存单元。机器级程序中将内存视做一个超大的字节数组,称之为虚拟内存。每个虚拟内存都有一个唯一的数字来标识,称之为地址
 

2.1.1 十六进制表示法(hexadecimal)

我们想表示一个字节(8位),当我们用二进制表示的时候,值域是 。这样我们要表示一个字就要八位数字来表示,未免有点太长了。那转换成10进制的话就是 ,但是十进制的转换又太麻烦了。这就有了十六进制!因为在十六进制里表示一个字节的值域是 ,只需要两个位就可以表示一个字,而且和二进制转化也方便.
图2-2
十六进制
0
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
十进制
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
二进制
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
 
  • 十六进制和二进制的转化
    • 直接转换法: 从低位向高位每四个分一组,高位不够四个补0,然后每组对应写成对应的16进制即可
      • 0x173A4C → 0001 0111 0011 1010 0100 1100
    • 转换法: 当x是时,x的二进制就是1后面➕n个0,然后再用第一种方法转换
      • n=9 → 0010 0000 0000 → 0x200
    • 中的n可以表示成为 的形式的时候,写成十六进制,1(i=0),2(i=1),4(i=2),8(i=3)➕j个十六进制的0
    • 当然也可以用最简单的短除法 → 每次除于16取余数,直到结果为0,然后从下往上写余数
  • 十六进制的加减法
    • 和十进制相似
 

2.1.2 字数据大小

每个机器都有固定的字长(word size),用来指明指针数据的标称大小(nominal size)
在32位和64位的机器中一些数据类型的大小是不一样的,在ISO C99中引入了int32_t和int64_t,它们不随着机器和编译器变化大小,分别对应4字和8字。
 

2.1.3 寻址和字节顺序

 
 

🤯第三章: 程序的机器级表示

 

3.2 程序编码

3.2.1 机器级代码

在前面的章节中讲过,计算机系统采用了多种不用形式的抽象,利用更加简单的抽象模型来隐藏复杂的实现细节。对于机器级编程,用两种抽象尤为重要。
  1. 机器级程序的格式和行为指令集体系架构(Instruction set architecture, ISA)
    1. 它定义了处理器的状态、指令的格式,以及每个指令对于状态的影响
  1. 机器级程序使用的存储器地址是虚拟地址,类似一个超大的字节数组
 
!在ISA32中,通常对程序员隐藏的处理器状态是可见的:
  • 程序计数器(PC):用%eip这个寄存器来存储下一条要执行的指令地址
  • 整数寄存器文件: 在ISA32中有8个,分别存储32位的值
  • 条件码寄存器: 保存最近执行的算数或逻辑指令的状态信息。用它们来实现控制或数据流中的条件变化
  • 一组浮点寄存器存放浮点数据
😶‍🌫️
这里插一嘴,汇编代码不区分有无符号整数,不区分各种类型的指针,甚至不区分指针和整数。
 

3.2.2 在Linux上面对C语言的各种操作

在Linux中我们使用gcc这个编译器来编译C源代码,如果你的Linux上面没有自带gcc可以输入”sudo apt install gcc”来下载
我们现在有一个C语言代码:
  • 几种gcc命令
    • gcc -O1 -S code.c → 产生一个汇编文本code.s
    • gcc -O1 -c coed.c → 编译并且汇编,生成一个code.o的二进制目标代码文件
    • gcc -O1 -o [name] code.c main.c → 生成一个可执行文件
  • 使用”objdump -d [name]” 可以反汇编文件
notion image
接下来我们就会主要讲各种对于寄存器的操作
 

3.3 数据格式

 
  • 图3-1⬇️
C声明
Intel 数据类型
汇编后缀
大小(字节)
char
字节
b
1
short
w
2
int
双字
l
4
long int
双字
l
4
long long int
——
——
4
char *
双字
l
4
float
单精度
s
4
double
双精度
l
8
long double
扩展精度
t
10/12
这里的’字(word)’一般是指16位的数据类型
 

3.4 访问信息

在一个IA32中央寄存器处理单元(CPU)中,包含8个存储32位值的寄存器(register)。 这些寄存器用来存储整数数据和指针。❗️注意: %eip不在这里,它是PC,不能用于存储数据
图3-2 8个寄存器,其中%esp和%ebp是栈顶指针和栈底指针
图3-2 8个寄存器,其中%esp和%ebp是栈顶指针和栈底指针

3.4.1 操作数指令符

🧐
IA32的操作数共有3种格式:
  1. $ → 立即数(immediate)
  1. → 从寄存器(register) 中取出值
  1. → 从存储器(memory) Addr 地址中拿出b个字节值
  • !寻址模式!
notion image

最常用 →
 

3.4.2 数据传输指令 - MOV类

指令名字 + 传输字节大小 ⇒ 指令 b → 1 byte w → 2 byte l → 4 byte
notion image
 
 
 

📎参考文章

  • 《Compter Systems A Programmer’s Perspective》- third edition
  • 《Compter Systems A Programmer’s Perspective》- second edition
 
💡
欢迎您在底部评论区留言,一起交流~
 
上一篇
算法总复习
下一篇
Python 的数据类型

评论
Loading...