type
status
date
slug
summary
tags
category
icon
password
为了学习计算机组成原理,这里将基于《CSAPP》这本书,回顾从第一章到第四章的内容,外加上自己的一点理解
😄第一章: 计算机系统漫游1.1 信息 = 位 + 上下文1.2 程序的翻译1.3 计算机硬件的基本组成🤔第二章: 信息的表示和处理2.1 信息存储2.1.1 十六进制表示法(hexadecimal)2.1.2 字数据大小2.1.3 寻址和字节顺序🤯第三章: 程序的机器级表示3.2 程序编码3.2.1 机器级代码3.2.2 在Linux上面对C语言的各种操作3.3 数据格式3.4 访问信息3.4.1 操作数指令符3.4.2 数据传输指令 - MOV类 📎参考文章
😄第一章: 计算机系统漫游
从最简单的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 计算机硬件的基本组成
“存储程序” — 将指令以二进制形式事先输入计算机的主储存器

冯诺依曼计算机特点:
- 【计算机硬件五大部件】储存器、运算器、控制器、I/O设备
- 二进制代码表示指令和数据
- 计算机采用储存程序的工作方式
- 指令和数据以同等地位存储在存储器内,并且按地址查找
- 指令由操作码和地址码组成
- 以运算器为中心
这种计算机的运行是围绕运算器进行的,运算效率不高,存储器和输出设备都要经过运算器
现代计算机特点:

- 以存储器为中心
- 运算器+控制器 = CPU

- 主存:也就是我们俗称的运存
- 辅存:电脑里面的机械硬盘(属于I/O设备)
- 程序运行的时候,将代码从辅存读取到主存里面
- 主机:CPU(运算器+控制器)+ 主存
考点:

🤔第二章: 信息的表示和处理
我们在上一章节留了一个坑,也就是整数、负数和浮点数在系统中如何表示?
在这一章节我们主要研究三种重要的数字表示:
- 无符号(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 机器级代码
在前面的章节中讲过,计算机系统采用了多种不用形式的抽象,利用更加简单的抽象模型来隐藏复杂的实现细节。对于机器级编程,用两种抽象尤为重要。
- 机器级程序的格式和行为 → 指令集体系架构(Instruction set architecture, ISA)
- 它定义了处理器的状态、指令的格式,以及每个指令对于状态的影响
- 机器级程序使用的存储器地址是虚拟地址,类似一个超大的字节数组
!在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]” 可以反汇编文件

接下来我们就会主要讲各种对于寄存器的操作
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.4.1 操作数指令符
IA32的操作数共有3种格式:
- $ → 立即数(immediate)
- → 从寄存器(register) 中取出值
- → 从存储器(memory) Addr 地址中拿出b个字节值
- !寻址模式!

最常用 →
3.4.2 数据传输指令 - MOV类
指令名字 + 传输字节大小 ⇒ 指令 b → 1 byte w → 2 byte l → 4 byte

📎参考文章
- 《Compter Systems A Programmer’s Perspective》- third edition
- 《Compter Systems A Programmer’s Perspective》- second edition
欢迎您在底部评论区留言,一起交流~
- 作者:PanDa
- 链接:Panda_Clog | 代码Vlog (c.pandaclog.xyz)/article/15d0312b-e533-80e5-afaa-eb46f1e76bbb
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。