查看全部128種考試
軟件水平考試
 考試動(dòng)態(tài) 報(bào)考指南 歷年真題 模擬試題 復(fù)習(xí)資料 心得技巧 專(zhuān)業(yè)英語(yǔ) 技術(shù)文章 軟考論壇 考試用書(shū)
 程序員 軟件設(shè)計(jì)師 網(wǎng)絡(luò)管理員 網(wǎng)絡(luò)工程師 系統(tǒng)分析師 數(shù)據(jù)庫(kù)系統(tǒng)工程師
1
2
3
4
5
6
7
8
9
10
Exam8.com  
【字體: Casl匯編語(yǔ)言輔導(dǎo)(上)
Casl匯編語(yǔ)言輔導(dǎo)(上)
spks.exam8.com 來(lái)源:考試吧(Exam8.com) 更新:2004-12-27 13:32:00 軟件水平考試 考試論壇

一、Casl匯編語(yǔ)言語(yǔ)法介紹

學(xué)習(xí)一個(gè)匯編語(yǔ)言需要掌握3個(gè)要點(diǎn):CPU 的可編程寄存器結(jié)構(gòu)、尋址方式及指令系統(tǒng)、偽指令。

1、COMETCPU 的可編程寄存器

COMETCPU 字長(zhǎng) 16 位,采用從左到右的編號(hào)。bit0 在最左邊(最高位),bit15 在最右邊(最低位)

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

1)16 位通用寄存器五個(gè):

GR0、GR1、GR2、GR3、GR4

通用功能:各種算術(shù)邏輯運(yùn)算

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

GR4 兼作堆棧指針(SP)

2)指令計(jì)數(shù)器 PC 一個(gè)(16位)

存放正在執(zhí)行的那條指令的第 1 個(gè)字的地址(一條指令占二個(gè)字),指令結(jié)束時(shí),PC 中存放下一條指令的地址(一般為原指令地址 +2 )。

3)狀態(tài)寄存器 FR 一個(gè)(二位)

運(yùn)算結(jié)果 FR0 FR1
大于  0 0
等于 0 1
小于 1 0

 

可以把 FR0 看成 SF(符號(hào)位),F(xiàn)R1 看成 ZF(零位位)

除了算術(shù)邏輯運(yùn)算指令(包括移位指令)外,LEA 指令也會(huì)影響 FR

2、符號(hào)指令寫(xiě)法與尋址方式

OP GR,ADR[,XR]

其中 OP 為操作碼;GR 為五個(gè)通用寄存器 GR0~GR4 之一;ADR 為一個(gè) 16 位的地址碼;XR 為四個(gè)變址寄存器 GR1~GR4 之一,[ ]表示可以省略。

1)直接尋址:當(dāng) [,XR] 省略時(shí),為直接尋址。

2)變址尋址:有效地址 E = ADR +(XR),當(dāng) ADR = 0 時(shí),為寄存器間接尋址。

3)立即數(shù)尋址:Casl 沒(méi)有立即數(shù)尋址。但在 LEA 指令中,當(dāng) [,XR] 省略時(shí),可作立即數(shù)傳送。沒(méi)有立即數(shù)運(yùn)算指令。

4)寄存器尋址:Casl 也沒(méi)有寄存器尋址(對(duì)源操作數(shù))。但 LEA 指令當(dāng) ADR = 0 時(shí),可作寄存器尋址(只用于數(shù)據(jù)傳送)。

3、Casl指令系統(tǒng)

1)取數(shù)指令 LD:內(nèi)存→寄存器

LD GR,ADR[,XR]

2)存數(shù)指令 ST:寄存器→內(nèi)存

ST GR,ADR[,XR]

3)加法 ADD、減法 SUB、邏輯與 AND、邏輯或OR、邏輯異或 EOR指令:

ADD
SUB
AND GR,ADR[,XR]
OR
EOR

內(nèi)存 OP 寄存器→寄存器

4)算術(shù)比較 CPA:

兩個(gè)帶符號(hào)數(shù)比較,結(jié)果不回送,只影響標(biāo)志位。

CPA GR,ADR[,XR]

5)邏輯比較 CPL:兩個(gè)無(wú)符號(hào)數(shù)比較,結(jié)果不回送,只影響標(biāo)志位。

CPL GR,ADR[,XR]

6)算術(shù)左移 SLA、算術(shù)右移 SRA:把操作數(shù)看成帶符號(hào)數(shù)。對(duì)寄存器操作數(shù)進(jìn)行移位(GR 的第 0 位——符號(hào)位不變。右移時(shí)空出的其余位補(bǔ)與第 0 位相同的 1 或 0 ;左移時(shí)空出的位補(bǔ) 0 ),位數(shù)由有效地址 E 決定。

SLA GR,ADR[,XR]
SRA

7)邏輯左移 SLL、邏輯右移 SRL:把操作數(shù)看成無(wú)符號(hào)數(shù)。對(duì)寄存器操作數(shù)進(jìn)行移位(不管左右移,GR 空出的位補(bǔ) 0 ),位數(shù)由有效地址 E 決定。

SLL GR,ADR[,XR]
SRL

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

LEA GR,ADR[,XR]

該指令有幾個(gè)特殊用途:

【例1】LEA GR0,41H 把立即數(shù) 41H 送給 GR0

【例2】LEA GR0,0,GR1 把寄存器 GR1 的內(nèi)容送給 GR0

【例3】LEA GR1,1,GR1 寄存器 GR1 的內(nèi)容加 1(相當(dāng)于 8086 匯編中的 INC 指令)

【例4】LEA GR1,-1,GR1 寄存器 GR1 的內(nèi)容減 1(相當(dāng) 8086 匯編中的 DEC 指令)

