系列导览
阶段一. 计算机原理:
计算机由哪些部件组成,程序是如何运行起来的呢?
链接:
阶段二. 编译原理:
当有了高级语言,有了各种各样的高级语言,比如C,Golang, Java这些,他又是怎么被计算机硬件所识别呢?
链接:
阶段三. 操作系统的介入
当程序不再直接运行在计算机的硬件设备上,而是由一个称为"操作系统"的超级大管家帮我们运行时,那又是一番怎样的情形呢?
链接:
前言
上大学的时候你一定学过"计算机原理"这门课程,说到"计算机原理", 虽然软硬不分家,但实际上这门课程更偏向于计算机硬件,
而对于狭义的软件,一般指的是高级语言编写的程序,可能大部分都是谭浩强他老人家了,哈哈哈哈哈....
本文是基于计算的核心硬件CPU, 寄存器,内存等这些概念,结合程序或叫软件来进行阐述,其中软件中关于高级语言的编译,则单独使用一篇博文进行讲解....
在学习计算机的底层运行原理时,要时刻将一个概念刻入脑子里:
计算机原理无非是这2点:
硬件方面:给数据找个安置的地方即"存储; 将数据进行"计算"并得到结果;
软件方面:而指导这一切的称为"指令"。
此处的"指令"其实就是我们所编写的软件程序在计算机底层时的身份。
计算机硬件
前面说了,计算机的核心影响只有两个:计算 和 存储,其余一切都是为了他们而服务
1. 中央处理器(CPU)
Central Processing Unit,是一块超大规模的集成电路,是一台计算机的运算核心(Core)和控制核心(Control Unit)。它的功能主要是解释计算机指令以及处理计算机软件中的数据。
中央处理器主要包括运算器(算术逻辑运算单元,ALU,Arithmetic Logic Unit),译码器,寄存器组成,和高速缓冲存储器(Cache),控制及状态的总线(Bus),以及实现它们之间联系的数据(Data)一起协同工作。
编程语言
1. 编程语言的历史
开始, 计算机只能运行二进制,即她只认识0101,所以最开始的程序是用0101编码出来的,称为"机器语言"。用这些01串去控制CPU进行计算,什么样的01串对应什么样的操作,以及01串具体如何控制计算机硬件设备,则由计算机架构决定,见下一小节。除此之外,还要手动为这一坨0101....分配存储空间以及输入和输入,所以显然,这是反人类的.....。
后来,芯片厂商发明了一些助记符,也就是"汇编语言"。所谓的01串,无非就是让CPU去计算,去移动,去获取等等,于是把这些行为用固定的一个"单词"去代替。但是,汇编语言不过是机器码的另一种表现形式而已,还是会直接和硬件比如寄存器打交道,只要与硬件相关那么他的可移植性就....
最后,"高级语言"诞生了,管你什么硬件,我代表的就是一个逻辑(算法),至于硬件怎么去实现我的逻辑?不管!于是,可移植性大大提升!高级语言需要有编译工具将之转换成最终的机器码,这部分由阶段二进行详解。
wxy碎碎念:这三个语言并不是"层层递进"的关系,高级语言 -- 编译--> 汇编语言 --等同于--> 机器语言
2. 计算机架构(Computer architecture)
参考wiki:
https://en.wikipedia.org/wiki/Computer_architecture
https://en.wikipedia.org/wiki/Reduced_instruction_set_computer
及其他相关的连接
wiki定义:
是描述计算机系统功能,组织和实现的一组规则和方法。在有些定义中,计算机架构被描述成计算机的能力和编程模型,但并不是特定的实现. 在其他定义中,计算机体系结构包括指令集体系结构设计,微体系结构设计,逻辑设计和实现。
wxy: 首先,所谓架构并不是具体的实现,而是一种规范;其次,所谓的规则和方法,其实就是让软件指令和硬件设备,如何具体结合起来,即一条"指令"到底意味着什么, 他的背后对应着哪些硬件操作....
2.1 指令集架构(ISA)
Instruction set architecture (ISA) defines the machine code that a processor reads and acts upon as well as the word size, memory address modes, processor registers, and data type.
In general, an ISA defines the supported data types, the registers, the hardware support for managing main memory, fundamental features (such as the memory consistency, addressing modes, virtual memory), and the input/output model of a family of implementations of the ISA.
An ISA specifies the behavior of machine code running on implementations of that ISA in a fashion that does not depend on the characteristics of that implementation, providing binary compatibility between implementations.
An instruction set architecture is distinguished from a microarchitecture, which is the set of processor design techniques used, in a particular processor, to implement the instruction set. Processors with different microarchitectures can share a common instruction set.
解析:
定义了处理器在读取机器码后,综合其word size、内存地址、处理器寄存器、以及数据类型,所做的操作。
总体来说,ISA定义了支持的数据类型,有哪些寄存器,用于管理主存的硬件支持,基本功能(例如内存一致性吗, 寻址模式, 虚拟内存),以及对应的一系列IO模型。
一个ISA定义了基于这个架构运行的机器码所对应的具体行为,运行方式并不依赖于具体的实现,在不同的具体实现之间实现了二进制兼容(binary compatibility).
指令集架构不同于微体系架构(microarchitecture), 后者是针对特定的处理器,为了实现指令集,所使用的一种处理器设计技术。具有不同为微架构的处理器可以共享一个公共指令集。
wxy:
ISA即指令集架构,是将计算机各个硬件以及硬件如何被操作通通抽象出来,用一条条指令去定义这些,
然后,只要是对于基于某个特定架构实现的计算机,所有二进制程序都可以兼容的运行于其上。
另外,还提了一点微体系架构,正如其名称中的"微"字,是独立于架构之外,各个cpu厂商为了实现这个架构,自己处理器内部的实现技术。
相关概念区分:
machine code: 机器码,CPU只认识这样的指令,即一组组0101010110....
instruction: 指令
instruction set:指令集
instruction set architectures:指令集架构
opcode: 操作码,是operation code的缩写, 也称为instruction machine code, instruction code, instruction syllable(音节), instruction parcel or opstring),
是在机器语言指令中,用来指定所要执行的操作那部分. 除了操作码自身,大部分指令还会指定要处理的数据称为操作数(operands).
另外,不仅硬件CPU的指令集架构会使用操作码; 在abstract computing machines(虚拟机?)中,操作码也作为其字节码规范的一部分。
wxy: 1 + 2 = 3,"1"是操作数(operands),"+"是操作码(opcode),整个算式是一条指令(instruction)
2. 从高级语言到机器语言的转化
根据语言的历史我们基本上可以判断,转化基本上就是 高级 --->汇编 ---->机器
汇编编译器assembler编译目标代码二进制文件(nasm -f elf -g -F stabs *.asm),连接器linker(ld -o bin_file *.o)除了把目标代码组合成一个单个的块,还要确保模块以外的函数调用能够指向正确的内存引用(连接器必须建立一个索引,也就是符号表,里面存放的是它连接的每一个目标模块中的每一个已命名项,其中存放着一些关于哪个名字或叫符号指向模块内部哪个位置的信息)。
立即数,内置在机器指令内部,它不是存放在寄存器中,也不是存放在位于某个指令之外的内存中。
1, 寄存器打中括号代表寄存器的内存地址中的内存数据。例:
mov eax,[ebx+16]。
2, 在汇编中,变量名代表的地址,不是数据。例:
Msg: "Hello World"
mov ecx,Msg #复制Msg地址到ecx寄存器,而不是数据
mov edx,[Msg] #复制数据,而不是地址
MsgLen: equ $-Msg #$代表末尾,长度=末尾位置减开始位置
各家的汇编格式可能不一样,例如gcc的汇编器使用的是AT&T文法,常见的汇编语言可以使用nasm编译。
指令的执行
- 机器语言(CPU可以直接识别的语言)不存在“变量”这个概念,它只能操作内存和寄存器(CPU内部的几个暂存电路,数量很有限)。变量这个概念在实现的时候通常是将之对应于某个寄存器或者某一片内存。
- CPU提供了一系列指令来方便程序员维护一个叫“栈”的数据结构。栈位于内存当中,栈顶和栈底都保存在特殊的寄存器当中,CPU可以随时将数据压栈或者出栈。这个“数据”的含义实际上比较宽泛,它可以是一个数字、字符,也可以是CPU的运行状态。CPU可以将某一刻的运行状态压栈,然后跳转到其他地方执行一段程序,然后出栈恢复之前的执行状态,这就实现了函数的调用。没错,CPU也不太认识什么叫做“函数”,不过将运行状态压栈以及恢复运行状态都有专门的指令,一般就把它们成为”子程序调用指令“和“返回指令”。
- 对于“局部变量”,CPU连“变量”都不认识,所以局部变量什么的也不存在了。不过这玩意可以依靠栈来实现,通过压栈就可以随时分配一个内存,出栈就可以认为这个内存区域不再被使用。配合刚才说过的“函数”调用的实现方法,这种依靠压栈分配出的内存一定只能被当前正在执行的函数使用。因为函数调用前,这片内存还没有被分配,返回后这片内存也不再使用了