转载:Casl汇编语言辅导

一、Casl汇编语言语法介绍

学习一个汇编语言需要掌握3个要点:CPU 的可编程寄存器结构、寻址方式及指令系统、伪指令。

1、COMETCPU 的可编程寄存器

COMETCPU 字长 16 位,采用从左到右的编号。bit0 在最左边(最高位),bit15 在最右边(最低位)

0123456789101112131415
                

1)16 位通用寄存器五个:

GR0、GR1、GR2、GR3、GR4

通用功能:各种算术逻辑运算

特殊功能:除 GR0 外都可作变址寄存器(地址指针)XR,GR0 可看成累加器。

GR4 兼作堆栈指针(SP)

2)指令计数器 PC 一个(16位)

存放正在执行的那条指令的第 1 个字的地址(一条指令占二个字),指令结束时,PC 中存放下一条指令的地址(一般为原指令地址 +2 )。

3)状态寄存器 FR 一个(二位)

运算结果FR0FR1
大于 00
等于01
小于10

 

可以把 FR0 看成 SF(符号位),FR1 看成 ZF(零位位)

除了算术逻辑运算指令(包括移位指令)外,LEA 指令也会影响 FR

2、符号指令写法与寻址方式

OP GR,ADR[,XR]

其中 OP 为操作码;GR 为五个通用寄存器 GR0~GR4 之一;ADR 为一个 16 位的地址码;XR 为四个变址寄存器 GR1~GR4 之一,[ ]表示可以省略。

1)直接寻址:当 [,XR] 省略时,为直接寻址。

2)变址寻址:有效地址 E = ADR +(XR),当 ADR = 0 时,为寄存器间接寻址。

3)立即数寻址:Casl 没有立即数寻址。但在 LEA 指令中,当 [,XR] 省略时,可作立即数传送。没有立即数运算指令。

4)寄存器寻址:Casl 也没有寄存器寻址(对源操作数)。但 LEA 指令当 ADR = 0 时,可作寄存器寻址(只用于数据传送)。

3、Casl指令系统

1)取数指令 LD:内存→寄存器

LD GR,ADR[,XR]

2)存数指令 ST:寄存器→内存

ST GR,ADR[,XR]

3)加法 ADD、减法 SUB、逻辑与 AND、逻辑或OR、逻辑异或 EOR指令:

ADD 
SUB 
ANDGR,ADR[,XR]
OR 
EOR 

内存 OP 寄存器→寄存器

4)算术比较 CPA:

两个带符号数比较,结果不回送,只影响标志位。

CPA GR,ADR[,XR]

5)逻辑比较 CPL:两个无符号数比较,结果不回送,只影响标志位。

CPL GR,ADR[,XR]

6)算术左移 SLA、算术右移 SRA:把操作数看成带符号数。对寄存器操作数进行移位(GR 的第 0 位——符号位不变。右移时空出的其余位补与第 0 位相同的 1 或 0 ;左移时空出的位补 0 ),位数由有效地址 E 决定。

SLAGR,ADR[,XR]
SRA

7)逻辑左移 SLL、逻辑右移 SRL:把操作数看成无符号数。对寄存器操作数进行移位(不管左右移,GR 空出的位补 0 ),位数由有效地址 E 决定。

SLLGR,ADR[,XR]
SRL

8)取有效地址指令LEA:E→寄存器

LEA GR,ADR[,XR]

该指令有几个特殊用途:

【例1】LEA GR0,41H 把立即数 41H 送给 GR0

【例2】LEA GR0,0,GR1 把寄存器 GR1 的内容送给 GR0

【例3】LEA GR1,1,GR1 寄存器 GR1 的内容加 1(相当于 8086 汇编中的 INC 指令)

9)无条件转移指令JMP与条件转移指令JPZ(不小于转)、JMI(小于转)、JNZ(不等于转)、JZE(等于转)

JMP 
JPZ 
JMIADR[,XR]
JNZ 
JZE 

●当地址码中缺 [XR] 时,所有转移指令为直接转移( ADR 即为转移地址)

     当地址码中有 [XR] 时,所有转移指令为间接相对接转移

●JPZ 与 JMI 根据符号位 FR0 作为判断条件

     JNZ 与 JZE 根据零位位 FR1 作为判断条件

10)进栈 PUSH 与出栈 POP:

(1)进栈指令 PUSH:

PUSHADR[,XR]

(SP)-1→SP,E→(SP)

(2)出栈指令 POP:

POPGR

((SP))→GR,(SP)+1→SP

注意:出栈指令的目的寄存器是 GR0~GR4,而进栈指令的源操作数不包括 GR0。 

11)子程序调用CALL与返回 RET指令

4、伪指令

1)START:程序开始

2)END:程序结尾

3)常量定义指令 DC

此伪指令与其它汇编语言中的 DB 指令似。利用 DC 指令可定义:

(1)定义十进制常数:

十进制常数名DCn

其中 -32768 < n ≤65535

(2)定义字符串常数:

字符串常数名DC'字符串'

