• 沒有找到結果。

指令系统是熟悉单片机功能、合理应用单片机的基础。掌握单片机指令的关键在于多看 多练,多上机练习,然后在现有程序的基础上进行模仿性编程。

汇编语言程序有 4 种结构形式,即顺序结构、分支结构、循环结构和子程序结构。下面 举例说明这 4 种程序结构及编程方法。

3.8.1 顺序结构程序设计

把 8000H 地址上的内容拆开,高位送 8001H 地址的低位,低位送 8002H 地址的低位,

8001H、8002H 地址的高位清零。本程序通常在把数据送显示缓冲区时使用。

程序流程图如图 3-1 所示,程序清单如下:

图 3-1 程序流程图

ORG 0000H

MOV DPTR,#8000H ;指定的字节 MOVX A,@DPTR

MOV B,A ;暂存

SWAP A ;交换

ANL A,#0FH ;屏敝高位 INC DPTR

MOVX @DPTR,A INC DPTR

MOV A,B

ANL A,#0FH ;指定字节的内容屏敝高位 MOVX @DPTR,A

LOOP: SJMP LOOP END 案例 5 拼字程序

把 8000H、8001H 两个字节的低位分别送入 8002H 的高位和低位。本程序一般用于把显 示缓冲区中的数据取出拼装成一个字节。

程序流程图如图 3-2 所示,程序清单如下:

ORG 0000H MOV DPTR,#8000H MOVX A,@DPTR

ANL A,#0FH ;屏敝高位 SWAP A

MOV B,A ;保存 INC DPTR

MOVX A,@DPTR ANL A,#0FH

ORL A,B ;合并

INC DPTR

MOVX @DPTR,A ;送 8002H 存放 LOOP: SJMP LOOP

END

图 3-2 程序流程图 案例 6 查表程序

求 R1 中的数(0~15 之间)平方,结果仍放回到 R1 中。

查表是计算机解决复杂问题所采取的一种简单而有效的方法。它根据变量 x 的值,在表 格中查找 y,使 y=f(x)。由于查表程序结构简单,执行速度快,因而广泛应用于数值计算、转 换、补偿、显示、打印等功能程序中。

设计查表程序的关键是善于组织表格,使其具有一定的规律性,便于编程查找。程序清 单(采用 DPTR 当基址寄存器)如下:

ORG 0100H

TAB2: PUSH DPH ;保存 DPTR 的原值 PUSH DPL

MOV DPTR, #TAB ;取平方表首地址 MOV A, R1

MOVC A, @A+DPTR ;查平方表 MOV R1, A

POP DPL ;恢复 DPTR 的原值 POP DPH

TAB: DB 0,1,4,9,16,25,39 ;平方表 DB 49,64,81,100,121 ;续表 DB 144,169,196,225 ;续表

为了保护调用程序中 DPTR 的值,在子程序中可以用堆栈进行保护,子程序返回之前应 正确恢复。

3.8.2 分支结构程序设计

程序分支是通过条件转移指令实现的,即根据条件对程序的执行进行判断,满足条件则 进行程序转移,不满足条件则顺序执行程序。

案例 7 无符号数的比较(单分支结构)

比较外部 RAM 的 Data1 和 Data2 单元的两个无符号数,并将大数存入 Data3 单元(Data1、

Data2、Data3 为 3 个连续的单元)。

解:该问题属于单分支结构,程序流程图如图 3-3 所示,程序清单如下:

图 3-3 无符号数的比较

ORG 1000H

COM1: MOV DPTR,#DATA1 ;设置外部数据存储器指针 MOV A,@DPTR ;取第一个数

MOV B,A ;暂存第一个数到 B

INC DPTR ;修改指针,指向第二个数所在的单元 MOVX A,@DPTR ;取第二个数到 A

CJNE A,B,L1 ;两数比较,产生 Cy 标志

L1: JC BIG1 ;若第二个数小于第一个数,则转向 BIG1;修改

;指针,指向 Data3 单元 BIG: INC DPTR

MOVX @DPTR,A ;存大数 RET

BIG1: XCH A,B ;将大数转移到 A SJMP BIG

END

案例 8 码制转换(双分支结构程序)

将 R2 中的一位十六进制数转换为 ASCII 码,结果仍放在 R2 中。

解:查 ASCII 码表可知数字 0~9 的 ASCII 码分别是 30H~39H;英文大写字母 A~F 的 ASCII 码分别是 41H~46H。可见该十六进制数若<10,要转换为 ASCII 码应加 30H;若≥10,

则加 37H。

该问题属于双分支结构,程序流程图如图 3-4 所示,程序清单如下:

图 3-4 十六进制数转换为 ASCII 码

ORG 0000H

HEXASC: MOV A, R2 ;将该十六进制数暂存于 A 中 CJNE A, #0AH, L1

L1: JNC ADD_37 ;判断是否小于 0AH ADD_30: ADD A, #30H ;小于 0AH,则加 30H

MOV R2, A ;保存结果

RET ;子程序返回

ADD_37: ADD A, #37H ;大于或等于 0AH,则加 37H MOV R2, A ;保存结果

RET

该程序使用了两个子程序返回指令,这也是双分支程序的一个特点。

案例 9 带符号数的比较(多分支结构程序)

比较内部 RAM 的 Data1 和 Data2 单元内以补码形式表示的两个带符号数,并将大数存入

BIG 单元,小数存入 SMALL 单元;若两数相等,则建立起标志位 F0。

解:要比较两个带符号数,不能依据 Cy 标志位判定其大小,其判定方法为:

(1)若 X、Y 两数符号相同,且(X-Y)为正,表明 X>Y。