【例5】LEA GR1,N,GR1 寄存器 GR1 的內(nèi)容加 N(相當(dāng)于立即數(shù)加法)

【例6】LEA GR1,-N,GR1 寄存器 GR1 的內(nèi)容減 N(相當(dāng)于立即數(shù)減法)

9)無(wú)條件轉(zhuǎn)移指令JMP與條件轉(zhuǎn)移指令JPZ(不小于轉(zhuǎn))、JMI(小于轉(zhuǎn))、JNZ(不等于轉(zhuǎn))、JZE(等于轉(zhuǎn))

JMP
JPZ
JMI ADR[,XR]
JNZ
JZE

●當(dāng)?shù)刂反a中缺 [XR] 時(shí),所有轉(zhuǎn)移指令為直接轉(zhuǎn)移( ADR 即為轉(zhuǎn)移地址)

     當(dāng)?shù)刂反a中有 [XR] 時(shí),所有轉(zhuǎn)移指令為間接相對(duì)接轉(zhuǎn)移

●JPZ 與 JMI 根據(jù)符號(hào)位 FR0 作為判斷條件

     JNZ 與 JZE 根據(jù)零位位 FR1 作為判斷條件

10)進(jìn)棧 PUSH 與出棧 POP:

(1)進(jìn)棧指令 PUSH:

PUSH ADR[,XR]

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

(2)出棧指令 POP:

POP GR

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

注意:出棧指令的目的寄存器是 GR0~GR4,而進(jìn)棧指令的源操作數(shù)不包括 GR0。 

11)子程序調(diào)用CALL與返回 RET指令

(1)子程序調(diào)用指令 CALL:

CALL ADR[,XR]

 (SP)-1→SP,(PC)+2→(SP),E→(PC)

(2)子程序返回指令 RET:

RET

((SP))→PC,(SP)+1→SP

4、偽指令

1)START:程序開(kāi)始

2)END:程序結(jié)尾

3)常量定義指令 DC

此偽指令與其它匯編語(yǔ)言中的 DB 指令似。利用 DC 指令可定義:

(1)定義十進(jìn)制常數(shù):

十進(jìn)制常數(shù)名 DC n

其中 -32768 < n ≤65535

(2)定義字符串常數(shù):

字符串常數(shù)名 DC '字符串'

(3)定義十六進(jìn)制常數(shù):

十六進(jìn)制常數(shù)名 DC #h

其中 0000 ≤ h ≤FFFF

(4)定義地址:

地址常數(shù) DC LABLE

其中 LABLE 是程序中的地址標(biāo)號(hào)

因?yàn)?Casl 沒(méi)有立即數(shù)運(yùn)算指令,所以需要與立即數(shù)進(jìn)行算術(shù)邏輯運(yùn)算時(shí),都要將立即數(shù)定義為內(nèi)存常數(shù)進(jìn)行運(yùn)算。

4)變量定義指令 DS用來(lái)保留指定字?jǐn)?shù)的存儲(chǔ)區(qū)域

[LABLE] DS n

其中 n 是十進(jìn)制常數(shù)(≥0),當(dāng) n=0 時(shí),存儲(chǔ)區(qū)域不存在,但標(biāo)號(hào) LABLE 仍然有效,即代表下一字的地址。

5)宏指令:IN、OUT、EXIT

Casl 中有進(jìn)行輸入、輸出及結(jié)束程序等宏指令,而沒(méi)有定義輸入、輸出符號(hào)指令,這類(lèi)處理由操作系統(tǒng)完成。

程序中出現(xiàn)宏指令時(shí),Casl 生成調(diào)用操作系統(tǒng)的指令串,但是,生成的指令串字?jǐn)?shù)不定。

執(zhí)行宏指令時(shí),GR 的內(nèi)容保持不變,而 FR 的內(nèi)容不確定。

(1)輸入宏指令 IN:

[LABLE] IN ALABLE,NLABLE

宏指令 IN 從輸入裝置上輸入一個(gè)記錄,紀(jì)錄中的信息(字符)依次按字符數(shù)據(jù)的形式存放在標(biāo)號(hào)為 ALABLE 開(kāi)始的區(qū)域內(nèi),已輸入的字符個(gè)數(shù)以二進(jìn)制數(shù)形式存放在標(biāo)號(hào)為 NLABLE 的字中,紀(jì)錄之間的分隔符號(hào)不輸入。

(2)輸出宏指令 OUT:

[ LABLE] OUT ALABLE,NLABLE

宏指令 OUT 將存放在標(biāo)號(hào)為 ALABLE 開(kāi)始的區(qū)域中的字符數(shù)據(jù)作為一個(gè)記錄向輸出裝置輸出,輸出的字符個(gè)數(shù)由標(biāo)號(hào)為 NLABLE 的字的內(nèi)容指定。輸出時(shí),若要紀(jì)錄間的分隔符號(hào),由操作系統(tǒng)自動(dòng)插入輸出。

(3)宏指令 EXIT :

[LABLE] EXIT

宏指令 EXIT 表示程序執(zhí)行的終止,控制返回操作系統(tǒng)。

二、基本程序結(jié)構(gòu)

1、順序程序(略)

2、分枝程序

1)簡(jiǎn)單分支程序

將比較指令(或其它能使標(biāo)志位發(fā)生變化的指令)和條件轉(zhuǎn)移指令結(jié)合,可實(shí)現(xiàn)分支程序。簡(jiǎn)單分支程序有兩種形式:

在匯編語(yǔ)言中,采用圖a的結(jié)構(gòu)容易出錯(cuò),例如把GB0中的十六進(jìn)制數(shù)轉(zhuǎn)換成 ASCII 碼可分成兩段, 0~9 的 ASCII 碼是 30H~39H ,即加 30H ;A~F 的ASCII 碼是 41H~45H ,即加 37 H。兩種結(jié)構(gòu)的程序如下:

圖a結(jié)構(gòu)

圖b結(jié)構(gòu)

CPL GR0,C10 CPL GR0,C10
JMI L1 JMI L1
ADD GR0,C37 ADD GR0,C7
JMP L2 L1 ADD GR0,C30
L1 ADD GR0,C30  …
L2 C10 DC 10
C10 DC 10 C7 DC 7
C37 DC #37 C30 DC #30
C30 DC #30

若采用圖a的結(jié)構(gòu),很容易把JMP L2漏掉,變成A~F 的ASCII 碼加了67H。

2)多岔分支程序

可以用多條比較指令和條件轉(zhuǎn)移指令實(shí)現(xiàn)多岔分支。

但用散轉(zhuǎn)表實(shí)現(xiàn)多岔分支則程序更為簡(jiǎn)練,其思路是在散轉(zhuǎn)表中存放各個(gè)分支程序的入口地址,用查表方法將入口地址放入變址寄存器,然后用JMP指令或CALL指令的間接尋址方式使程序轉(zhuǎn)到此入口。

【例1】根據(jù)鍵盤(pán)輸入命令轉(zhuǎn)入各命令處理程序

SB START
AGAIN IN

ALABLE,NLABLE

;輸入一個(gè)字符串
LD GR1,NLABLE ;字符串長(zhǎng)度
LEA GR1,0,GR1
JZE AGAIN ;若字符串長(zhǎng)度 =0,重輸
LD GR1,ALABLE ;將第一個(gè)字符放到GR1中
LEA GR1,-65,GR1 ;減去"A"的ASCII碼
JMI AGAIN ;若該字符<"A",重輸
CPA GR1,C4
JPZ AGAIN ;若該字符>"D",重輸
LD GR2,ENTRY,GR1 ;將散轉(zhuǎn)表中的一項(xiàng)地址放入GR2
CALL  0,GR2 ;轉(zhuǎn)入地址所指子程序
JMP AGAIN
ALABLE DS 5 ;輸入字符串緩沖區(qū)
NLABLE DS 1 ;輸入字符串長(zhǎng)度
C4 DC 4 ;常數(shù) 5
ENTRY DC ASUBR ;子程序A 入口地址
DC BSUBR ;子程序B 入口地址
DC CSUBR ;子程序C 入口地址
DC DSUBR ;子程序D 入口地址
END

在散轉(zhuǎn)表中也可存放轉(zhuǎn)移到各個(gè)分支程序入口的轉(zhuǎn)移指令,然后用變址尋址方式的JMP指令或CALL指令使程序轉(zhuǎn)到此入口。
【例2】

SB START
AGAIN IN

ALABLE,NLABLE

;輸入一個(gè)字符串
LD GR1,NLABLE ;字符串長(zhǎng)度
LEA GR1,0,GR1
JZE AGAIN ;若字符串長(zhǎng)度 =0,重輸
LD GR1,ALABLE ;將第一個(gè)字符放到GR1中
LEA GR1,-65,GR1 ;減去"A"的ASCII碼
JMI AGAIN ;若該字符<"A",重輸
CPA GR1,C4
JPZ AGAIN ;若該字符>"D",重輸
SLL GR1,1 ;散轉(zhuǎn)表每項(xiàng)占2 字
JMP ENTRY,GR1
ALABLE DS 5
NLABLE DS 1
C4 DC 4
ENTRY JMP ASUBR
JMP BSUBR
JMP CSUBR
JMP DSUBR
END

3、循環(huán)程序

循環(huán)程序也是用轉(zhuǎn)移指令實(shí)現(xiàn),循環(huán)的退出一般用循環(huán)計(jì)數(shù)器實(shí)現(xiàn),也可用其它條件來(lái)控制退出。

1)用循環(huán)計(jì)數(shù)器控制

【例1】將SD處的100個(gè)數(shù)搬到TD處(搬家程序)

SB START
LEA GR1,100 ;循環(huán)計(jì)數(shù)器
LEA GR2,0 ;偏移地址指針
LOOP LD GR0,SD,GR2 ;源操作數(shù)→GR0
ST GR0,TD,GR2 ;GR0→目的操作數(shù)
LEA GR2,1,GR2 ;修正偏移地址指針
LEA GR1,-1,GR1 ;搬完否?
JNZ LOOP
EXIT
SD DS 100
TD DS 100
END

當(dāng)源操作數(shù)和目的操作數(shù)有重迭時(shí),若源操作數(shù)在目的操作數(shù)的前面,則必須采用從下往上的搬法,即先搬最后一個(gè),再一個(gè)一個(gè)往前搬。
【例2】將 SD 處的 100 個(gè)數(shù)搬到 TD 處(有重迭)

SB START
LEA GR1,100 ;循環(huán)計(jì)數(shù)器
LEA GR2,99 ;偏移地址指針
LOOP LD GR0,SD,GR2 ;源操作數(shù)→GR0
ST GR0,TD,GR2 ;GR0→目的操作數(shù)
LEA GR2,-1,GR2 ;修正偏移地址指針
LEA GR1,-1,GR1 ;搬完否?
JNZ LOOP
EXIT
SD DS 1
TD DS 100
END

2)循環(huán)次數(shù)可能為 0 的循環(huán)程序
前面的例子無(wú)法實(shí)現(xiàn)循環(huán)次數(shù)可能為0的循環(huán)程序(如用連加實(shí)現(xiàn)兩個(gè)數(shù)相乘的算法),因?yàn)檠h(huán)計(jì)數(shù)器預(yù)置為0時(shí),實(shí)際的循環(huán)次數(shù)是65536。

