转自CSDN:http://topic.csdn.net/u/20120407/00/1dbee1fa-0252-4400-b2bb-ee667c88f9d8.html
对程序设计来说,基础就是支撑你编程的一个环境,就像我们玩游戏一样首先要熟悉游戏规则,比如玩斗地主,你首先要知道出牌的规则,组合的规则,胜负的规则,你才能打出好牌,做编程也一样,首先必须要熟悉编程的环境和规则。
那么有哪些规则呢(规则太多了,这里没法完全列举,只列举几个很重要的规则),只要搞清这些规则,并活用这些规则,慢慢就会对编程更加有体会。
规则1.CPU只能访问内存单元不直接访问外部存储器(比如磁盘),因此所有的指令必须装入内存后,cpu才能访问并执行。这样问题就来了,如何将程序装入内存?要搞清这个问题,需要知道内存空间,内存寻址以及相应的机器指令,这些就是所谓的基础。
规则2.CS寄存器和IP寄存器唯一确定当前将要执行的指令在哪个内存单元。从高级语言来看程序运行就是执行一系列的源代码,那么本质原因是什么呢?就是CS:IP不断变化然后执行对应内存地址中的指令。因此若是CS:IP顺序变化,那么程序就顺序执行;如果CS:IP发生突变,那么程序就执行相应的跳转。我们程序结构的本质就是建立在这个基础上的。比如函数调用这样的跳转结构。
规则3.CPU制定了一套异常处理流程,专门来处理异常指令。什么是异常我先举个列子,比如我们玩斗地主,一副牌里面只有一个大王和一个小王,如果我们在打牌的过程中,发现自己的手中有个大王,但是别的玩家却突然打出一张大王,这个时候我们就说发生异常了,因为规定的是只有一个大王,可是一副牌中却出现了两个大王,那么很可能是我们的牌有问题,这副牌不完整,这个时候我们一般选择中止游戏,不再接着继续出牌了。那么什么是CPU异常呢,CPU又如何处理异常呢?举个例子,当CPU检测到除0的指令时,CPU就认为程序出现异常了(除0是没有意义的,计算机无法计算结果),那么又如何处理异常呢,一般来说由相关的硬件强行改变CS:IP的值,将CS:IP的值指向处理该异常的一段新的指令地址(这里我们看到了规则2的应用,通过改变CS:IP来改变程序的执行流程,由于发生异常后CS:IP指向了新的地方,CPU就无法继续执行当前除0指令后面的程序指令了),而且新指向的处理异常的指令通常都是终止当前的程序,将程序从内存中卸载(参考规则1,内存和程序执行的关联)。因此我们知道写下如下程序时int a=1;int b=0;int c=a/b;int d=a+b;编译并运行程序会导致崩溃的原因是什么了。知道了为什么后面的int d=a+b指令为什么无法执行了。正是这些基础,让你知其然,更知其所以然。
规则4.上面所说的规则都是针对CPU等硬件而言的,下面我们说下操作系统的规则,因为计算机系统是一个分层的结构,我们很多时候不是直接在机器一层编程,而是在操作系统这一层。对于80386这样的硬件,因为有32根地址总线,因此逻辑空间为4GB,操作系统规定当CPU模式处在内核模式(需要了解CPU硬件的各种工作模式,这也是一个规则)的情况下,程序指令可以访问整个4GB的地址空间,当CPU模式处在用户模式的情况下,就只能访问低2GB的地址空间,不能访问高2GB的地址空间。类似于规则3中CPU的异常机制一样,操作系统也规定了一套异常机制,如果在用户模式下,检测到访问高2G地址空间的指令时操作系统就认为该指令是异常指令(注意:这是操作系统规定的异常指令而不是CPU规定的).类型于规则3中处理除0异常一样,操作系统也会终断当前程序,不再接着继续执行后面的程序指令。 所以当我们写下如下程序时,int *p = (int*)0xEFFFFFFF; *p = 0;在CPU的用户模式下编译运行时,程序会发生终止崩溃。现在你应该知其所以然了吧。(因为0xEFFFFFFF是高2GB的地址,在用户模式下访问该地址触发了操作系统异常)。
通过上面的叙述,我们可能对程序设计有了新的体会,那就是熟悉你当前编程的环境,知道有哪些机制,有哪些规则,哪些限制,只有知道这些基本概念了,你才能做到游刃有余,学习编程时心底更加踏实安稳,这不是仅仅背几个API,理解几个数据结构和算法就能登堂入室的