(3)定义十六进制常数:

十六进制常数名DC#h

其中 0000 ≤ h ≤FFFF

(4)定义地址:

地址常数DCLABLE

其中 LABLE 是程序中的地址标号

因为 Casl 没有立即数运算指令,所以需要与立即数进行算术逻辑运算时,都要将立即数定义为内存常数进行运算。

4)变量定义指令 DS用来保留指定字数的存储区域

[LABLE]DSn

其中 n 是十进制常数(≥0),当 n=0 时,存储区域不存在,但标号 LABLE 仍然有效,即代表下一字的地址。

5)宏指令:IN、OUT、EXIT

Casl 中有进行输入、输出及结束程序等宏指令,而没有定义输入、输出符号指令,这类处理由操作系统完成。

程序中出现宏指令时,Casl 生成调用操作系统的指令串,但是,生成的指令串字数不定。

执行宏指令时,GR 的内容保持不变,而 FR 的内容不确定。

(1)输入宏指令 IN:

[LABLE]INALABLE,NLABLE

宏指令 IN 从输入装置上输入一个记录,纪录中的信息(字符)依次按字符数据的形式存放在标号为 ALABLE 开始的区域内,已输入的字符个数以二进制数形式存放在标号为 NLABLE 的字中,纪录之间的分隔符号不输入。

(2)输入宏指令 OUT:

[ LABLE]OUTALABLE,NLABLE

宏指令 OUT 将存放在标号为 ALABLE 开始的区域中的字符数据作为一个记录向输出装置输出,输出的字符个数由标号为 NLABLE 的字的内容指定。输出时,若要纪录间的分隔符号,由操作系统自动插入输出。

(3)宏指令 EXIT :

[LABLE]EXIT

宏指令 EXIT 表示程序执行的终止,控制返回操作系统。

二、汇编语言常用子程序

1、拆字与拼字:

【例1】将 GR0 中的四位 BCD 码从高到低依次存放到 GR2 所指的四个内存单元中。

 START  
 LEAGR3,4;循环计数器
L1STGR0,REG;保护其余几位 BCD 码
 ANDGR0,C000F;屏蔽高 3 位,留下最低 1 位 BCD 码
 STGR0,3,GR2;将此位 BCD 码存放到 GR2 所指第四个内存单元
 LDGR0,REG;恢复其余几位 BCD 码
 SRLGR0,4;将已处理过的此位 BCD 码移出
 LEAGR2.-1,GR2;地址指针减 1
 LEAGR3,-1,GR3;循环计数器减 1
 JNZL1;未处理完,继续
 RET  
C000FDC#000F ;十六进制常数,屏蔽屏蔽高 3 位 BCD 码用
REGDS1 ;暂存单元
 END  

 

【例2】将存放在 GR2 所指的四个内存单元中的四位 BCD 码依从高到低顺序压缩到 GR0 中 。

 START  
 LEAGR0,0;GR0 清 0
 LEAGR3,4;循环计数器
L1SLLGR0,4;将已处理过的 BCD 码移到高位
 LDGR1,0,GR2;GR1 用作临时工作寄存器
 ANDGR1,C000F;屏蔽高 12 位
 STGR1,0,GR2;对内存单元中的 BCD 码预处理
 ADDGR0,0,GR2;将已处理过的此位 BCD 码加到 GR0 低位
 LEAGR2.1,GR2;地址指针指向下一位 BCD 码
 LEAGR3,-1,GR3;循环计数器减 1
 JNZL1;未处理完,继续
 RET  
C000FDC#000F ;十六进制常数,屏蔽高 12 位二进制数
 END  

2、数字与 ASCII 码之间的相互转换:

十进制数字 0~9 的 ASCII 码是 30H~39H ,所以只要将十进制数(BCD 码)加 30H 就是对应的 ASCII 码。

十六进制数转换成 ASCII 码可分成两段, 0~9 的 ASCII 码是 30H~39H ,即加 30H ;A~F 的ASCII 码是 41H~45H ,即加 37 H。

【例1】将 GR0 中的四位 BCD 码化成 ASCII 码从高到低依次存放到字符串变量 STR 中。

 START  
 LEAGR2,3;相对于 STR 首址的地址指针
 LEAGR3,4;循环计数器
L1STGR0,REG;保护其余几位 BCD 码
 ANDGR0,C000F;屏蔽高 3 位,留下最低 1 位 BCD 码
 ADDGR0,C30;转换成 ASCII 码
 STGR0,STR,GR2;将 ASCII 码存放到 GR2 所指第四个内存单元
 LDGR0,REG;恢复其余几位 BCD 码
 SRLGR0,4;将已处理过的此位 BCD 码移出
 LEAGR2.-1,GR2;地址指针减 1
 LEAGR3,-1,GR3;循环计数器减 1
 JNZL1;未处理完,继续
 RET  
C000FDC#000F ;十六进制常数,屏蔽高 3 位 BCD 码用
C30DC#30 ;十六进制常数 30
STRDS4  
REGDS1 ;暂存单元
 END  

 