【例2】將 A 和 B 兩個(gè)整數(shù)相乘和放到 C 中(不考慮溢出)

SB START
LD GR1,B ;乘數(shù)作循環(huán)計(jì)數(shù)器
LEA GR0,0 ;乘積清0
LOOP LEA GR1,0,GR1
JZE L1 ;若乘數(shù)為0,退出循環(huán)
ADD GR0,A ;被乘數(shù)加到乘積中
LEA GR1,-1,GR1 ;加完否?
JMP LOOP
L1 ST GR0,C  ;乘積→C
EXIT
A DS 1
B DS 1
C DS 1
END

3)循環(huán)次數(shù)不定的循環(huán)程序
不用循環(huán)計(jì)數(shù)器,而用其它方法控制循環(huán)的退出。
【例4】測(cè)試字符串STR的長(zhǎng)度,并將它保存到L中

SB START
LEA GR1,0 ;字符串長(zhǎng)度計(jì)數(shù)器(兼地址指針)清0
LOOP LD GR0,STR,GR1 ;取一字符
CPL GR0,F(xiàn)END
JZE L1 ;若是結(jié)束符,退出循環(huán)
LEA GR1,-1,GR1 ;長(zhǎng)度計(jì)數(shù)器+1
JMP LOOP
L1 ST GR0,L ;長(zhǎng)度→L
EXIT
L DS 1
FEND DC '$'
STR DC 'This is a sample$'
END

 4)多重循環(huán)

【例5】冒泡排序程序。

一組有符號(hào)數(shù)al(i=1,2,…,100),存放在Al開(kāi)始的連續(xù)單元中。下面一程序?qū)⑦@組數(shù)在原來(lái)的內(nèi)存區(qū)中由大到小重新排序。

SB START
LEA GR1,99
ST GR1,CN ;外循環(huán)計(jì)數(shù)器初值
L1 LEA GR1,0 ;外循環(huán)指針
LEA CR2,1 ;內(nèi)循環(huán)指針兼計(jì)數(shù)器初值
LEA GR3,0 ;交換標(biāo)志置0
L2 LD GR0,A1,GR1
CPA GR0,A1,GR2
JPZ  L3 ;內(nèi)循環(huán)體,若Ai≥Ai+1,不動(dòng)
LD GR4,A1,GR2 ;若Ai<Ai+1,交換
ST GR4,A1,GR1
ST GR0,A1,GR2
LEA GR3,1 ;交換標(biāo)志置1
L3 LEA GR1,1,GR1 ;內(nèi)循環(huán)調(diào)整
LEA GR2,1,GR2
CPL GR2,CN
JZE L2 ;內(nèi)循環(huán)控制
JMI L2
LEA CR3,0,CR3
JZE L4 ;本次內(nèi)循環(huán)交換標(biāo)志為0,排序結(jié)束
LD GR4,CN ;外循環(huán)計(jì)數(shù)減1
LEA GR4,-1,GR4
JZE L4 ;排序結(jié)束
ST  GR4,CN
JMP L1
L4 EXIT
A1 DS 100
CN DS 1
END

  這是一個(gè)二重循環(huán)結(jié)構(gòu)的程序。程序中采用冒泡排序的方法,首先從第1個(gè)單元開(kāi)始,依次把相鄰兩個(gè)元素比較,即第1個(gè)單元內(nèi)的數(shù)與第2個(gè)單元內(nèi)的數(shù)比較,第2個(gè)單元內(nèi)的數(shù)與第3個(gè)單元內(nèi)的數(shù)比較,…第99個(gè)單元與第100個(gè)單元的數(shù)相比較。每次把較大者放在前面單元,較小者放在后面單元。這樣第一次遍歷做了n-1次比較,最后最小的元素放在第100個(gè)單元。

第二次遍歷再?gòu)念^開(kāi)始,依次將相鄰兩個(gè)元素進(jìn)行比較,把n-1個(gè)元素遍歷一次需做n-2次比較,這樣,第99個(gè)單元存放全部元素中次小元素。

如此反復(fù),小的元素往下,大的元素向上猶如汽泡上浮,因此這種排序的方法給它一個(gè)形象的名字,叫做冒泡算法。在程序中還設(shè)GR3為交換標(biāo)志,若本次內(nèi)循環(huán)結(jié)束交換標(biāo)志為0,說(shuō)明沒(méi)有交換。即所有的Ai≥Ai+1,排序結(jié)束。
4、子程序

所謂子程序是指完成一定功能的指令序列,在主程序的若干地方可以用CALL指令對(duì)它調(diào)用,子程序結(jié)束時(shí)通過(guò)RET指令返回主程序。在子程序中,如果沒(méi)有特別說(shuō)明,則子程序中所要使用到的寄存器要保護(hù)。在子程序的開(kāi)始用PUSH指令將子程序中要使用的寄存器保護(hù),在返回前用POP指令恢復(fù)。主程序與子程序可以處在同一個(gè)程序中,此時(shí),主程序?qū)ψ映绦虻恼{(diào)用稱(chēng)為程序內(nèi)的調(diào)用,CASL中也允許主程序與子程序不在同一個(gè)程序中,這樣的調(diào)用就稱(chēng)為程序間凋用。

在子程序中一般不將GR4作為通用寄存器使用,因?yàn)镚R4作為棧頂指針。如果其它通用寄存器不夠用,要使用GR4,則先將GR4中的棧頂指針值保存,然后使用GR4,GR4使用完后,立即恢復(fù)棧指針的值。

1)參數(shù)傳遞

