《程序是怎样跑起来的》摘录

一。cpu

1.cpu是寄存器集合体,程序是把寄存器作为对象描述的

2.CPU由寄存器,运算器,控制器和时钟四个部分构成;

寄存器可以用来暂存指令,数据等处理对象,可以将其看作是内存的一种;控制器负责把内存上的指令,数据读入寄存器,并且根据运算结果控制计算机;运算器负责运算从内存读入的数据;时钟负责发出cpu开始计时的时钟信号

3.机器语言指令的主要类型和功能:

数据传送指令(寄存器和内存,内存和内存,寄存器和外围设备之间的数据读写操作);运算指令(累加寄存器执行算术运算,逻辑运算,移位运算,比较运算);跳转指令(执行条件循环,分支跳转,强制跳转等);call/return指令(函数的调用地址,返回调用前的地址)

4.内存,即主存,通过控制芯片与cpu相连,主要负责存储指令和数据;主存可以读写数据,每个字节带有一个地址编号;cpu通过读取内存地址进行读写操作;断电后主存数据会自动清除

5.寄存器主要种类和功能:

累加寄存器:存储执行运算的数据和运算后的数据,只有一个;

标志寄存器:存储运算处理后的cpu的状态,只有一个;保存累加寄存器的运算结果,包括正数,负数,0;标志寄存器的第一个、第二个、第三个字节维的值为1时,分别表示运算结果为正数,0,负数;

基址寄存器(起始地址),变址寄存器(相对地址);

程序计数器:存储下一条指令所在内存的地址;

通用寄存器:存储任意数据;

栈寄存器:存储栈区域的起始地址,只有一个;

指令寄存器:存储指令,cpu内部使用,只有一个;

cpu执行比较机制,会内部进行xxx-yyy的减法运算;所以程序中的比较运算,就是在做减法运算

6.call/return指令

call指令将调用函数后的要执行的指令地址存储在栈中;

将函数入口地址设定到程序计数器;

函数执行完成,通过函数的出口执行return命令;return命令的功能是把保存在栈中的地址设定到程序计数器中。

栈在程序领域中,通过用来表示不断的存储各种数据的内存区域

二。 二进制数

  1. 计算机内部都是由IC(intergrated Circuit)构成的,包括cpu和内存也是。ic的这个特性,决定了计算机的信息数据只能用二进制数来处理。
  2. 位权,比如十进制数十位数位权值=数字值*10;二进制数位权同十进制数,只是二进制基数是2,第n位=n-1次幂。
  3. 移位运算(shift):分为左移和右移,可以分别代表乘法和除法运算,倍数为2
  4. 二进制数中一般会把最高位作为符合来使用,最高位=1表示负数,最高位=0为正数。计算机在减法运算时,内部是做加法运算。为此,表示负数时就要使用二进制的补数。补数=二进制数各位取反+1;补数+二进制数绝对值=0
  5. 逻辑右移:二进制数的值表示图形模式而非数值,移位后最高位补0;算术右移:二进制数作为带符号的数值进行运算,移位后要在最高位填充移位前符号位的值。 只有右移才会区分这两者。
  6. 符号扩充:不管正数还是负数,都只需要用符号位的值填充高位即可。
  7. 逻辑运算包括:逻辑非(NOT),逻辑与(AND),逻辑或(OR),逻辑异或(XOR,exclusive or)。

三。小数

  1. 小数表示方法:符号,尾数,基数,指数。尾数部分用正则表达式,规则:将小数点前面的值固定为1的正则表达式,也就是通过左移或者右移实现。指数部分用EXCESS系统表示,通过将指数部分表示范围的中间值设为0,使得负数不需要用符合表示。比如8位单精度浮点数,最大值11111111的二分之一=127,则设置127=0,128=1,126=-1;基数在二进制中表示2
  2. 为了避免出现小数计算出错,可以忽略或者可以先转为整数再转换为小数的方法,也可以用BCD(binary coded decimal)。