【例2】将 GR0 中的 16 位二进制数化成四位十六进制数 ASCII 码从高到低依次存放到字符串变量 STR 中。

 START  
 LEAGR2,3;相对于 STR 首址的地址指针
 LEAGR3,4;循环计数器
L1STGR0,REG;保护其余几位二进制数
 ANDGR0,C000F;屏蔽高 12 位,留下最低 4 位二进制数
 CPLGR0,C0A;< 10 否?
 JMIL2;< 10 跳过加 7 ,只加 30H
 ADDGR0,C7;≥ 10,加 30H 前先加上 7
L2 ADDGR0,C30;加上 30H
 STGR0,STR,GR2;将 ASCII 码存放到 GR2 所指第四个内存单元
 LDGR0,REG;恢复其余几位二进制数
 SRLGR0,4;将已处理过的此 4 位二进制数移出
 LEAGR2.-1,GR2;地址指针减 1
 LEAGR3,-1,GR3;循环计数器减 1
 JNZL1;未处理完,继续
 RET  
C000FDC#000F ;十六进制常数,屏蔽屏蔽高 12 位二进制数
C30DC#30 ;十六进制常数 30
C0ADC#0A ;十六进制常数 0A
C7DC7 ;常数 7
STRDS4  
REGDS1 ;暂存单元
 END  

 

【例3】将字符串 STR 中的四位十六进制数的 ASCII 码化成 16 位二进制数放到 GR0 中 。

 START  
 LEAGR0,0;GR0 清 0
 LEAGR2,0;相对于 STR 首址的地址指针
 LEAGR3,4;循环计数器
L1SLLGR0,4;将已处理过的十六进制数移到高位
 LDGR1,STR,GR2;GR1 用作临时工作寄存器
 ANDGR1,C00FF;屏蔽高 8 位
 SUBGR0,C30;减去30H
 CPLGR0,C0A;< 10 否?
 JMIL2;< 10 ,完成转换
 SUBGR0,C7;≥ 10,再减去 7
L2 STGR1,STR,GR2;将 STR 中的 ASCII 码转换成十六进制数
 ADDGR0,STR,GR2;将此位十六进制数加到 GR0 低位
 LEAGR2.1,GR2;地址指针指向下一位 ASCII 码
 LEAGR3,-1,GR3;循环计数器减 1
 JNZL1;未处理完,继续
 RET  
C00FFDC#00FF ;十六进制常数,屏蔽高 8 位用
C30DC#30 ;十六进制常数 30
C0ADC#0A ;十六进制常数 0A
C7DC7 ;常数 7
STRDS4  
 END  

3、利用加减法及移位指令做乘法:

1)左移指令可将操作数乘 2 的整数次方(2、4、8、16);右移指令可将操作数除以 2 的整数次方。

若操作数是无符号数,用逻辑移位指令;若操作数是有符号数,用算术移位指令。

【例1】将 GR0 中的二进制数乘以 8。

 SLLGR0,3

【例2】将 GR0 中的带符号二进制数除以 4。

 SRAGR0,2

2)将移位指令和加减法结合起来可完成乘数不是 2 的整数次方的乘法运算。

【例1】将 GR0 中的二进制数乘以 10。

 START 
 SLLGR0,1
 STGR0,REG
 SLLGR0,2
 ADDGR0,REG
 RET 
REGDS1
 END 

【例2】将 GR0 中的二进制数乘以 7。

 START 
 STGR0,REG
 SLLGR0,3
 SUBGR0,REG
 RET 
REGDS1
 END 

4、二进制数与十进制数的转换

1)二化十:

将二进制数转换为十进制数的一种常用算法是将被转换的二进制数依次被 10i( 对 16 位二进制数,i为 4、3、2、1、0)除,所得的商即为该十进制数位的值,其余数再被下一个 10i 除。一般用减法代替除法,即一边减 10i,一边计数器加 1,直到不够减再进行下一位 10i-1。以求得十进制数的各位数。

例如:一个相当于十进制数 34635 的二进制数,可先用 10000 去减,可减 3 次,得万位数是 3;再用 1000 去减,得千位数是 4;……

【例1】将 GR0 中的二进制数转换为十进制数的ASCII 码放入字符串 STR 中。

 START  
 LEAGR1,0;减数表及字符串指针
 LEAGR2,5;循环计数器
L1 LEAGR3,48;该十进制位的数码预置 0 的 ASCII 码
L2LEAGR3,1,GR3;数码位的 ASCII 码加 1
 SUBGR0,SNO,GR1;操作数减去 10
 JPZL2;够减,继续
 ADDGR0,SNO,GR1;不够减,操作数及数码位的 ASCII 码恢复
 LEAGR3,-1,GR3 
 STGR3,STR,GR1;转换好的该位 ASCII 码存入结果字符串
 LEAGR1,1,GR1;地址指针加 1
 LEAGR2,-1,GR2;循环计数器减 1
 JNZL1;未结束,继续下一位
 RET  
SNODC10000 
 DC1000 
 DC100 
 DC10 
 DC1 