主程序調(diào)用子程序時(shí),通常要向子程序傳遞參數(shù)(入口參數(shù))。子程序結(jié)束,也會(huì)有數(shù)據(jù)送回主程序(返回參數(shù))。當(dāng)參數(shù)較少時(shí),主程序?qū)?shù)存于寄存器(GR0~GR3)傳遞給子程序;也可放于內(nèi)存給子程序;當(dāng)傳遞參數(shù)較多時(shí),通常存于內(nèi)存(參數(shù)表),并將參數(shù)表的首地址存于寄存器傳遞給子程序;也可以通過(guò)堆棧傳遞參數(shù)值。

【例1】寄存器傳遞參數(shù)

MAIN START
LD GR0,A ;被加數(shù)送GR0
LEA GR1,B ;加數(shù)送GR1
CALL SUBA
ST GR0,C ;結(jié)果回送
……
EXIT
SUBA ADD GR0,0,GR1
RET
A DC 56
B DC 89
C DS 1
D DC 186
E DC 567
F DS 1
END

【例2】?jī)?nèi)存?zhèn)鬟f參數(shù)

MAIN START
LD GR0,A ;被加數(shù)送GR0
LD GR1,B
ST GR1,BUF ;加數(shù)送BUF內(nèi)存單元
CALL SUBA
ST GR0,C ;結(jié)果回送
……
EXIT
SUBA ADD GR0,BUF
RET
BUF DS 1
A DC 56
B DC 89
C DS 1
D DC 186
E DC 567
F DS 1
END

【例3】參數(shù)表傳遞參

MAIN START
LEA  GR1,LIST ;參數(shù)表首址送GR1
CALL SUBA
EXIT
SUBA LD GR0,0,GR1 ;被加數(shù)
ADD GR0,1,GR1 ;與加數(shù)相加
ST GR0,2,GR1 ;結(jié)果回送
RET
LIST DC 56
DC 89
DS 1
END

【例4】堆棧傳遞參數(shù)

MAIN START
LD GR1,A
PUSH 0,GR1 ;被加數(shù)壓入堆棧
LD GR1,B
PUSH 0,GR1 ;加數(shù)壓入堆棧
LEA GR1,C
PUSH 0,GR1 ;結(jié)果地址壓入堆棧
CALL SUBA
LEA GR4,3,GR4 ;堆棧指針退回
EXIT
SUBA LD GR0,3,GR4 ;被加數(shù)
ADD GR0,2,GR4 ;與加數(shù)相加
LD GR1,1,GR4 ;結(jié)果地址
ST GR0,0,GR1 ;結(jié)果回送
RET
A DC 56
B DC 89
C DS 1
END

2)子程序的返回

子程序通過(guò)RET指令返回主程序。RET指令的功能是將棧頂?shù)姆祷氐刂分萌隤C。一般情況,應(yīng)該保證返回時(shí)的堆棧指針SP(GR4)與調(diào)用時(shí)一致。以保證正確返回。但CASL中,GR4兼作通用寄存器,變址器和棧頂指針,因此在子程序中可以通過(guò)GR4修改返回地址,這樣子程序返回時(shí),就不一定返回到主程序的調(diào)用點(diǎn)下面的一條指令。在早期的程序員CASL試題中常常利用這一技巧。

3)現(xiàn)場(chǎng)保護(hù)

通常情況下,子程序都應(yīng)該保護(hù)它所使用過(guò)的寄存器。因PUSH指令不能保護(hù)GR0,所以GR0用ST指令保護(hù),用LD指令恢復(fù)。

【例4】無(wú)符號(hào)乘法。

有兩個(gè)無(wú)符號(hào)數(shù)N1,N2,下面一子程序?qū)崿F(xiàn)N1×N2返回。調(diào)用子程序時(shí)GR1存放參數(shù)N1、N2和相乘結(jié)果的存放區(qū)域的首地址,如下圖所示。設(shè)相乘過(guò)程不會(huì)產(chǎn)生溢出。

GR1+0 N1
+1 N2
+2 結(jié)果
MULT START
ST GR0,SAVE
PUSH 0,GR2 ;保護(hù)寄存器
PUSH 0,GR3
LEA GR2,0 ;部分積清零
LEA GR3,16 ;循環(huán)計(jì)算器
LD GR0,1,GR1 ;取出乘數(shù)N2
LOOP SLL GR2,1 ;部分積左移一位
SLL GR0,0 ;測(cè)乘數(shù)N2最高位是否為1
JPZ L1 ;若為0,跳過(guò)這一位
ADD GR2,0,GR1 ;若為1,部分積加上被乘數(shù)
L1 SLL GR0,1 ;乘數(shù)左移一位,算下一位
LEA GR3,-1,GR3 ;16位算完否?
JNZ LOOP
ST GR2,2,GR1 ;存放乘積
LD GR0,SAVE ;恢復(fù)寄存器的值
POP GR3
POP GR2
RET
SAVE DS 1
END

象手算乘法一樣,由于兩個(gè)數(shù)是二進(jìn)制數(shù),所以唯一的問(wèn)題是乘0還是乘1;顯然,乘0結(jié)果為0,而乘1則結(jié)果與開(kāi)始的數(shù)(被乘數(shù))相同。因此在二進(jìn)制乘法中每一步都可以簡(jiǎn)化成下列運(yùn)算:
如果乘數(shù)中現(xiàn)有位為1,則將被乘數(shù)加到部分積上,為0則不加。剩下的問(wèn)題是部分積和被乘數(shù)每次相加要進(jìn)行移位,保證每次相加都正確對(duì)準(zhǔn)。乘法過(guò)程可分成以下幾步:

(1)積清0,設(shè)置計(jì)數(shù)器初值16。

