CSAPP
读书笔记(一)
依据它的原意Computer System A Programmer’s Perspective, 这本书的中翻<深入理解计算机系统>意思并不对, 它并不深入, 但是却足够广泛, 适合入门, 因为它是
CMU
的计算机导论书籍.
去知乎扒了讨论帖, 貌似读这本书应该再配合食用 王爽<汇编原理>
, 之前在b站看了点汇编的lab课程, 然后又读课本上32位微处理器的编程结构, 初步体会到: 汇编大部分真就是和寄存器打交道, 好多寄存器…
*读这本书主要是为了巩固坚实的基础认知/知识, 并为后面想进行的一生一芯lab做准备.
看的是CSAPP
中文版电子书, 感谢译者.
Ⅰ. 计算机系统漫游
Q: 写了一个
hello world
c语言程序, 从点击运行到屏幕输出, 中间究竟发生了什么 ?
注意, 计算机程序的运行原理是:
预处理器
cpp
编译器ccl
汇编器as 链接器ld
hello.c
=>hello.i
>hello.s
>hello.o
>hello.exe
源程序 处理后的源程序 汇编程序 可重定位目标程序 可执行目标程序
文本格式 || 二进制格式
预处理 Pre-Processing
, 注意, 此阶段不检查语法错误
#include <stdio.h> //告诉预处理器读取系统头文件stdio.h的内容,并把它直接插入程序文本中。得到另一个 C 程序,通常是以 .i 作为文件扩展名
int main(){
printf("hello,world\n");
return 0;
}
编译 Compiling
, 为不同高级语言的不同编译器提供了通用的输出语言
main: #一个main函数
subq $8, %rsp
movl $.LC0, %edi
call puts
movl $0, %eax
addq $8, %rsp
ret
汇编 Assembling
, 将 hello.s
翻译成机器语言指令(17个字节长度的二进制形式的指令编码)
#如果打开hello.o将看到一堆01乱码
链接 Linking
, 源程序调用了printf函数, 它已经被单独预编译好了printf.o
, 需要链接器把该文件合并到hello.o
程序中.
*不过注意, 像Python、Ruby和Javascript这样的解释语言处理过程与上述不同.
之后可执行文件会被加载到磁盘中,等待由系统执行 (怎么执行的, 如下)
其内部的执行是在硬件上的.
软件===>硬件, 依靠着操作系统提供的服务。
例如, 在 Unix 操作系统上运行该可执行文件,我们将它的文件名输入到称为 shell
的应用程序中∶
./hello
shell 是一个命令行解释器.
它显示提示符,等待你输入一个命令行让它执行。若该命令行的第一个单词不是内置 shell 命令,那么 shell 就会假设这是一个可执行文件的名字,它将加载并运行这个文件。 (怎么加载的? 如下)
shell 经由CPU执行一系列指令, 将 hello 目标文件中的代码和数据: 利用DMA技术直接经由总线从磁盘复制到主存, 包括最终会被输出的字符串 “hello, world\n”。
接着, CPU(处理器)就开始执行 hello 程序的 main 程序中的机器语言指令(依据指令集架构)。这些指令将 “hello, world\n” 中的字节从主存 --经由寄存器 –复制到显示设备,最终显示 在屏幕上。
于是你在显示屏上就可以看到输出: hello,world
注意, 从程序员的角度来看,上述过程的许多"复制"就是开销,减慢了程序“真正”的工作。我们希望复制能尽快完成。于是存储器分层思想, 以及
cache
高速缓存存储器 应运而生, 它可以将程序的性能提高一个数量级.![]()
了解编译系统如何工作是大有益处的
深刻了解编译系统的工作有助于我们: 优化程序性能, 理解链接时出现的错误, 避免安全漏洞.
性能加速定律:
Amdahl 定律: 加速时系统某部分,其对整体性能的影响取决于该部分的 重要性α 和 加速程度k.
加速比S : S= 1 / [(1−α) + α/k]
软件工具链lab
当然上述的步骤在使用现成的IDE上点击运行就好了嗷, 但是想要摆脱对IDE的依赖, 就需要更深刻地了解它.
如Unix上从 源文件===========>可执行文件, 会手动使用一套工具链来完成, 如GNU
:
**GNU 工具链 **包含
GNUgcc
:一个支持多种语言的编译器套件,例如 C/C++ 和 Objective-C/C++。
GNUmake
:用于编译和构建应用程序的自动化工具。
GNUBinutils
:一套二进制实用工具,包括链接器和汇编器。
GNU 调试器 (GDB
)。
… #
GNU = GNU's Not Unix
GNU项目故事有着很宏大的目标.
gcc
(GNU C Compiler
) 是 GNU/Linux 操作系统的默认c编译器, 手动使用时如:
gcc -o hello hello.c
注意, 在功能上, gcc
命令后面可以跟很多指令, 在实际操作时可以不仅仅执行编译.
然后编译过程也可具体展开, 规定编译先后等, 以提高编译效率, 叫做 构建(build), GNU遂提供了相应的工具 make
. 可以手动编写makefile文件来使项目按照你的规则编译,而且把一堆 gcc
命令打包使流程变得简单!
如何手动编写makefile文件来手动编译程序? 指路