STRDS5 ;转换结果字符串
 END  

1)十化二:

将十进制数转换为二进制数的算法基础是下面公式:

N = (Dn-1*10n-1+Dn-2*10n-2+……+D1*101+D0*100

  = ((…((Dn-1*10+Dn-2)*10+……+D1)*10+D0)*10

可以用循环程序实现此公式,*10 可用移位及加法指令完成。

【例2】将存放在字符串 STR 中的五位十进制数(<65536)的 ASCII 码转换成二进制数放到 GR0 中 。

 START  
 LEAGR0,0;转换结果寄存器清 0
 LEAGR2,5;循环计数器
 LEAGR1,0;地址指针(偏移量)
L1 SLLGR0,1;转换结果*10,先乘以 2
 STGR0,REG;暂存 2*X
 SLLGR0,2;2*X*4=8*X
 ADDGR0,REG;8*X + 2*X
 LDGR3,STR,GR1;取一位 ASCII 码
 ANDGR3,C000F;将 ASCII 码变成 BCD 码
 STGR3,REG;结果暂存
 ADDGR0,REG;将新的一位 BCD 码加到转换结果中
 LEAGR1,1,GR1;地址指针加 1
 LEAGR2,-1,GR2;循环计数器减 1
 JNZL1;未结束,继续下一位
 RET  
C000FDC#000F ;十六进制常数,屏蔽高 12 位二进制数
STRDC'35475'  
REGDS1;暂存单元
 END  

5、求累加和

【例1】将变量 NUMBER 中的 5 个二进制数累加后放入变量 SUM 中。

 START  
 LEAGR2,NUMBER;地址指针
 LEAGR3,5;循环计数器
 LEAGR0,0;累加和清 0
L1ADDGR0,0,GR2;累加
 LEAGR2,1,GR2;地址指针指向下一个二进制数
 LEAGR3,-1,GR3;计数器减 1
 JNZL1;未完,继续
 STGR0,SUM;累加结束,累加和送入 SUM 单元
 RET  
NUMBERDS5 
SUMDS1 
 END  

、试题解释

1、2001年试题三[程序说明]

 

子程序 DEHZ 用来对 HZ 编码的字串做解码处理。

HZ 编码是海外华人创造的一种将含有高位为 1 的汉字双字节字串转换成易于在网络中传输的ASCII 字符串的变换方式。编码过程中,被转换字符串中的原汉字子字符串各字节高位作清零处理,使之成为 ASCII 子字符串,并在其前后两端分别添加 ~{ 和 ~} 作为标记;而对于原 ASCII 子字符串,则将其中的 ~ 改写为 ~~,其余字符不变。

DEHZ 解码子程序则是 HZ 编码的复原过程。复原 ASCII 子字符串过程中遇有 ~~ 字符则改写为一个 ~ ,遇有 ~{ 则将其后直至 ~} 标记前的各字节高位置 1,复原为汉字子字符串,同时删除其前后标记。~的后续字符不属于以上情况均作为错误处理。

调用该子程序时, GR1 存放原始字符串首地址, GR2 存放还原后的目标字符串首地址。工作寄存器  GR3 用作处理汉字子字符串的识别标志,进入子程序时应初始化为处理 ASCII 子字符串。程序按照   CASL 语言的标准约定,字符串的每个字符只占用一个存储字的低八位。原始字符串和目标字符串均以 0 作为结束标志。

[程序]

 START 1
DEHZPUSH0,GR32
 PUSH0,GR23
 PUSH0,GR14
 LEAGR3,05
LOOP__(1)__ 6
 CPA GR0,MARK07
 JNZGOON8
 LEAGR1,1,GR19
 LDGR0,0,GR110
 CPAGR0,MARK011
 __(2)__ 12
 CPAGR0,MARK1,GR313
 JNZ ERROR14
 __(3)__ 15
 LEAGR1,1,GR116
 JMPLOOP17
ERROROUTERS1R,ERLEN18
 JMPEXIT19
GOON__(4)__ 20
 STGR0,0,GR221
 LEAGR2,1,GR222
 LEAGR1,1,GR123
 CPAGR0,VO24
 __(5)__ 25
EXITP0PGR126
 P0PGR227
 P0PGR328
 RET 29
V1DC130
V0 DCO31
 DC#008032
MARK0DC '~ '33
MARK1DC'{ }'34
ERSTRDC'ERROR!'35
ERLENDC636
 END 37

[解]

寄存器作用:

GR1:源字符串地址指针,调用该子程序时,存放源字符串首地址。

GR2:目标字符串地址指针,调用该子程序时,存放目标字符串首地址。

GR3:用作处理汉字子字符串的识别标志。0 表示 ASCII 码(初始值),1 表示汉字。

GR0:工作寄存器,存放待处理的字符。(从第 7 行 "CPA  GR0,MARK0" 看出)

分析:

1)从第 7 行 " CPA  GR0,MARK0" 看出,GR0 中存放待处理的字符。所以第 6 行(__(1)__)必定是一条取数指令:"LD  GR0,0,GR1" ,即把源字符串地址指针所指的字符取到 GR0 中。

2)从第 7 行及第 8 行可知,第 9 行到第 17 行是处理碰到“~”的情况,即判断后一字符是否是“~”、“{ ”及“}”。若都不是,则出错。

