1.计算机基础

1.2.1

冯·诺尼曼结构,最核心的思想:程序存储

任何计算机要完成的工作都要先编写成程序,然后把程序和院士数据送入计算机主存里并启动执行,一旦程序被启动,计算机在无需操作人员的干预下,自动完成逐条指令的取出和执行等任务。

因此为了实现这个构想,计算机需要的一些东西:

  • 主存,存放程序和数据

  • 自动逐条取出指令的部件

  • 执行指令的部件ALU

  • 有将程序和原始数据输入计算机的部件

  • 有将运算结果输出的部件

此外还有这些特性:

  • 程序由指令构成

  • 指令描述如何对数据进行处理

有了这些分析,一个计算机模型基本上就可以抽象出来了,

<模型>

主要思想:

  • 计算机由运算器、控制器、存储器、输入设备、输出设备五个基本部分组成

  • 各部分功能

    • 存储器不仅存放数据,也能存放指令,形式上两者没啥区别,但计算机要能区分

    • 控制器应能自动取出指令来执行

    • 运算器能进行加减乘除基本算数运算,也能进行一些逻辑运算

    • 操作人员可以使用输入输出设备使用计算机

  • 计算机内部用二进制来表示指令和数据,每条指令由操作码和地址码两部分组成,操作码指出操作类型,地址码指出操作数的地址

  • 采用“存储程序”工作方式

1.2.2现代计算机结构

前面是个模型,实际现在用的计算机类似,但是有了更工程的实现。

CPU编程模型+存储器=主机;此外还有输入设备输出设备。

硬件插在主板上,主板上有个很重要的东西就是总线,AB;CB;DB

计算机的工作原理,不停的取指令译码执行。想让一段程序执行,就把程序的起始地址放在PC寄存器里

  • 根据PC取得指令

  • 指令译码

  • 取操作数

  • 执行指令

  • 回写结果

  • 修改PC的值,继续下一个循环

程序由指令序列组成。

程序和数据都在存储器里,形式上没啥区别。指令中要给出的信息有操作性质即操作码,操作数。

操作数可能在指令中直接给出,也可能在寄存器里,也可能在存储器里,这就是不同的寻址方式。

因此指令里要有操作码和操作数的地址

1.3

程序(指令序列)是如何生成并生成的呢?

1.3.1

最早的程序直接用机器语言,直接就编指令序列。打孔纸片,磁环,最早的程序员就是干这活的。因此必然可读性基本上没有。最痛苦的是,搞错了要改太困难了。

后来用符号来表示,即汇编语言。汇编语言并非机器码的直接代替,汇编语言也是需要编译的,但是编译后的机器码反汇编和汇编差的不多,以至于可以手工汇编。汇编语言是对机器码做的一层简单包装,用标号去指代了地址,此外还有一些伪指令用来控制一些其他东西。

汇编语言转换成机器语言也是有程序来做的,即汇编程序。

汇编语言远吗由汇编指令构成,汇编指令用一句话描述:用助记符和标号来表示的指令。

什么又是指令呢?这要结合机器模型去研究,根据特定的机器,可以设计指令,一个典型的,读或写。指令就是来描述硬件级别的数据操作,如接通存储器指定地址和寄存器之间的数据通路,这就是LDR指令。实际一条指令可能要多步操作完成。

指令能完成的操作:加减,存取,根据结果判断是否转移执行。

可以看出,汇编语言编写复杂程序是很痛苦的,比如写一个冒泡排序,可以实现但是过于痛苦。用对动作描述的指令写程序还有个问题,指令和不同的机器相关,也即机器码不通用。机器语言是面向机器结构的语言。

因此汇编语言可以写程序但是还是很麻烦。因此后来有了高级语言写程序。高级语言和机器结构无关,描述的是算法(机器语言描述的是动作),高级语言一条语句对应几条、几十条指令。高级语言又有面向过程和面向对象的区别。

高级语言也要处理成机器码才能执行,有两种转换方式:编译、解释。

  • 编译即把高级语言的源程序转换为机器机的目标程序,执行时启动目标程序就行

  • 解释即把高级语言逐条翻译成机器语言并立即执行,不生成目标文件

解释语言没有可执行文件,不像编译语言,不可以执行源码,要执行最后生成的可执行文件。

1.3.2程序的生成

一个典型的程序

#include <stdio.h>

int main(void)
{
  printf("aaa");
  return 0;
}

这个hello.c存在计算机里是以ascii保存的,在gcc+linux平台,经过以下过程

hello.c->预处理->hello.i->编译->hello.s->汇编->hello.o->链接->hello

在机器上得到了可执行文件,存放在磁盘里,如果在linux环境里,在shell里启动,输入./hello按下回车就开始执行了,在屏幕上出现字符。

这就是一个整个的程序运行起来的过程。

对于不同层次的语言之间,有个等价转换,即编译、汇编、指令译码,汇编指令和机器码是一一对应的。

最早的程序开发很简单,直接输指令和数据就行,然后把第一条指令地址送入PC寄存器。

现在的高级语言开发的程序需要复杂的环境,需要编辑器编写源程序,需要一套翻译转换软件处理各类源程序(预处理程序、编译器、汇编器、链接器,解释器,这些都叫语言处理程序),需要一个可以执行程序的界面。因此需要语言处理程序+语言运行时的系统。

1.4

操作系统+语言处理系统,这个系统又要由指令系统体系架构支撑。

这部分介绍不同抽象层。

1.4.1

最早的计算机用机器语言,第一代程序设计语言。最早的计算机层次很简单,只有三层

