加载到内存中的机器语言程序,由CPU进行解析和运行,进而计算机系统整体的控制和数据运算也开始运行。
寄存器 可用来暂存指令、数据等处理对象,可以将其看作是内存的一种。根据种类的不同,一个CPU内部会有20~100个寄存器。控制器负责把内存上的指令、数据等读入寄存器,并根据指令的执行结果来控制整个计算机。运算器负责运算从内存读入寄存器的数据。时钟负责发出CPU开始计时的时钟信号。
汇编语言采用助记符(memonic)来编写程序,每一个原本是电气信号的机器语言指令都会有一个与其相应的助记符,助记符通常为指令功能的英语单词的简写。
汇编语言和机器语言基本上是一一对应的。
顺序执行是指按照地址内容的顺序执行指令。条件分支是指根据条件执行任意地址的指令。循环是指重复执行同一地址的指令。
函数的调用 需要在完成函数内部的处理后,处理流程再返回到函数调用点(函数调用指令的下一个地址)。因此,如果只是跳转到函数的入口地址,处理流程就不知道应该返回至哪里了。
函数调用使用的是call指令,而不是跳转指令。在将函数的入口地址设定到程序计数器之前,call指令会把调用函数后要执行的指令地址存储在名为栈的主存内。函数处理完毕后,再通过函数的出口来执行return命令。return命令的功能是把保存在栈中的地址设定到程序计数器中。
计算机处理信息的最小单位——位,就相当于二进制中的一位。位的英文bit是二进制数位(binary digit)的缩写。
8位二进制数被称为一个字节。字节是最基本的信息计量单位。位是最小单位,字节是基本单位。内存和磁盘都使用字节单位来存储和读写数据,使用位单位则无法读写数据。因此,字节是信息的基本单位。
内存IC中有电源、地址信号、数据信号、控制信号等用于输入输出的大量引脚(IC的引脚),通过为其指定地址(address),来进行数据的读写。
指针也是一种变量,它所表示的不是数据的值,而是存储着数据的内存的地址。
数组是指多个同样数据类型的数据在内存中连续排列的形式。作为数组元素的各个数据会通过连续的编号被区分开来,这个编号称为索引(index)。指定索引后,就可以对该索引所对应地址的内存进行读写操作。
在数组的各个元素中,除了数据的值之外,通过为其附带上下一个元素的索引,即可实现链表。数据的值和下一个元素的索引组合在一起,就构成了数组的一个元素。
如果不使用链表数组,那么中途删除或追加元素时,其后的元素就必须要全部移动。
程序保存在存储设备中,通过有序地被读出来实现运行,这一点大家都很清楚。这一机制称为存储程序方式(程序内置方式),现在看来这是理所当然的,但在当时它的提出可以说是一个里程碑。为什么这么说呢?因为在此以前的程序都是通过改变计算机的布线等来变更程序的。
Windows的操作系统本身也是多个DLL文件的集合体。有时在安装新应用时,DLL文件也会被追加。应用则会通过利用这些DLL文件的功能来运行。
不管是硬盘还是软盘,不同的文件是不能存储在同一个簇中的,否则就会导致只有一方的文件不能被删除。因此,不管是多么小的文件,都会占用1簇的空间。
在任何情况下,文件中的字节数据都是连续存储的,大家一定要认识到这一点
把文件内容用“数据×重复次数”的形式来表示的压缩方法称为RLE(Run Length Encoding,行程长度编码)算法。
JAVA 虚拟机是运行 JAVA 应用的字节代码解析。
只要分别为各个环境安装专用的Java虚拟机,同样的字节代码就能在各种环境下运行了。
机器语言的程序称为本地代码(native code)。程序员用C语言等编写的程序,在编写阶段仅仅是文本文件。文本文件(排除文字编码的问题)在任何环境下都能显示和编辑。我们称之为源代码。通过对源代码进行编译,就可以得到本地代码。
最初应用软件的功能中,存在着直接操作计算机硬件的部分。而这又是为什么呢?原因主要有两点,一是当时MS-DOS的功能尚不完善,二是为了提高程序的运行速度。
应用软件则必须根据不同的操作系统类型来专门开发。CPU的类型不同,所对应的机器语言也不同,同样的道理,操作系统的类型不同,应用程序向操作系统传递指令的途径也是不同的。
大家说的Java,有两个层面的意思。一个是作为编程语言的Java,另一个是作为程序运行环境的Java。
字节代码的运行环境就称为Java虚拟机(JavaVM, Java Virtual Machine)。Java虚拟机是一边把Java字节代码逐一转换成本地代码一边运行的。
编译器会将程序员编写的源代码(sample.java)转换成字节代码(sample.class)。而Java虚拟机(java.exe)则会把字节代码变换成x86系列CPU适用的本地代码,然后由x86系列CPU负责实际的处理。
Java虚拟机每次运行时都要把字节代码变换成本机代码,这一机制是造成运行速度慢的原因。为此,目前业界也在努力改善这一问题,比如把首次变换后的本地代码保存起来,第2次以后直接利用本地代码,或是对字节代码中处理较为费时的部分进行优化(改善生成的本地代码质量)等。
用某种编程语言编写的程序就称为源代码,保存源代码的文件称为源文件。
CPU能直接解析并运行的不是源代码而是本地代码的程序。即使是用不同编程语言编写的代码,转换成本地代码后,也都变成用同一种语言(机器语言)来表示了。
能够把C语言等高级编程语言编写的源代码转换成本地代码的程序称为编译器。每个编写源代码的编程语言都需要其专用的编译器。将C语言编写的源代码转换成本地代码的编译器称为C编译器。读入的源代码还要经过语法解析、句法解析、语义解析等,才能生成本地代码。
栈中对数据进行存储和舍弃(清理处理)的代码,是由编译器自动生成的,因此不需要程序员的参与。使用栈的数据的内存空间,每当函数被调用时都会得到申请分配,并在函数处理完毕后自动释放。与此相对,堆的内存空间,则要根据程序员编写的程序,来明确进行申请分配或释放。
垃圾回收机制(garbage collection)指的是对处理完毕后不再需要的堆内存空间的数据和对象进行清理,释放它们所使用的内存空间。这里把不需要的数据比喻为了垃圾。
C语言用的是free()函数,C++用的是delete运算符。在C++的基础上开发出来的Java及C#这些编程语言中,程序运行环境会自动进行垃圾回收。这样就可以避免由于程序员的疏忽(忘了记述内存的释放处理)而造成内存泄露了。
操作系统的硬件控制功能,通常是通过一些小的函数集合体的形式来提供的。这些函数及调用函数的行为统称为系统调用(system call)
多任务指的是同时运行多个程序的功能。Windows是通过时钟分割技术来实现多任务功能的。
时钟分割指的是在短时间间隔内,多个程序切换运行的方式。在用户看来,就是多个程序在同时运行。
操作系统和中间件合在一起,也称为系统软件。应用不仅可以利用操作系统,也可以利用中间件的功能。
即插即用(Plug-and-Play)指的是新的设备连接(Plug)后立刻就可以使用(Play)的机制。
汇编语言指令的语法结构是操作码opcode+操作数oprand(也存在只有操作码没有操作数的指令)。操作码表示的是指令动作,操作数表示的是指令对象。用汇编语言来分析“Give me money”这个英文指令的话,Give就是操作码,me和money就是操作数。
寄存器是CPU中的存储区域。不过,寄存器并不仅仅具有存储指令和数据的功能,也有运算功能。寄存器的名称会通过汇编语言的源代码指定给操作数。内存中的存储区域是用地址编号来区分的。CPU内的寄存器是用eax及ebx这些名称来区分的。此外,CPU内部也有程序员无法直接操作的寄存器。例如,表示运算结果正负及溢出状态的标志寄存器及操作系统专用的寄存器等,都无法通过程序员编写的程序直接进行操作。
局部变量是临时保存在寄存器和栈中的。函数内部利用的栈,在函数处理完毕后会恢复到初始状态,因此局部变量的值也就被销毁了,而寄存器也可能会被用于其他目的。因此,局部变量只是在函数处理运行期间临时存储在寄存器和栈上。
显示器中显示的信息一直存储在某内存中。该内存称为VRAM(Video RAM)。在程序中,只要往VRAM中写入数据,该数据就会在显示器中显示出来。实现该功能的程序,是由操作系统或BIOS提供,并借助中断来进行处理的。
控制就是指CPU和各种设备之间配合进行数据的输入输出处理。
石头、剪刀、布分别用数值0、1、2来表示。
我们用0~9这10个随机数,0~4时表示石头,5~7表示剪刀,8~9表示布,这样规定后,石头、剪刀、布的百分比率就分别变成了50%、30%、20%。
由于借助公式产生的随机数具有一定的规律性,因此并不是真正的随机数,通常称为伪随机数。
计算机中预先被定义过的位数和精度称为数据类型。