3)从第 11 行可知,要判断是否连续两个“~”情况,而后面是继续比较,所以第 12 行(__(2)__)应该是一条“JZE”指令,而且是转移到 GOON ,即把“~”存放到目标字符串中。

4)第 13 行“CPA GR0,MARK1,GR3”应该是比较“{ ”及“}”:在中文状态比较“}”(结束),在西文状态比较“{ ”(开始)。所以这里用的是变址寻址,即由 GR3 的值是 0 或 1,决定是比较“{ ”还是“}”。

5)第 12 行(__(3)__)应该是改变汉字子字符串的识别标志 GR3 的指令,即原来是 0 的变成 1,原来是 1 的变成 0,异或指令可以达到此目的。将 GR3 与常数 1 相异或,因 Casl 没有没有立即数运算指令,只能和常数 V1 异或:EOR GR3,V1。

6)第 20 行(__(4)__)是 GR0 中存放的字符送到目标字符串前的处理工作:若是西文状态( GR3 的值是 0 ),保持原样;若是中文状态( GR3 的值是 1 ),字节最高位置 1,复原为汉字子字符串,将GR0 的内容与十六进制数 0080 相或,即能达到目的。所以这条指令应是:OR GR0,V0,GR3 。

7)第 24 行将 GR0 与 0 比较,是判断字符串结束标志 0 。若非 0(未结束),继续处理。故第 25 行(__(5)__)应是一条条件转移指令:JNZ LOOP 。

2、2000年试题四[程序说明]

 

(1)本子程序根据每位职工的基本工资(非负值)和他完成产品的超额数或不足数计算该职工的应发工资。

(2)主程序调用时,GR1中给出子程序所需参数的起始地址,参数的存放次序如下表:

GR1

a1
 b1
 c1
 a2
 b2
 c2
 
 an
 bn
 cn
 -1(结束标志)

 其中 ai 为职工 i 的基本工资;bi 为职工 i 的完成产品的超额数或不足数;ci为职工 i 的应发工资数(i = 1、2、…、n)。

bi以原码形式存放(大于零为超额,小于零为不足),基本工资与计算所得的应发工资以补码形式存放。

(3)应发工资的计算规则为:

●恰好完成定额数(此时bi = 0),应发工资即为基本工资。

●每超额 4 件,在基本工资基础上增加 10 元(不到 4 件,以 4 计算,例如超额数为 10 时,增加 30 元)。

●每不足 4 件,在基本工资基础上减 5 元(不到 4 件,以 4 计算,例如不足数为 5 时,减 10元)。

[程序]

 START 1

BEG 

PUSH0,GR12
 PUSH0,GR23
 PUSH0,GR34
L1 __(1)__ 5
 LEA GR0,0,GR26
 JMIFINISH7
 LDGR3,1,GR18
 LEA GR2,0,GR39
 ANDGR2,C7FFF10
 JZEL311
 SRLGR3,1512
 LEAGR2,-1,GR213
L2__(2)__ 14
 LEAGR2,-4,GR215
 JPZL216
L3__(3)__ 17
 __(4)__ 18
 __(5)__ 19
FINISHPOPGR320
 POPGR221
 POPGR122
 RET 23
C7FFFDC#7FFF24
BONUSDC1025
 DC-526
 END 27

[解]

寄存器作用:

GR1:地址指针

GR2:临时工作单元。先放 ai,后放 bi(绝对值)。

GR3:bi符号

GR0:ci---应发工资

分析:

1)从第 6 行 "LEA GR0,0,GR2" 及第 7 行 "JMI FINISH" 可知 GR0 开始时应是 ai,GR2 也应是ai,(从 LEA 指令功能分析)。所以第 5 行(1)应该是取数指令:

LD GR2,0,GR1

2)从第 8 行 "LD GR3,1,GR1" 及第 9 行 "LEA GR2,0,GR3" 可知 GR2 及 GR3 放的都是 bi(超额数或不足数),而从第 10 行 "AND GR2,C7FFF"(注意:C7FFF是 16 进制常量的标号(第 24 行)),可知 GR2 存放其绝对值。而且在该值为 0 时直接结束该职工处理(第 11 行 "JZE L3")。

3)从第 12 行 "SRL GR3,15" 可知 GR3 存放 bi 的符号(超额为 0,不足为 1)

4)从第 25、26 两行可知 BONUS 是每个超额或不足单位(4 件)的增加或扣除金额。从而得出最关键的第 14 行2应为 "ADD GR0,BONUS,GR3"。第 15、16 行指出这一加或减(GR3=1时,源操作数为负)是一循环过程,一直到 GR2<0。为防止 bi 为 4 的整数倍时多加减一次,在第 13 行中先将 GR 减 1。