(2)若 X、Y 两数符号不同,则根据符号判定大小。

程序流程图如图 3-5 所示,程序清单如下:

图 3-5 比较两个带符号数

DATA1 EQU 40H DATA2 EQU 41H BIG EQU 30H SMALL EQU 31H ORG 0000H COM2: MOV A, 40H

XRL A, 41H

JNZ STEP1 ;两数不等,转 STEP1 SETB F0 ;两数相等,F0 置位 RET

STEP1: JB ACC.7, TEST ;两数异号,转 TEST XRL A, 41H ;恢复 40H

SUBB A, 41H ;比较

JB ACC.7, STEP3 ;40H 小,转 STEP3 STEP2: MOV BIG, 40H

MOV SMALL, 41H RET

TEST: XRL A, 41H

JNB ACC.7, STEP2 ;40H 为正,转 STEP2 STEP3: MOV SMALL, 40H

MOV BIG, 41H

NEXT: INC R0 ;指向下一个数据单元 MOV A, @R0 ;取当前数据

CJNE A, Data2, COMP ;比较当前数与当前最大数

COMP: JC CON ;若当前数小于当前最大数,则继续 MOV Data2, A ;否则,把当前数当作最大数 CON: DJNZ Data1, NEXT ;判断数据是否比较完毕

RET ;比较结束 该程序属于“先执行后判断”结构的单循环程序。

3.8.4 子程序设计

对于一般的单片机应用系统,通常采用模块化程序设计方法来设计应用程序。所谓模块 化程序设计,就是把一个复杂的程序分成多个功能上相对独立的程序模块(即子程序),分别 编制、调试,然后连接在一起形成一个完整的程序。为此,对那些具有独立功能的或通用的或 需要多次重复使用的程序段,常编写成子程序,需要执行这段程序时,就用 ACALL 或 LCALL 指令调用该子程序,子程序执行完毕再由返回指令 RET 返回到调用程序继续执行。子程序调 用与返回过程如图 3-6 所示。

图 3-6 子程序的调用与返回

案例 12 一位数码管显示

P1 接七段数码管段数据口,P3.4 接七段数码管位数据口,编写程序,使一位数码管 0~9 循环点亮。数码管为共阴极数码管。

程序流程图如图 3-7 所示,程序清单如下:

ORG 0000H START: CLR P3.4

MOV P1,#3FH ;显示“0”

图 3-7

LCALL DELAY

MOV P1,#06H ;显示“1”

LCALL DELAY

MOV P1,#5BH ;显示“2”

LCALL DELAY

MOV P1,#4FH ;显示“3”

LCALL DELAY

MOV P1,#66H ;显示“4”

LCALL DELAY

MOV P1,#6DH ;显示“5”

LCALL DELAY

MOV P1,#7DH ;显示“6”

LCALL DELAY

MOV P1,#07H ;显示“7”

LCALL DELAY

MOV P1,#7FH ;显示“8”

LCALL DELAY

MOV P1,#67H ;显示“9”

LCALL DELAY LJMP START

DELAY: ;延时子程序

MOV R4,#10 D1: MOV R5,#200 D2: MOV R6,#126 D3: DJNZ R6,D3

DJNZ R5,D2 DJNZ R4,D1 RET

END

1.常用的程序结构有哪几种?特点如何?

2.什么是伪指令?常用的伪指令功能如何?

1.求 8 个无符号数的平均值,这 8 个无符号数存放在内部 RAM 以 20H 开始的 8 个单元 中,结果保存在 30H 中。

2.设内部 RAM 从 21H 单元开始存有一组带符号数,数据长度存于 20H 单元,要求把该 组数据中的正数、负数分别求和,并存放在寄存器 R6 和 R7 中。

3.设内部 RAM 从 LIST 单元开始存有一组无符号数据,数据个数为 30,编程找出其中 的最大数,并存入 BIG 单元中。

4.设内部 RAM 从 20H 单元开始存有 40H 个无符号数,试编制程序将它们按从大到小的 顺序排列,结果仍存放在原存储区域内。

5.试编写程序,将内部 RAM 的 20H、21H 单元的两个无符号数相乘,结果存放在 R2、

R3 中,R2 中存放高 8 位,R3 中存放低 8 位。

6.已知自变量 X 存放在 4000H 单元中,函数值 Y 存放在 4001H 单元中,编写程序计算 分支函数的值。

5X ;X 10H Y 4X 50H ;X 10H 3X 30H ;X 10H

 

  

  

7.编写排序程序,将地址为 30H~3FH 的片内数据存储器中的数据降序排序。

8.设被加数存放在内部 RAM 的 20H、21H 单元,加数存放在 22H、23H 单元,若要求 和存放在 24H、25H 中,试编写出 16 位数相加的程序。

指令系统功能的强弱决定了计算机性能的高低。80C51 单片机的指令系统共 111 条指令,

其指令的执行时间短、字节少,位操作指令极为丰富。

指令由操作码和操作数组成。寻址方式是寻找存放操作数的地址并将其提取出来的方法。

80C51 单片机有 7 种基本的寻址方式。

本模块以举例方式,对于初学者经常用到的各类指令和简单的程序类型进行了较详细的 注释。数据传送类程序的编写是初学者首先应掌握的,而数据传送空间是内部 RAM、寄存器 及外部数据空间及程序空间。因此,内部硬件结构及存储器结构应是初学者首先应该掌握的。

只有软件指令功能和硬件映像相结合,才能更好地掌握汇编源程序的编写。初学者可以结合本 模块中的例题和习题进行程序编写的练习。

相關文件