(2)積左移1位。

(3)乘數(shù)最高位是否為1。

(4)若為1,則被乘數(shù)加積。

(5)乘數(shù)左移1位,計(jì)數(shù)器減1,若不為0轉(zhuǎn)(2)。

程序中GR0存乘數(shù),GR2存積,GR3為計(jì)數(shù)器

二、匯編語(yǔ)言常用子程序

1、拆字與拼字:

【例1】將 GR0 中的四位 BCD 碼從高到低依次存放到 GR2 所指的四個(gè)內(nèi)存單元中。

START
LEA GR3,4 ;循環(huán)計(jì)數(shù)器
L1 ST GR0,REG ;保護(hù)其余幾位 BCD 碼
AND GR0,C000F ;屏蔽高 3 位,留下最低 1 位 BCD 碼
ST GR0,3,GR2 ;將此位 BCD 碼存放到 GR2 所指第四個(gè)內(nèi)存單元
LD GR0,REG ;恢復(fù)其余幾位 BCD 碼
SRL GR0,4 ;將已處理過(guò)的此位 BCD 碼移出
LEA GR2.-1,GR2 ;地址指針減 1
LEA GR3,-1,GR3 ;循環(huán)計(jì)數(shù)器減 1
JNZ L1 ;未處理完,繼續(xù)
RET
C000F DC #000F ;十六進(jìn)制常數(shù),屏蔽高 3 位 BCD 碼用
REG DS 1 ;暫存單元
END

【例2】將存放在 GR2 所指的四個(gè)內(nèi)存單元中的四位 BCD 碼依從高到低順序壓縮到 GR0 中 。

START
LEA GR0,0 ;GR0 清 0
LEA GR3,4 ;循環(huán)計(jì)數(shù)器
L1 SLL GR0,4 ;將已處理過(guò)的 BCD 碼移到高位
LD GR1,0,GR2 ;GR1 用作臨時(shí)工作寄存器
AND GR1,C000F ;屏蔽高 12 位
ST GR1,0,GR2 ;對(duì)內(nèi)存單元中的 BCD 碼預(yù)處理
ADD GR0,0,GR2 ;將已處理過(guò)的此位 BCD 碼加到 GR0 低位
LEA GR2.1,GR2 ;地址指針指向下一位 BCD 碼
LEA GR3,-1,GR3 ;循環(huán)計(jì)數(shù)器減 1
JNZ L1 ;未處理完,繼續(xù)
RET
C000F DC #000F ;十六進(jìn)制常數(shù),屏蔽高 12 位二進(jìn)制數(shù)
END

2、數(shù)字與 ASCII 碼之間的相互轉(zhuǎn)換:

十進(jìn)制數(shù)字 0~9 的 ASCII 碼是 30H~39H ,所以只要將十進(jìn)制數(shù)(BCD 碼)加 30H 就是對(duì)應(yīng)的 ASCII 碼。

十六進(jìn)制數(shù)轉(zhuǎn)換成 ASCII 碼可分成兩段, 0~9 的 ASCII 碼是 30H~39H ,即加 30H ;A~F 的ASCII 碼是 41H~45H ,即加 37 H。

【例1】將 GR0 中的四位 BCD 碼化成 ASCII 碼從高到低依次存放到字符串變量 STR 中。

START
LEA GR2,3 ;相對(duì)于 STR 首址的地址指針
LEA GR3,4 ;循環(huán)計(jì)數(shù)器
L1 ST GR0,REG ;保護(hù)其余幾位 BCD 碼
AND GR0,C000F ;屏蔽高 3 位,留下最低 1 位 BCD 碼
ADD GR0,C30 ;轉(zhuǎn)換成 ASCII 碼
ST GR0,STR,GR2 ;將 ASCII 碼存放到 GR2 所指第四個(gè)內(nèi)存單元
LD GR0,REG ;恢復(fù)其余幾位 BCD 碼
SRL GR0,4 ;將已處理過(guò)的此位 BCD 碼移出
LEA GR2.-1,GR2 ;地址指針減 1
LEA GR3,-1,GR3 ;循環(huán)計(jì)數(shù)器減 1
JNZ L1 ;未處理完,繼續(xù)
RET
C000F DC #000F ;十六進(jìn)制常數(shù),屏蔽高 3 位 BCD 碼用
C30 DC #30 ;十六進(jìn)制常數(shù) 30
STR DS 4
REG DS 1 ;暫存單元
END

【例2】將 GR0 中的 16 位二進(jìn)制數(shù)化成四位十六進(jìn)制數(shù) ASCII 碼從高到低依次存放到字符串變量 STR 中。

START
LEA GR2,3 ;相對(duì)于 STR 首址的地址指針
LEA GR3,4 ;循環(huán)計(jì)數(shù)器
L1 ST GR0,REG ;保護(hù)其余幾位二進(jìn)制數(shù)
AND GR0,C000F ;屏蔽高 12 位,留下最低 4 位二進(jìn)制數(shù)
CPL GR0,C10 ;< 10 否?
JMI L2 ;< 10 跳過(guò)加 7 ,只加 30H
ADD GR0,C7 ;≥ 10,加 30H 前先加上 7
L2 ADD GR0,C30 ;加上 30H
ST GR0,STR,GR2 ;將 ASCII 碼存放到 GR2 所指第四個(gè)內(nèi)存單元
LD GR0,REG ;恢復(fù)其余幾位二進(jìn)制數(shù)
SRL GR0,4 ;將已處理過(guò)的此 4 位二進(jìn)制數(shù)移出
LEA GR2.-1,GR2 ;地址指針減 1
LEA GR3,-1,GR3 ;循環(huán)計(jì)數(shù)器減 1
JNZ L1 ;未處理完,繼續(xù)
RET
C000F DC #000F ;十六進(jìn)制常數(shù),屏蔽屏蔽高 12 位二進(jìn)制數(shù)
C30 DC #30 ;十六進(jìn)制常數(shù) 30
C10 DC 10 ;十進(jìn)制常數(shù) 10
C7 DC 7 ;常數(shù) 7
STR DS 4
REG DS 1 ;暫存單元
END