5)第17、18、19行(L3)依次是该职工的应发工资回送、修改地址指针(指向下一职工)和跳到处理程序开始(L1):

ST GR0,2,GR1

LEA GR1,3,GR1

JMP L1

3、1999年试题四〖程序4.1〗[程序4.1说明]

 

本子程序是对 15 位二进位串,求它的奇校验位,生成 16 位二进制位串,使 16 位二进制位串有奇数个 1。

进入此子程序时,15 位二进制位串在 GR1 的第 1 位至第 15 位,并假定 GR1 的第 0 位是 0,求得的奇校验位装配在 GR1 的第 0 位上。


[程序4.1]

 START 1
BEGPUSH0,GR22
 PUSH0,GR33
 LEAGR3,14
 __ (1) __ 5
L1SLLGR2,16
 __ (2) __ 7
 LEAGR3,1,GR38
L2JZEL39
 JMPL110
L3__ (3) __ 11
 STGR3,WORK12
 ADDGR1,WORK13
 POPGR314
 POPGR215
 RET 16
WORKDS117
 END 18

[分析]

1)从说明中已知,被转换的二进位串(一个字)放在 GR1 中。

2)第 6 行 "SLL GR2,1" 这条指令是处理奇偶校验用的,因此 GR2 也应该是工作单元,初始值为被处理数,故第 5 行(1)应该是 "LEA GR2,0,GR1"。

3)从第 4、5 行看,GR3 是一个计数器(统计值为 1 的位的个数),初始值为 1,即当 GR2 一个 1也没有时,其值为 1(奇校验)。

4)第 6 行 "SLL GR2,1" 将被处理数左移一位,需要判断最高位是否为 1,若是,计数器加 1,否则跳过这条指令。因最高位也是符号位,所以可用 "JPZ L2"(2)。

5)第 9 行(L2)"JZE L3"是移位结束条件,即移到结果为 0 时结束。

6)第 11、12、13 行,是在计数器值为奇数(即实际 1 的个数为偶数)时把被处理字 GR1 最高位变成 1。而计数器 GR3 为奇数即其最低位为 1,因此需把 GR3 的最低位变成最高位,所以第 11 行(3)应该是:SLL GR3,15


4、1999年试题四〖程序4.2〗

[程序4.2说明]

 

(GR1)+0

A

+1

n

+2

B

[程序4.2]

 START 
SUMLDGR2,0,GR1
 LDGR3,1,GR1
 LEAGR0,0
L5ADDGR0,0,GR2
 LEAGR2,1,GR2
 _ (4) _ 
 JNZL5
L3__(5)    
 STGR0,0,GR3
 RET 
 END 

[分析]

1)GR1 为参数表起始地址

2)GR2 为数组地址指针,起始值为A

3)GR3 为计数器,初始值为数组长度 n。

4)GR0 为累加和工作单元

5)(  4  )应该是计数器减 1:LEA GR3,-1,GR3

6)(  5  )应把结果单元地址 B 赋给 GR3:LD GR3,2,GR1
本程序是统计字符串中数字字符"0"至"9"的出现次数。

4、1998年试题四

[程序说明]

 

字符串中的每个字符是用ASCII码存贮。一个存贮单元存放两个字符,每个字符占8位二进位。

程序中,被统计的字符串从左至右存放在STR开始的连续单元中,并假定其长度不超过200,字符串以'·'符作为结束。NCH开始的10个单元存放统计结果。 20

 STARTMIN1
MINLEAGR2,92
 LEAGR0,03
L1_ (1) _ 4
 LEAGR2,-1,GR25
 JPZL16
 LEAGR4,07
 LEAGR1,08
L2LDGR2,STR,GR19
 EORGR4,C110
 JNZRL11
  _ (2) _  12
RLSRGR2,813
 LEAGR3,0,GR214
 SUBGR3,C915
 JNZL416
L3LEAGR3,0,GR217
 SUBGR3,CO18
 JM1L519
 LEAGR2,1
 
 
L4LEAGR4,0,GR423
 
 
 
L5SUBGR2,C27
 
 
C1DC130
CDC'·'31
C0DC'0'32
C9DC'9'33
STRDS20034
NCHDS1035
 
END 36EXIT 29JNZL428JMPL226_(5)_ 25JNZL224_(4)_ 22_(3)_ 21

[解]

1)第2~8行(L2以前)是初始化程序,其中第2~6行是把计数器存放单元NCH开始的十个单元清零。地址指针是GR2(递减),故((1))为:ST GR0,NCH,GR2

2)从第 8、9 行看出 GR1 是地址指针(相对于 STR)。GR2是工作单元(要处理的字符)

3)因一个字放两个字符,故GR3用作高低字节标志。起始值为0,先处理高字节,第10行指令"EOR GR4,C1"一方面判断是否第一次(结果非0),并将GR4置1。

第一次处理高字节,用逻辑右移指令将高8位内容移到低8位(高8位置0)。

第二次处理低字节,用先逻辑左移再逻辑右移指令将高8位内容置0,故(2)为:

SLL GR2,8

4)在处理过程又用 GR3 作临时工作单元,即把GR2内容送给GR3再处理。处理时先判是否>"9"(不计数)。然后减以 "0" ,使 GR3 变成 0~9。

5)计数处理是在第 21、22、23 三行中完成。使 NCH 开始的 10 个单元中与 GR3 对应的那个单元加1。因加法指令的目的操作数只能是寄存器,所以先给 GR2 送 1(第 21 行),再将 NCH 对应单元内容加到GR2 中,再将 GR2 内容送回 NCH 对应单元(采用 GR3 变址寻址)。故34为:"ADD GR2,NCH,GR3"及"ST GR2,NCH,GR3"。

6)在一个字的第二次处理后(用第 24、25 行判断),要修改字符串的地址指针 GR1(加1)。故    (5为:"LEA GR1,1,GR1"。 本子程序将一个非负二进整数翻译成五位十进整数字符。

5、1997年试题四[程序说明]

 

进入子程序时,在 GR0 中给出被翻译的非负二进整数,在 GR2 中给出存放五位十进整数数字字符的起始地址。

十进制数字字符用 ASCII 码表示。当结果小于五位时,左边用空白符替换;当二进整数为零时,在(GR2)+4 中存放 0 的 ASCII 码。

数字字符 0 至 9 的 ASCII 码是 48 至 57,空白符的 ASCII 码是 32。
[程序] 这是一个典型的二化十汇编语言题例,其算法是将被转换的二进制数依次被 10i(i为 4、3、2、1、0)除,所得的商即为该十进制数位的值,其余数再被下一个 10i 除。一般用减法代替除法,即一边减10i,一边计数器加 1,直到不够减再进行下一位 10i-1

 START 1
 LEAGR1,02
 LEAGR3,323
L1____(1)____ 4
 JPZL25
 STGR3,0,GR26
 LEAGR2,1,GR27
 LEAGR1,1,GR18
 LEAGR4,-4,GR19
 JNZL110
L2___(2)___ 11
L3___(3)___ 12
 JMIL413
 SUBGR0,SNO,GR114
 LEAGR3,1,GR315
 ___(4)___ 16
L4STGR3,0,GR217
 LEAGR2,1,GR218
 LEAGR1,1,GR119
 ___(5)___ 20
 JNZL221
 RET 22
SNODC1000023
 DC100024
 DC10025
 DC1026
 DC127
 END 28

[解]

 

1)寄存器分配:GR0:被转换数;GR2:存放五位十进整数数字字符的起始地址。

GR1:数位计数器(兼作SNO内存数组的下标)

GR3:在初始化时放空格的ASCII码(48),在转换时作某一位的数码计数器(初始值为 0 的 ASCII 码 48)

2)SNO 内存变量依次存放 104、103、102、101、100

3)第 2~9 行为初始化程序,在 GR0<10i 时,对应的十进整数数字字符单元放空格(当结果小于五位时,左边用空白符替换),此过程一直进行到 GR0≥10i 或 GR1= 4(个位)。因此____(1)____应为 "CPL GR0,SNO,GR1"。

4)L2 开始进行除法(减法)。GR3 作某一位的数码计数器。从 L4 可看出,该计数值直接放到结果单元 [GR2],而按题意所放的是 ASCII 码,所以其初始值应为 0 的 ASCII 码 48。因此___(2)___为:

LEA GR3,48

5)根据算法,GR0≥10i 才做减法,故____(3)____还是 "CPL GR0,SNO,GR1"。

6) ___(4)___是 "JMP L3",即继续做这一位的减法,直至 GR0<10i

7)L4 后 3 行是某一位结束处理:结果送到地址指针 GR2 所指的存放单元;地址指针 GR2 加 1;SNO 内存数组的下标 GR1 加 1。

8)___(5)___应该是判断除法是否做到个位结束。即下标 GR1=5,因此这一句为:

LEA GR3,-5,GR1
子程序 OFFSET 用二分法,查找无符号整数 M 在一个长度为 N 的有序(升序)无符号整数列表NTABLE 中的位置。程序中标号为 LOW 和 UP 的两个存储字分别用作存放查找空间的上下限。

6、1996年试题四

[程序说明]

 

进入子程序时,在 GR1 中中给出存放子程序所需参数的起始地址。参数的存放次序如下图:

从子程序返回时,GR0 中存放查找结果,即 M 在此有序表中的位置序数,如表中找不到 M,则 GR0 中返回 0,其它寄存器的内容保持不变。
[程序]
[解]

 START  1
OFFSETPUSH0,GR2 2
 PUSH0,GR3 3
 LDGR0,0,GR1 4
 LEAGR2,0 5
 STGR2,LOW 6
 ___(1)___  7
 ___(2)___  8
 STGR2,UP 9
LOOPADDGR2,LOW 10
 SRLGR2,1 11
 LEAGR3,0,GR2 12
 ___(3)___  13
 ___(4)___  14
 JZEFOUND 15
 JPZINCLOW 16
 LEAGR2,-1,GR2;M<NTABLE(K)17
 STGR2,UP 18
 JMPCMPLU 19
