3.4 汇编语言程序设计基础
每一类CPU都有自己的指令系统,当指令和地址采用二进制代码表示时,称之为机器语言。CPU直接识别和执行的是机器语言的指令代码。
汇编语言是一种采用助记符表示的机器语言,即用助记符号来代表指令的操作码和操作数,用标识符代表地址、常数或变量。助记符一般都是英文单词的缩写,因此使用方便。这种用助记符和标识符编写的程序称为汇编语言源程序。
3.4.1 汇编语言特征
汇编语言是学习单片机应用编程的重要内容,其主要特征如下。
(1)汇编语言源程序与汇编程序(编译)
汇编语言源程序是用户编写的应用程序,它必须翻译成机器语言的目标代码(亦称目标程序)计算机才能执行。其翻译工作可由汇编(编译)程序自动完成,汇编程序的功能就是将用助记符号编写的源程序翻译成用机器语言表示的目标程序,如图3-1所示。
图3-1 汇编程序的功能示意图
(2)汇编语言与C51
在51单片机实际应用过程中,应用程序仍然可以采用汇编语言编写。虽然当前使用C51编写单片机应用程序已成为潮流,但汇编语言仍然是单片机应用的基本编程语言。在熟悉汇编语言的基础上再学习C51编程,是学习单片机C51程序设计的最佳途径。汇编语言的特点如下。
1)汇编语言是直接面向单片机硬件编程的,它反映了单片机指令执行的工作流程。学习汇编语言可以深刻理解单片机的工作原理,有助于编写高效率程序。
2)在功能相同的条件下,汇编语言生成的目标程序,所占用的存储单元比较少,而且执行的速度也比较快。
3)由于单片机应用的许多场合主要是输入/输出、检测及控制,而汇编语言具有直接针对输入/输出端口的操作指令,便于自控系统及检测系统中数据的采集与发送。
4)单片机资源的控制字等参数设置,在汇编语言源程序和C51程序中是相同的。汇编语言是直接对其资源进行操作的;C51对单片机资源的操作是通过自定义变量设置来完成的,这些变量需要说明为单片机内部资源的实际地址才有意义。
因此,汇编语言是学习单片机的重要组成部分,也是学习C51程序设计的基础。
3.4.2 汇编语言程序的组成
汇编语言源程序是由汇编语句组成的,一般情况下,汇编语言语句可分为:指令性语句(即汇编指令)和指示性语句(即伪指令)。
1.指令性语句
指令性语句由前已述及的指令系统所定义的汇编指令组成(简称指令),是进行汇编语言程序设计的可执行语句,每条指令都产生相应的机器语言的目标代码。源程序的主要功能是由指令性语句去完成的。
2.指示性语句
指示性语句(伪指令)又称汇编控制指令。它是控制汇编(翻译)过程的一些命令,程序员通过伪指令要求汇编程序在进行汇编时的一些定位、运算及符号转换操作。因此,伪指令不产生机器语言的目标代码,是汇编语言程序中的不可执行语句。
必须说明的是:汇编过程和程序的执行过程是两个不同的概念,汇编过程是将源程序翻译成机器语言的目标代码,此代码按照伪指令的安排存入存储器中。程序的执行过程是由CPU从存储器中逐条取出目标代码并逐条执行,完成程序设计的功能。
3.4.3 伪指令
伪指令主要用于指定源程序存放的起始地址、定义符号、指定暂存数据的存储区及将数据存入存储器、结束汇编等。一旦源程序被汇编成目标程序后,伪指令就不再出现(即它并不生成目标程序),而仅仅在对源程序的汇编过程中起作用。因此,伪指令给程序员编制源程序带来较多的方便。
51单片机汇编语言中常用的伪指令有以下几种。
1.ORG(汇编起始地址)
格式:ORG 16位地址
功能:规定了紧跟在该伪指令后的源程序经汇编后产生的目标程序存储在程序存储器中的起始地址。
汇编起始地址伪指令应用示例:
汇编结果:ORG 3000H下面的程序或数据存放在存储器3000H开始的单元中,标号START为符号地址,其值为3000H。
2.END(结束汇编)
格式:END或END 标号
功能:汇编语言源程序的结束标志,即通知汇编程序不再继续向下进行汇编。
如果源程序是一段子程序,则END后不加标号。
如果是主程序,加标号时,所加标号应为主程序模块的第一条指令的符号地址,汇编后程序从标号处开始执行。若不加标号,汇编后程序从0000H单元开始执行。
3.EQU(等值)
格式:标识符EQU数或汇编符号
功能:把数或汇编符号赋给标识符,且只能赋值一次。
等值伪指令应用示例:
等值伪指令应用示例:
这两个伪指令后面的指令序列放在地址001BH开始的存储单元中。
注意,EQU与前面的标号之间不要使用冒号,而只用一个空格来进行分隔。
4.DB(定义字节)
格式:[标号:]DB 项或项表
功能:将项(单数据)或项表(多数据)中的字节(8位)数据依次存入标号所指示的存储单元中。
注意:项与项之间用“,”分隔;字符型数据用" "括起来;数据可以采用二进制、十六进制及ASCII码等形式表示;省去标号不影响指令的功能;负数须转换成补码表示;可以多次使用DB定义字节。
定义字节伪指令应用示例1:
定义字节伪指令应用示例2:
该伪指令汇编结果:将12H存放在TAB(即2000H)单元,0AFH存放在TAB+1单元,00111001B存放在TAB+2单元,“9”存放在TAB+3单元。
5.DW(定义字)
格式:[标号:]DW 项或项表
功能:将项或项表中的字(16位)数据依次存入标号所指示的存储单元中。
定义字伪指令应用示例1:
定义字伪指令应用示例2:
该伪指令汇编结果为:将0102H存入TAB(3000H、3001H)单元,将0304H存入TAB+2(3002H、3003H)单元,将0506H存入TAB+4(3004H、3005H)单元。
若要定义多个字时,可以多次使用DB定义字节。
6.DS(定义存储单元)
格式:标号:DS数字
功能:从标号所指示的单元开始,根据数字的值保留一定数量的字节存储单元,留给以后存储数据用。
定义存储单元伪指令应用示例:
7.BIT(地址符号设置)
格式:标识符BIT 位地址
功能:将位地址赋以标识符(注意,不是标号)。
地址符号设置伪指令应用示例:
经以上定义后,A1和A2就可当作位地址来使用。
3.4.4 程序设计步骤及技术
汇编语言是面向CPU进行编程的语言。汇编语言程序设计除了应具有一般程序设计的特征外,还具有其自身的特殊性。
1.程序设计步骤
汇编语言程序设计一般经过以下几个步骤。
1)分析问题,明确任务要求,对于复杂的问题,需要抽象成数学模型,即用数学表达式来描述。
2)确定算法,即根据实际问题和指令系统的特点确定完成这一任务需经历的步骤。
3)根据所选择的算法,确定内存单元的分配;使用哪些存储器单元;使用哪些寄存器;程序运行中的中间数据及结果存放在哪些单元,以利于提高程序的效率和运行速度;然后制定出解决问题的步骤和顺序,画出程序的流程图。
4)根据流程图,编写源程序。
5)上机对源程序进行汇编、调试。
2.程序设计技术
在进行汇编语言程序设计时,对于同一问题,会有不同的编程方式,但应按照结构化程序设计的要求,即程序的基本结构应采用顺序、选择和循环3种基本结构,而实现基本结构的指令语句也会有多种不同的形式,因而在执行速度、所占内存空间、易读性和可维护性等方面就有所不同。
因此,在进行程序设计时,应注意以下事项和技巧。
1)把要解决的问题化成多个具有一定独立性的功能模块,各模块尽量采用子程序完成其功能。
2)力求少用无条件转移指令,尽量采用循环结构。
3)对主要的程序段要下功夫精心设计,这样会收到事半功倍的效果。如果在一个重复执行100次的循环程序中多用了2条指令,或者每次循环执行时间多用了2个机器周期,则整个循环就要多执行200条指令或多执行200个机器周期,使整个程序运行速度大大降低。
4)由于51单片机程序存储器的某些初始单元已有定义,因此,在需要使用这些单元或附近单元时,应在该单元内安排一条转移指令。
5)能用8位数据解决问题的就不要使用16位数据。
6)在中断处理程序中,要保护好现场(包括标志寄存器的内容),中断结束前要恢复现场。
7)累加器是信息传递的枢纽,在调用子程序时应通过累加器传送子程序的参数,通过累加器向主程序传送返回参数。所以,在子程序中一般不把累加器推入堆栈。若需保护累加器的内容时,应先把累加器的内容存入其他寄存器单元,然后再调用子程序。
8)为了保证程序运行的安全可靠,应考虑使用软件抗干扰技术,如数字滤波技术、指令冗余技术、软件陷阱技术,用汇编语言程序实现这些技术,不需要增加硬件成本,可靠性高,稳定性好,方便灵活。
用汇编语言编写程序,对于初学者来说容易遇到困难,程序设计者只有通过实践,不断积累经验,才能编写出较高质量的程序。