四。内存

  1. 内存IC包括DRAM(可读写,需要刷新电路保存数据),SRAM(可读写,不需要刷新电路就能保存数据),ROM(只能用来读取的内存)等,有电源,控制信号,地址信号,数据信号等大量引脚。
  2. 内存IC内部有大量可以存储八位数据的地方,通过地址指定这些场所,之后就可以进行数据读写。
  3. 写的过程:通过A0-A9指定地址,将数据输入给数据信号D0-D7,将WR(写信号)设为1;读的过程:通过A0-A9指定地址,将RD(读信号)设为1,读出D0-D7的数据。
  4. little endian :数据低位存储在内存低位地址的方式。
  5. 指针是表示指向地址的变量。定义指针数据类型表示从该指针存储的地址中一次能够读写数据的字节数。
  6. 数组是内存使用方法的基础,因为数组和内存的物理构造是一样的。数组定义中所指定的数据类型,表示一次能够读写的内存大小。可以通过数组索引所对应的地址的内存进行读写操作。
  7. 栈和队列都可以不通过指定地址和索引对数组元素进行读写,需要临时操作数据,就可以使用这些方法。栈LIFO,队列FIFO;如果我们在内存中预留出这两者需要的空间,并确定写入和读出顺序,就不用指定地址和索引了。队列一般是使用环状缓存区(ring buffer)的方式实现的。
  8. 链表:在数组的各个元素中,除了数据的值之外,通过为其附带上下一个元素的索引,即可实现链表。数据的值+下一个元素的索引=数组元素;链表元素末尾没有后续数据,因此填充-1.
  9. 二叉查找树:在链表基础上往数组中追加元素时,根据数据大小,分成左右两个方向。

以上栈,队列,链表,二叉查找树都是基于数组的。

五。磁盘

  1. 一般磁盘的1个扇区是512字节。把磁盘的一部分假想为内存使用的机制称为虚拟内存(virtual memory),使用内存提高磁盘访问速度的机制称为磁盘缓存(磁盘数据保存在内存中)。
  2. 存储在磁盘的程序需要读入到内存才能运行。同理,如浏览器保存获取的数据到硬盘,这都是把低速设备的数据保存到相对告诉的设备中。
  3. 虚拟内存:把实际内存的内容,和硬盘上的虚拟内存的内容进行部分置换,并同时运行程序。虚拟内存有分页式和分段式两种。Windows用的是分页式,磁盘的内容读出到内存称为page in,反之为page out。一般Windows计算机的页的大小是4KB.虚拟内存的大小一般是同等内存大小至两倍内存大小。
  4. DLL(dynamic link library),程序运行时动态加载library(函数和数据的集合)的文件。多个应用可以共有同一个DLL文件,通过这种方式可以节约内存。Windows系统本身也是多个dll文件的集合体。另外,在不变更exe文件的情况下,通过升级dll文件就可以更新。
  5. 分割硬盘的方式有扇区方式和可变长方式。扇区方式,把磁盘表面分成若干同心圆的空间就是磁道,把磁道按照固定大小(存储的数据长度相同)划分的空间就是扇区。磁盘的数据保存是以簇为单位的,硬盘空间越大,簇的容易也越大。不管多么小的文件,都会占用1簇的空间。

六。文件压缩

  1. 文件就是字节数据的集合。在任何情况下,文件中的字节数据都是连续存储的(包括文本格式,图像格式)。
  2. 把文件内容用数据*重复次数的形式来表示的压缩方法称为RLE(run length encoding,行程长度编码)算法。
  3. 哈夫曼算法:多次出现的数据用小于8位的字节数表示,不常用的数据用超过8位的字节数表示。
  4. Windows的标准图像数据形式为BMP,完全未压缩。bitmap:显示器及打印机输出的点(bit)可以直接映射(map)。
  5. 能还原到压缩前状态的压缩为可逆压缩,反之为不可逆压缩。

七。运行环境

  1. 运行环境=操作系统+硬件,cpu只能解释其固有的机器语言,不同cpu能解释的机器语言不同。
  2. 机器语言的程序称为本地代码(native code);通过对源代码进行编译,就可以得到本地代码。市面上出售的Windows软件包就是本地代码。Windows应用程序的本地代码,通常是dll文件或者是exe文件。
  3. 应用程序向操作系统传递指令的途径称为api(application programming interface)。
  4. 利用虚拟机获得其他操作系统环境
  5. java虚拟机:java编译后生成 的是字节码的程序;字节码的运行环境称为java虚拟机。java虚拟机是一边把java字节码逐一转换成本地代码一边运行的。这样同样的java代码不用受限于不同的操作系统+硬件,只需要对应的java虚拟机就可以了。
  6. BIOS(Basic input/output system),存储在ROM,是预先内置在计算机主机内部的程序。除了键盘,磁盘,显卡等基本控制程序外,还有启动“引导程序”的功能。引导程序是存储在启动驱动器起始区域的小程序。操作系统的启动驱动器一般是硬盘,也可以是cd-rom或者软盘。引导程序的功能是把在硬盘等记录的os加载到内存中运行,虽然启动应用是os的功能,但是os并不能自己启动自己,而是通过引导程序来启动。这种也叫bootstrap(小引导程序带动大操作系统)