INCLOWLEAGR2,1,GR2;M> NTABLE(K)20
 STGR2,LOW;K+1→LOW21
 ___(5)___  22
CMPLUCPLGR2,LOW 23
 ___(6)___  24
 ___(7)___  25
FOUNDLEAGR0,1,GR2 26
 POPGR3 27
 POPGR2 28
 RET  29
LOWDS1 30
UPDS1 31
 END  32

 

二分法查找的基本思想是对任意一段查找空间 [LOW,UP](有序)中的的表元,试探位置 K=(LOW+UP)/2上的成分 NTABLE(K) 与 M 进行比较,其可能结果有三种:

1)NTABLE(K)= M,找到,结束查找。

2)NTABLE(K)< M,下一查找空间为[K+1,UP]。

3)NTABLE(K)> M,下一查找空间为[LOW,K-1]。

初始查找空间为 LOW=0,UP=N-1。

程序中空格___(1)___和___(2)___前面的两条指令是将查找空间的上限 LOW 中 0,二在它之后的指令是将 GR2 中的值存于查找空间的下限 UP 中。因此这两个空格是把下限初值 N-1 送给 GR2。由于进入子程序时,N 存放在(GR1)+1 中,所以这两条指令为:

LD GR2,1,GR1

LEA GR2,-1,GR2

从标号 LOOP 开始的循环是求试探位置 K,根据 NTABLE(K) 和 M 比较结果,分别处理三种不同的情况,直至查到或查找空间为 0 。

考察空格___(3)___和___(4)___前面的指令,可得 K 在 GR2 和 GR3 中,在执行___(3)___和___(4)___两条指令后,有三种转向,因此这两条指令是将 GR0 中的 M 与 NTABLE(K)比较。而从程序说明中以知,NTABLE(0) 地址在 GR1+2。故 NTABLE(K) 的地址应为 GR2 或 GR3 与(GR1+2)相加(绝对地址)。但GR2 在后面要作相对地址  K用,所以只能是 GR3 与(GR1+2)相加。所以空格___(3)___和___(4)___为:

ADD GR3,2,GR1

CPL GR0,0,GR3

执行上述两条指令后,若不相等则要调整查找空间,在继续查找前,先应判断查找空间是否为 0,在程序中是用标号为 CMPLU 的指令实现,显然 GR2 内应是查找空间的下限 UP。故___(5)___的答案为:

LD GR2,UP

当查找空间不为0时(UP>LOW),应继续查找,所以___(6)___的解答为:

JPZ LOOP

子程序返回时,GR0 中存放查找结果,在表中找到M时,GR0 中存放M在表中的位置序数,在程序中用 "FOUND LEA GR0,1,GR2" 实现(这里 GR2 中是试探位置,与位置序数差 1 )。

若表中找不到 M,GR0 中要放 0,所以___(7)___处应填 "LD GR2,-1"。

 

老顽童撰写于2001年7月,2002年7月修改增补 

(GR1)+0 

M

1

N

2

NTABLE的首址

子程序 SUM 是将存贮字 A 起的 n(n>0) 个字求和,并将结果存于存贮字 B 中。
调用该子程序时,主程序在 GR1 中给出存放子程序所需参数的起始地址。参数的存放次序如下图:

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CASL引入国内以后作为中国计算机软件专业技术资格和水平考试高级程序员级考试内容之一。使用虚拟的计算机目的为的是一个公平的考试环境,毕竟如果让每天和MC680X0打交道的朋友去和写PC驱动的朋友一起考i80X86汇编显然是不公平的。 CASL达到这一目的的同时却带来了一个麻烦:CASL程序无法在常见的PC或者其他任何计算机上运行。 我们有三条常见选择: 1)汇编器,将Casl汇编程序汇编成诸如80X86指令的程序,在PC上运行 2)解释器,解释执行每一条指令,有点像解释型高级语言,但是来的简单一些 3)忘记CASL,忘记高程考试 ;;;;-) 在选择了第二种方案以后我们开始了这个软件...... Nasl的设计主要目标便是简单易用,事实上在我能找到的所有CASL解释器中没有一个能很快上手运行起来的,当然这不包括Nasl本身。由于Comet是一个虚拟计算机,诸如复旦大学计算机科学系所设计的CASL汇编器的设计只能给使用者带来不必要的麻烦。鉴于它只能在Pure DOS下运行,Nasl诞生了,编写一个开放的人人可以得到的方便的CASL解释器是编写Nasl的初衷之一。 Nasl能对输入的CASL汇编程序解释运行,以此可以观察各个寄存器以及内存的变化情况,使得您可以熟悉CASL汇编并对汇编语言程序设计的思想有所了解,帮助通过高程考试。Nasl支持CASL汇编文件的编辑,但是请不要将它视作一个";;;开发环境";;;,CASL和Nasl都不值得您去那么做。 最后祝所有努力学习的朋友好运!
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值