一、分支程序
(乌振声 黄金明)在程序设计中,经常会遇到各种判断和比较,如“相等”和“不相等”;“大于”和“小于”;“满足条件”和“不满足条件”等等。这些判断和比较在程序中都可以组成各种不同的逻辑框,并产生相应的分支程序,根据不同条件可以使程序转向不同的分支。所以。一般一个程序都不会是一直执行下去的一个模块的结构,而是有许多条件判断的多模块结构。
例如符号函数就是一个例子:

下面我们用65SC02的汇编指令来实现符号函数。假设自变量X的值已存入标号为VAL的单元中,求出的函数值放在标号为RES的单元中,X(-128≤X≤+127)为带符号的8位二进制数。用条件转移指令即可按标志位的情况,实现程序的分支。程序框图如图1所示,程序如下:

START LDA VAL ;X→A
CMP #$OO ;查X的特点
BEQ ZERO ;X=0
BMI MINUS ;X<0
LDA #$1 ;X>Q,则1→A
JMP ASSIGN
ZERO LDA #$00 ;X=0,则
JMP ASSIGN
MINUS LDA #$-1 ;X<0,则-1→A
ASSIGN STA RES ;A→Y
END
二、循环程序
前面介绍的分支程序根据条件的不同,跳过一些指令转而执行另一些指令,最多也只能执行一次。在某些情况下,程序中的某一段程序要反复执行多次,这段反复被执行多次的程序环称之为循环程序。循程序使程序长度大大缩短,所以,凡能使用循环程序的地方应尽量采用它。
循环程序一般由四部分组成:①、初始化部分:分为循环工作部分的初始化和结束条件的初始化。②、处理部分:它进行数据处理和操作。③、循环控制部分:用来判断循环结束的条件。④、结束部分:循环程序的构成如图2所示。必须注意:不要使循环返回至初始化部分,否则会导致死循环,这是初学者常出的错误。

[例]将存放在2000—20FF单元中的256个数据送到3000—30FF单元中去。
由于每一次传送数据的指令的操作码都是一样的,只是每一次传送数据的源地址和目的地址不一样。这样,用X寄存器的零页变址方式,把源地址和目的地址放在零页单元中,然后用加1的指令来修改源地址和目的地址,则传送指令对任何一次传送都是一样的。这样可以循环使用传送指令。本题程序框图如图3所示。

源程序:
ORG
DFB $00,$20 ;源数据块首地址填入;1A,1B单元
ORG
DFB $00,$30 ;目的块首地址填入FA,FB单元
ORGC $1000 ;源程序起始地址
START LDX #OO ;0→变址寄存器X
LDY #$FF ;数据块长度→Y
MOVE LDA($1A,X);传送一个源数据
STA($FA,X);到目的地址单元中
INC $1A,X 修改源地址,使之加1
INC $FA,X ;修改目的地址,使之加1
DEY ;数据块长度-1→Y
BNE MOVE ;数据未传送完,继续循环传送
BRK;结束
三、子程序
在程序编写过程中,经常会遇到相同的计算或操作。例如,作乘法、除法、求平方根、三角函数等,如果每次都从头开始编写计算程序,不仅麻烦而且是一种浪费。所以,把这些相同的部分编写成一个独立的程序段,称之为子程序。当遇到相同的计算或操作时就调用子程序,而不必对这些相同部分重复编写程序了。通常情况下,整个程序是由主程序和几个子程序组成的。65SC02微处理机备有专门的转子指令JSR,用以把控制转移到子程序。还备有专门的子程序返回指令RTS,用以使子程序返回到主程序。主,子程序关系如图4所示。

在存储器M4地址中,存放着一条转子指令JSR ROUT,当主程序执行到地址M4中的转子指令时,要求如下:
1.将主程序的断点地址M5压入堆栈,并把子程序ROUT的起始地址送入程序计数器PC,实现向子程序的转移。
2.在子程序的最后一条指令必须是RTS返回指令,它能使主程序的断点地址M5从堆栈中退出送入程序计数器PC,从而使主程序能继续往下执行。
[例]在16个不带符号的二进制数据中找最大值。数据在放在2000—200F之间的单元中,求得的最大值存入06单元。

在这个例子中,把两个数之间的比较单独编成一个子程序。子程序的功能就是把两个数中较大的数存入A寄存器。A寄存器中总是存放着已比较过的数据中的最大值。通过Y寄存器每次加1,即可实现存放数据的内存地址加1,又可兼作数据块的长度计数。由于共有16个数据要进行比较,所以,主程序需要调用子程序16次,才能找出最大值。程序框图如图5所示。
程序如下:
ORG $1000
START LDA #00 ;数据块首址送08和07单元
STA $07 ;即(08)(07)=$2000
LPA #$20
STA $08
LDY #00 ;置计数器Y初值=0
LDA #00 ;设最大值为0放在A中
LOOP JSR MAXM
INY ;计数器+1
CPY #$10 ;计数器中的值=16?
BNE LOOP ;不等于数据块长度、继续比较
STA $06 ;最大值送06单元
BRK ;结束
MAXM CMP($07),Y ;下一个数>最大值?
BCS NOCHG ;不大于时,最大值保持不变
LDA($07),Y;大于时,换最大值存入A中
NOCHG RTS ;返回主程序
四、程序举例
在显示器屏幕的顶端显示“PLEASE TYPE LETTERA”一串字符。然后从键盘输入字母A,则在下一行继续显示“PLEASE TYPE LETTER A”字符串。
在这个例子中,需要调用监控程序中的几个子程序,下面先把监控程序中的几个子程序入口地址介绍一下。
$FC58:清屏幕子程序
$FE89:设定键盘为输入设备子程序
$FE93:设定CRT为输出设备子程序
$FDFO:输出一个字符到CRT子程序
$FD35:从输入设备读一个字符子程序
程序如下:
ORG $1000
START JSR $FC58
JSR $FE89
JSR $FE93
LOOP LDY # $00
LDA DISAD,Y
STA $05
INY
LDA DISAD,Y
STA $04
DIS1 LDY # $00
LDA ($04),Y;
CMP #$00
BEQ RD1
JSR $FDFO;
JSR CAL
JMP DIS1
RD1 JSR $FD35
CMP #$C1
BNE RD1
JMP LOOP
CAL CLC
LDA $04
ADC #$01
STA $O4
LDA $05
ADC #$00
STA $05
RTS
DISAD DBY DISPLAY
DISPLAY BYT $8D,
ASC“PLEASE-TYPE-LET-TERA”
BYT $6A,$00
END