八。从源文件到可执行文件

  1. Windows自带的exe文件就是本地代码。dump指把文件的内容,每个字节用2位16进制来表示的方式。本地代码就是各种数值的罗列。每个数值都表示一个命令或数据。
  2. 把高级语言编写的源代码转换为本地代码的程序称为编译器。每个高级语言对应的编译器不同;同时cpu类型不同,编译器也不同。
  3. 本地文件无法直接运行,还需要进行链接处理得到可以运行的exe文件。编译后生成的是.obj的目标文件,把多个目标文件结合,生成一个exe文件的处理就 是链接,运行链接的程序称为链接器。
  4. 库文件指的是把多个目标文件集成保存到一个文件中的形式。链接器指定库文件后,就会把需要的目标文件抽取出来,同其他目标文件结合生成exe文件。
  5. Windows中,API的目标文件存储在名为DLL文件的特殊库文件中。类似于import32.lib这样的库文件称为导入库。而不需要进行导入操作的库文件为static静态链接库。
  6. exe文件是作为单独的文件存储在硬盘的,双击exe文件,就会将对应内容加载到内存中运行。
  7. exe文件的内容分为再配置信息,变量组和函数组。当程序加载到内存后,额外生成两个组:栈和堆。栈用来存储函数内部临时变量(局部变量),以及函数调用时所用参数的内存区域。堆存储程序运行时的任意数据及对象的内存领域。所以一个程序使用的内存空间=程序中变量的空间(复制exe文件)+函数的空间(复制exe文件)+栈空间(运行时分配)+堆空间(运行时分配);栈的空间分配和清理都是编译器自动完成;堆的空间释放需要专门写程序处理。
  8. 编译器是在运行前对源代码解释处理;解释器是在运行时对源代码的内容逐行解释处理。
  9. 根据开发工具种类,有的编译器可以通过选择build菜单生成exe文件;这种情况,build指的是连续执行编译链接。

九。操作系统和应用的关系

  1. 应用不是直接控制硬件,而是通过操作系统间接控制硬件。操作系统收到应用发出的指令后,先对该指令进行解释,然后对时钟ic和显示器用的I/O进行控制。
  2. 操作系统中函数以及函数调用的行为称为系统调用(system call)
  3. Windows多任务是通过时钟分割技术实现的。Windows中还具有以程序中的函数为单位进行时钟分割的多线程功能。
  4. 操作系统和中间件合在一起,也称为系统软件。

十。通过汇编语言了解程序的实际构成

  1. 在本地代码中,附带表示其功能的英语单词缩写,如add,cmp,称为助记符。使用助记符的编程语言称为汇编语言,最终也是需要通过汇编器转换为本地语言才能运行。此处汇编器和编译器的作用是一样的。本地代码可以通过反汇编程序转换为汇编语言。
  2. 由伪指令segment和ends围起来的部分,称为段定义。
  3. 操作码+操作数=汇编语言指令(mov,add,push,pop等)
  4. 函数的参数通过栈传递,返回值通过寄存器返回。

十一。硬件控制方法

  1. Windows控制硬件时借助的是输入输出指令,最具代表性的是IN,OUT。IN指令通过指定端口号的端口输入数据,存储在cpu内部的寄存器中。OUT则是把寄存器的数据输出到指定端口。
  2. 计算机主机中,附带了用来连接显示器和键盘等外围设备的连接器。各连接器的内部,都连接有用来交换计算机主机同外围设备之间电流特性的IC.这些ic统称为I/O控制器。由于电压不同,数字信号及模拟信号的电流特性也不同,因此就产生了I/O控制器。其中有用于临时保存输入输出数据的内存,这个内存就是端口(port),也称为寄存器。这里的寄存器作用主要是临时存储数据,cpu寄存器主要是数据运算处理。I/O控制器和外围设备的关系是一对多,各端口之间通过端口号区分,端口号也称为I/O地址。
  3. IRQ=interrupt request,中断请求,暂停当前正在运行的程序,跳转到其他程序运行的机制。实施中断请求的是I/O控制器,执行中断程序的是cpu。使用中断编号发起中断请求。按照顺序调查多个外围设备的状态称为轮询;轮询对于中断请求很少的系统来说比较合适。
  4. DMA(direct memory accesso),不通过cpu,外围设备直接和住内存进行数据传送。由于cpu作为中介的时间被节省了,因此传送数据的速度加快。
  5. 简单概括,显示器显示的信息一直存储在VRAM中(video ram)。实现该功能的程序,是由操作系统或BIOS提供,借助中断进行处理的。Windows时代,显卡专用硬件一般配置有与主内存想独立的VRAM和GPU。

猜你喜欢

转载自blog.csdn.net/Trival_dreamy/article/details/81457618