首页 > 教程 > 正文

阅读排行

程序设计的几个基本概念
2014-01-20 11:01:21   来源:Fcode研讨团队   评论:0 点击:

本文介绍了程序设计的基础概念,是大多数教科书第一章的补充。


有位朋友刚开始学编程,所以以下文字写给她的。高手就不用看了~~


关于程序设计的几个基本概念,其实还是蛮重要的。然而很多新手,甚至已经书写过很多程序的老手,他们的这些概念都非常的模糊。


首先说一说高级语言和汇编语言,以及机器语言的区别和联系。很多课本上也都有提到过,但都比较模糊,难以深刻的理解。


实际上,我们的计算机是不懂得我们的语言的(中文,英文等)。而计算机处理数据,只是 1 和 0 两种而已。因此,真正的计算机执行的命令,都是以 0 和 1 这样的数字形式存在的。不同的处理器,他们的执行命令也不同,但基本上已经形成业内的一些规范和指令集。


而机器语言由于都是用数字表示的指令和数据,因此非常的生涩,几乎不会有人直接使用它写程序。


于是,人们使用更方便理解的具有一定意义的文字的命令去一一对应这些机器语言。这样相当于提供了一种人可以接受的机器语言形式,这就是汇编语言。


汇编语言与机器语言的对应关系非常直接,非常简单,这就使得机器语言与汇编语言之间,存在一种很直接的相互转换过程。这就是汇编和反汇编。(汇编指从汇编语言到机器语言,反汇编则相反)(实际上,某些汇编语句还是需要转换的,但绝大多数都可以直接与机器语言对应)


汇编的过程,就是一个汇编程序(比如微软的 MASM)将一个文本形式的汇编源代码(比如 *.asm 文件)翻译成机器语言的过程。


比如有以下的 *.asm 文件代码段:


   rA dd ?   ;定义 rA 变量


   rB dd ?   ;定义 rB 变量


   rC dd ?   ;定义 rC 变量


.code


start:


   mov rA , 1   ;为 rA 赋值为 1


   mov rB , 2   ;为 rB 赋值为 2


   mov eax , rA   ;将 rA 装载入 eax 寄存器


   add eax , rB   ;在 eax 寄存器加上 rB 的值


   mov rC , eax   ;将相加的结果,也就是 eax 寄存器的值放入 rC 变量


    当然,我们的汇编程序并不是死死的要求我们敲入一个又一个的变量地址。汇编程序还有很多功能,比如变量内存管理。

如上代码提到的变量 rA,rB 和 rC 三个变量。汇编程序自动为我们分配了地址。而所有的定义语句,在汇编后将不再存在。


以上的汇编语句,经过汇编以后,就变成了形如以下的机器语言(后面对应了反汇编后的“汇编”表达形式):


C705 00304000 01000000       ;mov dword ptr [403000], 1


C705 04304000 02000000       ;mov dword ptr [403004], 2


A1 00304000                  ;mov eax, [403000]


0305 04304000                ;add eax, [403004]


A3 08304000                  ;mov [403008], eax



这里的 [403000] 就是 rA 的地址,[403004] 是 rB 的,而 [403008] 是 rC 的。也就是说,经过汇编之后,所有的变量名变成了地址,所有的函数,也变成了地址,所有的常量也变成了它的值。这样,我们在书写汇编语言代码的时候,就不需要去考虑内存地址的问题,简化了我们的工作。而从“变量名”(如 rA,rB,rC)到“内存空间”(如 403000,403004),是由汇编程序去完成分配的。


正因为源代码中的变量都变成了地址,因此我们在拿到别人的可执行文件(如 EXE),再经过反汇编后,我们无法得到原始的源代码。我们看到的,是一堆不可直接理解的内存地址...从 EXE 得到原始的源代码,几乎是不可能的,因为在汇编(高级语言的编译)过程中,很多很多信息都已经丢失了。


上面以一个例子显示了汇编语言与机器语言,以及与反汇编后看到的“汇编语言”的一些区别和联系。其实它们之间还有更多更多的关联。就不再描述了。


由于汇编语言的操作非常细致,因此要完成一个简单的动作,就需要大量的语句。而且书写起来不够直观。因此人们制定了高级语言规范(比如 C,C++,Java,BASIC 等)。并设计开发了高级语言编译器。(这里的编译器区别于汇编语言的汇编程序)


编译器是把高级语言的源代码文件(比如 C 语言的 *.cpp 源代码文件)转换成对应平台的目标代码(机器语言)的程序。


比如以上的汇编代码,如果写成高级语言,则可能很简单的书写为:


rC = rA + rB


经过高级语言的编译器编译之后,得到的目标程序(比如 EXE),它的指令类似与上面描述的一长串机器语言指令。


这样的高级语言书写形式,更符合人们的习惯。也更容易理解和修改。这样的形式也更容易方便的完成一些列的动作。更简单直接。


也因为这样的书写方式更远离机器语言,因此翻译这样的高级语言源代码也就更复杂,设计高级语言编译器的难度就更大。