【例3】將字符串 STR 中的四位十六進(jìn)制數(shù)的 ASCII 碼化成 16 位二進(jìn)制數(shù)放到 GR0 中 。

START
LEA GR0,0 ;GR0 清 0
LEA GR2,0 ;相對(duì)于 STR 首址的地址指針
LEA GR3,4 ;循環(huán)計(jì)數(shù)器
L1 SLL GR0,4 ;將已處理過(guò)的十六進(jìn)制數(shù)移到高位
LD GR1,STR,GR2 ;GR1 用作臨時(shí)工作寄存器
AND GR1,C00FF ;屏蔽高 8 位
SUB GR1,C30 ;減去30H
CPL GR1,C0A ;< 10 否?
JMI L2 ;< 10 ,完成轉(zhuǎn)換
SUB GR1,C7 ;≥ 10,再減去 7
L2 ST GR1,STR,GR2 ;將 STR 中的 ASCII 碼轉(zhuǎn)換成十六進(jìn)制數(shù)
ADD GR0,STR,GR2 ;將此位十六進(jìn)制數(shù)加到 GR0 低位
LEA GR2.1,GR2 ;地址指針指向下一位 ASCII 碼
LEA GR3,-1,GR3 ;循環(huán)計(jì)數(shù)器減 1
JNZ L1 ;未處理完,繼續(xù)
RET
C00FF DC #00FF ;十六進(jìn)制常數(shù),屏蔽高 8 位用
C30 DC #30 ;十六進(jìn)制常數(shù) 30
C0A DC #0A ;十六進(jìn)制常數(shù) 0A
C7 DC 7 ;常數(shù) 7
STR DS 4
END

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

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

若操作數(shù)是無(wú)符號(hào)數(shù),用邏輯移位指令;若操作數(shù)是有符號(hào)數(shù),用算術(shù)移位指令。

【例1】將 GR0 中的二進(jìn)制數(shù)乘以 8。

SLL GR0,3

【例2】將 GR0 中的帶符號(hào)二進(jìn)制數(shù)除以 4。

SRA GR0,2

2)將移位指令和加減法結(jié)合起來(lái)可完成乘數(shù)不是 2 的整數(shù)次方的乘法運(yùn)算。

【例1】將 GR0 中的二進(jìn)制數(shù)乘以 10。

START
SLL GR0,1
ST GR0,REG
SLL GR0,2
ADD GR0,REG
RET
REG DS 1
END

【例2】將 GR0 中的二進(jìn)制數(shù)乘以 7。

START
ST GR0,REG
SLL GR0,3
SUB GR0,REG
RET
REG DS 1
END

4、二進(jìn)制數(shù)與十進(jìn)制數(shù)的轉(zhuǎn)換

1)二化十:

將二進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制數(shù)的一種常用算法是將被轉(zhuǎn)換的二進(jìn)制數(shù)依次被 10i( 對(duì) 16 位二進(jìn)制數(shù),i為 4、3、2、1、0)除,所得的商即為該十進(jìn)制數(shù)位的值,其余數(shù)再被下一個(gè) 10i 除。一般用減法代替除法,即一邊減 10i,一邊計(jì)數(shù)器加 1,直到不夠減再進(jìn)行下一位 10i-1。以求得十進(jìn)制數(shù)的各位數(shù)。

例如:一個(gè)相當(dāng)于十進(jìn)制數(shù) 34635 的二進(jìn)制數(shù),可先用 10000 去減,可減 3 次,得萬(wàn)位數(shù)是 3;再用 1000 去減,得千位數(shù)是 4;……

【例1】將 GR0 中的二進(jìn)制數(shù)轉(zhuǎn)換為十進(jìn)制數(shù)的ASCII 碼放入字符串 STR 中。

START
LEA GR1,0 ;減數(shù)表及字符串指針
LEA GR2,5 ;循環(huán)計(jì)數(shù)器
L1 LEA GR3,48 ;該十進(jìn)制位的數(shù)碼預(yù)置 0 的 ASCII 碼
L2 LEA GR3,1,GR3 ;數(shù)碼位的 ASCII 碼加 1
SUB GR0,SNO,GR1 ;操作數(shù)減去 10
JPZ L2 ;夠減,繼續(xù)
ADD GR0,SNO,GR1 ;不夠減,操作數(shù)及數(shù)碼位的 ASCII 碼恢復(fù)
LEA GR3,-1,GR3
ST GR3,STR,GR1 ;轉(zhuǎn)換好的該位 ASCII 碼存入結(jié)果字符串
LEA GR1,1,GR1 ;地址指針加 1
LEA GR2,-1,GR2 ;循環(huán)計(jì)數(shù)器減 1
JNZ L1 ;未結(jié)束,繼續(xù)下一位
RET
SNO DC 10000
DC 1000
DC 100
DC 10
DC 1
STR DS 5 ;轉(zhuǎn)換結(jié)果字符串
END

1)十化二:

將十進(jìn)制數(shù)轉(zhuǎn)換為二進(jìn)制數(shù)的算法基礎(chǔ)是下面公式:

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

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

可以用循環(huán)程序?qū)崿F(xiàn)此公式,*10 可用移位及加法指令完成。

