熊小兵 刘丹
摘要:从汇编语言程序设计在计算机相关专业课程体系中的地位与作用出发,说明在新形势下继续开设这门课程的一些基本问题,包括地位与作用、定位与内容、重点与难点以及方法与评价等,阐述在教学中应当采取怎样的对策以解决这类问题。
关键词:汇编语言;程序设计;课程改革
引 言
汇编语言程序设计作为一门独立的课程在诞生之初,一直是各高校计算机专业的一门专业必修课。近年来,国内一些高校(尤其是重点高校)的计算机相关专业在进行培养方案修订时,大都对这门课程做了较大调整。有些学校将其由必修课改成选修课,有些学校将其课时做了较大压缩,有些学校甚至干脆取消这门课。
1 地位与作用问题
汇编语言程序设计在所有专业课(含专业基础课)中具有独特的地位与作用。一直以来,计算机及其应用系统的构成基本上分为硬件和软件两大块,计算机相关专业所涵盖的学科理论知识与工程技术也相应地分为硬件和软件两大块。受此影响,在人才培养实践中,计算机相关专业所开没的基础课程也主要围绕这两大块展开。硬件主要有电子技术基础、数字逻辑、计算机组成原理、系统结构等,而软件主要有数据结构、高级语言程序设计、操作系统、数据库等。
从硬件和软件的关系看,计算机及其应用系统的工作以硬件为基础,却以软件为动力,硬件和软件密不可分,硬件要靠软件驱动。一般而言,以计算机系统为核心的应用开发必须是硬件开发和软件开发同时伴随,因此有些课程注定要同时围绕硬件和软件两方面展开,如汇编语言程序设计、接口技术、单片机、嵌入式系统等。
在所有这些软件和硬件紧密结合的课程中,汇编语言程序设计又是基础课。通过学习汇编语言程序设计,学生不仅可以更加透彻地理解在其他课程中学习过的有关知识,更加深入地了解计算机系统的内部工作机制,而且能为后续接口技术、单片机、嵌入式系统等课程的学习打下坚实基础。
总之,汇编语言程序设计把硬件和软件有机地紧密结合在一起,能让学生对传统意义上的两大块有一个更全面同时也更深入的认识和理解。鉴于以上认识,笔者认为各高校计算机相关专业在进行培养方案修订时不宜完全取消汇编语言程序设计这门课程。
2 定位与内容问题
程序设计语言经历了机器语言、汇编语言、高级语言等发展阶段。从编程效率看,汇编语言不及高级语言,但从语言的整体功能看,汇编语言比高级语言要强,通俗点说就是指高级语言能做到的事,汇编语言都能做到,但反过来则未必。
高级语言程序设计的主要内容包括两部分:高级语言和程序设计。汇编语言程序设计也不例外,其主要内容也由两部分构成:汇编语言和程序设计。事实上,不管学习什么语言程序设计,主要内容就是两个:程序设计的基本思想方法和语言本身。
由于语言只是程序的载体,是程序设计的工具,因此第1个内容即程序设计的思想方法是相通的。鉴于此,汇编语言程序设计的教学应该以汇编语言本身为重点,即汇编语言为程序设计提供的各个元素及其应用,内容应该包括数据表示、数据安排、寻址方式、指令系统、程序结构、流程控制、参数传递、中断调用、数据处理等;而其定位应该是让学生掌握最基本的知识和能力,一方面让学生通过学习汇编语言深入理解计算机系统内部的工作机制,另一方面能让学生在必要时借助汇编语言弥补高级语言的功能性不足。
3 重点与难点问题
3.1 数据表示问题
计算机的基本功能就是加工处理数据,数据需要存放到计算机系统中。实际应用中的数据丰富多彩,具有各种不同的类型;而计算机中的数据则单调得多。应用中各种不同类型的数据如何在计算机中以恰当的形式表示出来,就是程序设计面临的首要问题。
数据在计算机中的表示有多种方法,不同方法有各自的优缺点,适用于不同的应用要求。基本上来说,计算机系统对数据的加工处理主要是数据运算和数据输入输出。为了节约存储空间,我们一般比较喜欢2进制代码长度比较小即2进制代码比较短的表示方法。在2进制代码长度方面,数值数据的代码表示一般不如其2进制表示。
计算机对数值数据最重要的加工处理就是算术运算,为了方便运算,我们比较喜欢2进制表示,即在运算方面数值数据的2进制表示要优于其代码表示。采用2进制表示的主要问题是溢出,但这同时也是代码表示的主要问题之一。此外,代码表示即使没有溢出,也可能得到错误的结果。计算机对数据进行加T处理时,加工处理之前要输入原始数据,加工处理之后要输出结果数据,我们当然希望采用比较有利于输入/输出的表示法。在这方面,数据的代码表示要比其2进制表示好。
代码形式的数据在输入/输出时只需要采用简单的移位操作即可实现,因为每一位上的数都有同样长度的代码,而且数据在输入/输出时本身就是通过代码进行标识。例如,在西文环境中普遍采用ASCII码标识每一个常用字符,因此ASCII码形式的数值数据在输入/输出时特别有优势:输出时只需要8位8位的进行分割,就可以得到每一位上的数,而且不需要做任何转换就可以送往输出设备输出;输入时不需要做任何转换,只需要8位8位的进行拼接,就可以得到整个数。如果是2进制形式,则要麻烦得多:输出时需要通过除法等分离出每一位上的数,然后转换成ASCII码后才能送往输出设备输出;输入时需要将ASCII码转换成对应的一位数,然后通过乘法和加法等拼成一个整体。
总之,学生要学会在深刻理解并熟练掌握各种数据表示方法的基础上,善于根据需要灵活选择合适的数据表示方法。这一部分的教学内容主要是介绍基本的数据表示方法及各自的优缺点,尤其注重学生对各种表示方法的理解。
3.2 寻址方式问题
计算机的工作由程序驱动,而概括地说,程序又是加工处理数据的。不管是程序加丁.处理的数据,还是程序本身,在程序执行时都要存放到仔储器巾。
程序在执行过程中,需要不断地从存储器中取指令和数据,往存储器中存数据,这就面临一个非常重要的问题——寻址。从应用层面看,程序有结构问题:顺序结构、分支结构和循环结构等;而数据也有结构问题:一维结构、二维结构、三维结构等。不同的程序结构和数据结构对寻址方式的要求不一样,为了满足这种差异性,系统必须提供多种不同的寻址方式。
以Inte18086为例,立即寻址主要用来处理常量,其他寻址方式则主要用来访问变量,包括寄存器寻址、直接寻址、寄存器间接寻址、相对寄存器寻址、基址变址和相对基址变址等 。在访问变量的各种寻址方式中,寄存器寻址主要用来访问寄存器变量,而其他寻址方式则主要用来访问内存变量。在访问内存变量的各种寻址方式巾,直接寻址方式主要用在顺序结构巾,而其他寻址方式则主要用在循环结构中。在用于循环结构的寻址方式中,寄存器间接寻址和相对寄存器寻址主要用于一维数据结构,而基址变址和相对基址变址则主要用于二维数据结构。
这一部分的教学内容主要是存取数据和指令所需要的各种寻址方式,重点是各寻址方式的表达形式、构成成分及各成分的作用。
3.3 指令系统问题
程序主要是加工处理数据的,同时程序主要由指令构成,因此指令的主要功能也是围绕加工处理数据展开。
一般而言,一条完整的指令主要围绕4个问题展开:①什么地方或什么样的数;②与什么地方或什么样的数;③做什么样的运算;④结果放到什么地方。什么样的数即常数(常量),既可以是数值常数,又可以是符号常数。什么地方的数即变数(变量),既可以是寄存器数,义可以是内存数。上述4个问题中,①②④由指令巾的操作数(常数)或地址码(变数)表达,而③则由指令中的操作码表达 。
这一部分的教学内容主要是介绍一些最常用、最基本的指令,重点是各指令的功能、格式和用法,
3.4 流程控制问题
流程控制是所有程序都不可回避的问题。汇编语言程序的流程控制主要包括分支控制、循环控制、中断调用、子程序调用。由于程序总是试图顺序执行,因此顺序结构的流程控制不需要特别关心。实际上,这个问题已经由系统解决。
不管哪种类型的流程控制,它们都是通过执行相应的流程控制指令,让原本顺序执行的流程转移到某个目标位置来实现,因此流程控制的一个核心问题就是如何在流程控制指令中正确地提供目标地址 。此时的目标地址就是一个广义的数据,因此数据的寻址方式也可以用在指令寻址中。
这一部分的教学内容主要是各种类型流程控制所需要用到的基本指令,重点是各指令的功能、格式及其用法,尤其是如何利用转移指令实现分支和循环。
3.5 参数传递问题
按模块化程序设计思想,一个规模较大、功能较复杂的程序通常由一个主程序和若干个子程序构成,它们之间形成调用和被调用的关系。主程序在通过调用子程序为自己解决某些问题时,通常需要为子程序提供一些相关的数据,子程序在内部对这些数据做相应的加工处理后再将处理结果返回给主程序,这就是所谓的参数传递问题。主程序提供给子程序的数据通常叫做人口参数,而子程序返回给主程序的数据则通常叫做出口参数。
需要做参数传递时,通常有两种选择:一种方法是直接传递所需要的数据,另一种方法是传递所需数据的位置信息即地址。第一种方法即通常所说的值传递,第二种方法即通常所说的地址传递。需要注意的是,传地址的目的也是为了传数据。在具体实现时,不管哪种做法即不管是值传递还是地址传递,都需要事先约定好一个地方,这是它们的共同点;不同点在于值传递是将所需要的数据本身放在这个事先约定好的地方,而地址传递是将所需要数据的位置信息即地址放在这个事先约定好的地方。约定地方时既可以约定寄存器,又可以约定内存单元,还可以约定堆栈,因此具体的参数传递方式灵活多样,而且各有各的优势,在实际应用中通常综合以上各种做法以求达到较好的效果。
一般来说,当参数比较少时,值传递比较合适;而当参数比较多时,地址传递比较合适。约定寄存器只适合于少量参数的传递,而约定内存则没有此限制。参数交换示意图如图1所示。
根据需要,一个子程序可以调用另一个子程序,也可以调用自己本身,这种情况就是所谓的递归调用,此时的子程序通常叫做递归子程序。凡是能够用递推关系描述的问题,都可以通过递归方法求解。
递归子程序的执行过程可以分成两个阶段:回溯和返回。回溯就是层层递归,将未知的、比较复杂的求解问题逐渐转化成已知的、比较简单的求解问题。在回溯的过程中,一旦层层递归到简单问题的求解,就不再继续递归,而是直接解出这个比较简单的问题,然后进入返回阶段。回溯是一个层层递归的过程,因此返回也是一层一层进行。写递归子程序的重点和难点在于回溯数据在保存和返回时的使用。
这一部分的教学内容主要是参数传递的各种方法及其优缺点。
4 方法与评价问题
如前所述,汇编语言和高级语言虽然是不同的程序设计语言,但是它们都是程序设计的工具,而程序设计的基本思想和方法不受程序设计语言的限制。汇编语言程序设计开没在高级语言程序设计之后,因此教师在教学中应充分利用它们两者之间的联系与差别组织教学,充分利用学习迁移规律减轻学生的学习负担,同时提高学习效率,加深理解。
在教学过程中,教师可以围绕两个基本点进行汇编语言和高级语言的比较教学:一是围绕程序的功能(数据安排、数据输入、数据运算、数据输出),介绍汇编语言为了实现这些功能而提供的相应处理机制;二是围绕程序的结构(顺序结构、分支结构、循环结构、子程序结构),介绍汇编语言为了实现这些结构而提供的相应处理机制。由于学生已经有了在高级语言程序设计课程中习得的各种编程经验,因此教师在进行汇编语言程序设计教学时,不管讲授什么内容,都要注意和高级语言作比较,利用高级语言提高教学效率。
关于教学效果的评价,根据自身多年的教学实践经验,笔者认为采用开卷考试或者撰写课程论文的方式比较适合。如果选择开卷考试,可以以主观题为主甚至全部采用主观题;如果选择课程论文,则可以对汇编语言和高级语言进行对比研究。值得强调的是,评价方式要灵活多样,具体依教学要求和评价目标而定。
5 结语
虽然汇编语言在应用开发尤其是纯软件的应用开发方面并不具有优势,但是在教育教学上却有着不可忽视的作用。在计算机专业几门核心课程的教学中,教师就可以充分利用汇编语言提高教学效果,在组成原理的教学中利用汇编指令讲述指令系统,在接口技术的教学中利用汇编语言编写相应的硬件驱动程序,在编译技术的教学中利用汇编语言作为编译的中间码讲述编译优化,不仅可以简化问题、提高效率,而且更方便学生理解和接受。