同时,因为高级语言的书写更简单,因此必然导致同样的高级语言语句,可以有不同的机器语言实现方法。这些方法,有些更好,有些就比较糟糕。如何选择更高效的方法实现高级语言功能,这是不同编译器选择优化的不同考虑。也就是说,同一段高级语言代码,经过不同的编译器编译,得到的目标程序是不同的,而且区别会很大。


同时,由于操作系统的出现,代替了刚开始应用程序的磁盘管理,文件管理,内存管理....使得不同操作系统,不同平台下,需要不同的目标程序。而人们书写代码之后,往往希望能够应用到不同的操作系统或平台。因此,高级语言可以一定程度上满足这种需求。同样的高级语言代码,经过 Windows 下 Win32 编译器编译,可以得到程序的 Win32 版本;经过 .NET 平台编译器编译,可以得到程序的 .NET 版本;在 Linux 下,用 Linux 下的编译器编译,又可以得到程序的 Linux 版本。


当然了,这样的跨平台,只是针对源代码而言的。如果要向另一个平台转移,一般是需要重新编译,重新获得目标程序的。而不是一个高级语言书写的程序,获得的目标程序就可以在不同平台上运行。


实际上,很多程序,在书写的初期,就使用了某些平台的特性(比如涉及注册表的内容,就只能在 Windows 下使用)。这样,就决定了他们只能在某个平台上使用,在其他平台上编译,会出现错误。或者源代码需要一定的改动。当然,这比完全重写要容易得多。


正因为高级语言与汇编/机器语言的对应关系不再是单一的一一对应关系,因此,人们制定了很多高级语言规范(比如 C,C++,Java,BASIC,Java 等),以满足不同的需要。而同一种高级语言规范,全世界各开发商,又开发了不同的编译器(比如 C++ 的编译器就有微软的 Visual C++,Borland 的 C++ Builder 等)。这些编译器哪个更好,也不是三言两语可以说清楚的。它们都各有各的长处,各有各的应用领域,而每个程序员也都有自己的习惯,需求。


相比汇编语言汇编成机器语言的一一对应来说,编译的过程就有了很高的灵活度。因此各个编译器开发商,都在极力的宣言自己能够快速的生成小巧,精炼的汇编代码,提高目标程序的执行效率。对高级语言代码的最优编译,是编译器不断追求的目标。


作为一个商业的编译器产品来说,除了编译器,更多的,还有为书写代码方便而提供的代码编辑器,编辑环境(IDE),调试器,各种库文件,头文件,说明书,帮助文档,演示代码等。这就使得本来应该很小的编译器(最多几个 MB),在成为一个编译器产品后,变得十分庞大(多达几百 MB,甚至几个 GB)。


对于大多数编译器来说,都有自己面向的高级语言规范和目标平台。比如 Visual C++ 面向 C++ 语言的源代码,目标平台是 Windows 的 Win32 平台。当然有些编译器也可以生成 .NET 平台的目标程序。因为高级语言规范是逻辑上的规定,它是不依赖于平台的,因此语法规范上通常都没有涉及到具体实现的细节。这些细节,是交给编译器去发挥的。因此,大多数人学习一门语言之后,还很奇怪,为什么这些和自己接触到的很多计算机知识(比如注册表,对话框等等)联系不上,自己书写的程序为什么还是一个黑黑的,像 DOS 一样的窗口?


这是因为,类似注册表,对话框,图标这些特征。都是依赖于平台的,比如只有 Windows 操作系统才有注册表,而不同操作系统的对话框或各种按钮,实现的细节不同。语法规范上一般不会对这些做出规定。是商业化的编译器为了让用户使用这些平台相关的特征,才会附带一系列的扩展功能(比如对 Windows API 的支持,对 OpenGL 的支持等)。正是使用它们,才能设计出各种漂亮的界面化的窗口程序。


实际上,这种黑黑的像 DOS 一样窗口的程序,有一个名词,叫做 Console(控制台) 程序。它们区别有界面的那些 GUI (图形用户界面)程序。我们熟悉的 QQ,迅雷这些商业软件都是 GUI 程序。WinRAR 也是 GUI 程序。


但是,请不要忽视了 Console 程序的地位。我们使用的编译器自身,绝大多数都是 Console 程序; WinRAR 的内核:rar.exe 也是 Console 程序。Console 程序大多数来说,是内涵型的。他们没有华丽的外表,却往往在后台默默的工作,不为人知。


作为学习程序设计来说,我们应当首先对语法规范有足够的了解,对数据结构的理解,对算法的理解,对逻辑层次的理解,这些都是非常重要的。不要因为自己还在设计 Console 程序,而别人已经能够设计漂亮的界面了,就感到自卑,等你熟悉了算法,数据结构,编程思想之后,再去学习附带的扩展的界面化的功能,就会十分的轻松了。

相关热词搜索:程序设计 概念

上一篇:随心所欲控制 write(*,*)
下一篇:Fortran 二进制文件读写

分享到: 收藏