后来用汇编语言,第二代程序设计语言,汇编语言程序必须通过汇编程序来转换为机器码,因此多了一些层次

现代计算机用高级语言,第三代程序设计语言,过程式的。第四代程序设计语言,非过程式的,编码的时候只要说明做什么,实现什么功能。

应用程序->语言处理系统->操作系统->指令体系结构->计算机硬件

在应用程序和指令集体系结构之间的都是软件,这些系统软件都是指令组成的,指令是计算机硬件的一种抽象形式,抽象有一套规定,这个规定就是指令集体系结构。最下面的计算机硬件。

语言处理系统包括语言处理程序、运行时系统(库函数、调试、优化等),操作系统包括人机交互界面、提供服务功能的内核。

可以看出计算机语言的发展也是一个不断“抽象”的过程,从最简单的最基本的描述计算机动作的指令,再到符号的表示,然后用高级语言的语句来抽象,在抽象的时候就产生了新的层次。

1.4.2

最终的一个计算机的层次。

一个应用(具体的问题)先转换为算法,然后用高级语言来进行描述算法,得到高级语言源程序。在源程序翻译或者解释源程序的时候需要操作系统的支撑,操作系统实际上是对计算机底层功能进行抽象的一个层次,相当于提供了一个虚拟的机器给程序员使用。从应用到操作系统都属于软件层次,这些软件都是一条条指令,这些指令都是指令集体系结构规定的指令,这些规定是对底层硬件的抽象,

指令集体系结构的具体实现就是微体系结构的实现,微体系结构最终是有功能部件,即门电路,再往下就是组成门电路的晶体管。

指令集体系结构(ISA)是软硬件的分界面,也是一个接口,因此程序执行的结果,不仅仅和软件相关,也和硬件相关。所有软件功能都建立在ISA之上,所有的软件功能都是通过ISA来实现的。

不同的计算机课程处在不同层次,如果贯通不同层次,那么会对计算机的理解达到一个新的高度。通个这个体系,能看出每个上层对下层进行了抽象,每个下层是对上层的具体实现。底层对上层提供了一种支撑环境。

最高层我们点鼠标拖动就能完成所有操作,最抽象的这层,但实际上背后做了层层转化。

ISA指令集体系结构,来细致看看。

ISA(instruction set architecture),简称为指令系统,ISA实际上是一种规约(specification),规定了如何使用硬件(软件是如何使用硬件的),具体的:

  • 规定了可以执行的指令的集合,包括指令格式、指令种类以及每种操作对应的操作数的相应规定

  • 规定了指令可以接受的操作数的类型(有无符号,浮点数等类型)

  • 规定了操作数能存放的寄存器组的结构,包括寄存器组的名称、编号、长度和用途

  • 规定了操作数能存放的存储空间的大小(最大有多大)和编址方式(8bit一个地址还是16bit一个地址)

  • 规定了操作数存放是大端还是小端

  • 规定了指令集获取操作数的方式,即寻址方式

  • 规定了指令执行过程的控制方式,包括程序计数器(PC)、条件码的等

ISA在通用计算机是不可少的部分,用计算机这个物理实体,必须通过指令集来使用,没有这个东西,就不能说一台设备是通用计算机,只能说是专用数字电路。

ISA和计算机组成的关系:计算机组成称为微体系结构。

不同ISA规定的指令集不同,IA-32、MIPS、ARM。

IA-32有8个通用寄存器,MIPS有32个;IA32有3bit表示寄存器,MIPS有5bit,因此ISA和微体系结构密切相关。计算的组成必须可以实现ISA的功能,MIPS里面不是用标志方式来确定转移的,因此这个微体系结构不需要标志寄存器。有时候同一种ISA也可以通过不同微体系结构实现。如乘法指令可以专门用乘法器,或用ALU加减运算来实现,所以计算机组成是不一样的,但是抽象出来的指令是相同的。

指令集是对计算机组成的抽象。ISA是对微体系结构的抽象。

1.5

分层设计在计算机里处处提现。

现在已经进入了后PC时代,计算资源多样化,IO设备无处不在,手持设备和传统PC共存。因此要有协同设计的能力,硬件、OS、编译器之间的关联更加密切。对于应用程序员:

  • 编写高效程序必须要了解计算机底层

  • 要掌握并行程序设计

  • 应用问题更加复杂,领域更广

计算机学科主要研究计算机系统各个不同抽象层的实现以及相互转换的机制。将来工作也是在一个或者几个抽象层上工作。

这部分就是介绍所有的抽象层之间的联系,构建起系统框架。

计算机系统基础主要是从程序员角度来认识计算机系统,使得成为一个高效的程序员。

学习这部分使用的平台:IA-32 + Linux + gcc

类似的课程:

也是描述程序执行的底层机制,在程序和程序的执行机制之间建立关联,强化理解而非记忆。

  • 数据的表示

  • 数据的运算

  • 语句的转换和表示

  • 复杂数据类型的转换表示

  • 过程调用的转换表示

  • 链接和加载

  • 程序执行,存储器的访问

  • 程序执行时异常和中断的处理

  • 输入输出的实现,用户态、内核态、系统调用

三个主题两个内容:

  • 表示和转换

    • 不同类型数据的表示

    • 指令的表示和编码

    • 存储地址的表示

    • 高级语言程序对应的机器级代码是怎么样的,如何转换并链接生成可执行文件

  • 执行控制流

    • 计算机能理解的程序是如何控制和组织的

    • 如何在计算机中组织多个程序的并发执行

    • 逻辑控制流中的异常事件及其处理

    • IO操作的执行控制流(用户态-内核态)

最后更新于