【例2】將存放在字符串 STR 中的五位十進(jìn)制數(shù)(<65536)的 ASCII 碼轉(zhuǎn)換成二進(jìn)制數(shù)放到 GR0 中 。

START
LEA GR0,0 ;轉(zhuǎn)換結(jié)果寄存器清 0
LEA GR2,5 ;循環(huán)計(jì)數(shù)器
LEA GR1,0 ;地址指針(偏移量)
L1 SLL GR0,1 ;轉(zhuǎn)換結(jié)果*10,先乘以 2
ST GR0,REG ;暫存 2*X
SLL GR0,2 ;2*X*4=8*X
ADD GR0,REG ;8*X + 2*X
LD GR3,STR,GR1 ;取一位 ASCII 碼
AND GR3,C000F ;將 ASCII 碼變成 BCD 碼
ST GR3,REG ;結(jié)果暫存
ADD GR0,REG ;將新的一位 BCD 碼加到轉(zhuǎn)換結(jié)果中
LEA GR1,1,GR1 ;地址指針加 1
LEA GR2,-1,GR2 ;循環(huán)計(jì)數(shù)器減 1
JNZ L1 ;未結(jié)束,繼續(xù)下一位
RET
C000F DC #000F ;十六進(jìn)制常數(shù),屏蔽高 12 位二進(jìn)制數(shù)
STR DC '35475'
REG DS 1 ;暫存單元
END

5、求累加和

【例1】將變量 NUMBER 中的 5 個(gè)二進(jìn)制數(shù)累加后放入變量 SUM 中。

START
LEA GR2,NUMBER ;地址指針
LEA GR3,5 ;循環(huán)計(jì)數(shù)器
LEA GR0,0 ;累加和清0
L1 ADD GR0,0,GR2 ;累加
LEA GR2,1,GR2 ;地址指針指向下一個(gè)二進(jìn)制數(shù)
LEA GR3,-1,GR3 ;計(jì)數(shù)器減1
JNZ L1 ;未完,繼續(xù)
ST GR0,SUM ;累加結(jié)束,累加和送入 SUM 單元
RET
NUMBER DS 5
SUM DS 1
END

【例2】將自然數(shù)1~16累加后放入變量 SUM 中。

START
LEA GR1,0 ;地址指針
LEA GR0,0 ;累加和清 0
L1 LEA  GR1,1,GR1 ;自然數(shù)加1
ST GR1,SUM ;加數(shù)(自然數(shù))送入內(nèi)存暫存
ADD GR0,SUM ;累加
CPA GR1,A
JNZ L1 ;未完,繼續(xù)
ST GR0,SUM ;累加結(jié)束,累加和送入 SUM 單元
EXIT
A DC 16
SUM DS 1
END

LEA GR1,0
LEA GR0,0 ;累加和(被加數(shù))
CF LEA GR1,1,GR1
 ;
ADD GR0,C
 
JNZ CF
ST GR0,B
EXIT
A DC 16

6、利用遞歸方法求5的階乘

START ;主程序
LEA GR1,5 ;入口參數(shù)5(階乘)→GR1
CALL FACT ;調(diào)用FACT子程序
EXIT
FACT LEA GR1,0,GR1
JNZ IIA ;GR1未到0,繼續(xù)遞歸
LEA GR1,1 ;GR1=0,退出遞歸
RET
IIA PUSH 0,GR1 ;保護(hù)這一級(jí)乘數(shù)
LEA GR1,-1,GR1 ;乘數(shù)減1
CALL FACT ;繼續(xù)調(diào)用FACT子程序自己
POP GR1 ;逐級(jí)退出遞歸,恢復(fù)本級(jí)乘數(shù)
LEA GR0,0
CALL MUL ;乘上本級(jí)乘數(shù)
RET
MUL ADD GR0,RESUL
LEA GR1,-1,GR1
JNZ MUL
ST GR0,RESUL
RET
RESUL DC 1
END

 


轉(zhuǎn)帖于:軟件水平考試_考試吧
文章搜索  
看了本文的網(wǎng)友還看了:
·軟件工程習(xí)題200題之二  (2004-12-29 23:54:00)
·軟件工程習(xí)題200題之一  (2004-12-29 23:53:00)
·Casl匯編語(yǔ)言輔導(dǎo)(下)  (2004-12-29 23:52:00)
軟件水平考試權(quán)威輔導(dǎo)教材: 訂書(shū)電話(huà):010-62168566  更多>>>
網(wǎng)友評(píng)論
昵 稱(chēng): *  評(píng) 分: 1分 2分 3分 4分 5分
標(biāo)題:   匿名發(fā)表    (共有條評(píng)論)查看全部評(píng)論>>
版權(quán)聲明 -------------------------------------------------------------------------------------
  如果軟件水平考試網(wǎng)所轉(zhuǎn)載內(nèi)容不慎侵犯了您的權(quán)益,請(qǐng)與我們聯(lián)系,我們將會(huì)及時(shí)處理。如轉(zhuǎn)載本軟件水平考試網(wǎng)內(nèi)容,請(qǐng)注明出處。
關(guān)于本站  網(wǎng)站聲明  廣告服務(wù)  聯(lián)系方式  付款方式  站內(nèi)導(dǎo)航  客服中心  友情鏈接  考試論壇  網(wǎng)站地圖
Copyright © 2004-2008 考試吧軟件水平考試網(wǎng) All Rights Reserved    
中國(guó)科學(xué)院研究生院權(quán)威支持(北京) 電 話(huà):010-62168566 傳 真:010-62192699
百度大聯(lián)盟黃金認(rèn)證  十佳網(wǎng)絡(luò)教育機(jī)構(gòu)  經(jīng)營(yíng)許可證號(hào):京ICP060677