- 試題排行
- 最新熱點(diǎn)
- 最新推薦
2
3
4
5
6
7
8
9
10
2008年上半年軟考軟件設(shè)計(jì)師考試試題(上午)
2008年上半年軟考網(wǎng)絡(luò)工程師考試試題(下午)
2008年上半年軟考軟件設(shè)計(jì)師考試試題(下午)
2008年上半年軟件水平考試程序員考試試題(上
2008年下半年軟考網(wǎng)絡(luò)工程師預(yù)測試題及答案
2008年上半年軟件水平考試程序員考試試題(下
2008下半年軟件水平考試軟件設(shè)計(jì)師押題試卷
08年上半年軟考數(shù)據(jù)庫系統(tǒng)工程師考試試題(上
2008下半年軟件水平考試程序員模擬試題及答
一、Casl匯編語言語法介紹
學(xué)習(xí)一個(gè)匯編語言需要掌握3個(gè)要點(diǎn):CPU 的可編程寄存器結(jié)構(gòu)、尋址方式及指令系統(tǒng)、偽指令。
1、COMETCPU 的可編程寄存器
COMETCPU 字長 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)指令寫法與尋址方式
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 沒有立即數(shù)尋址。但在 LEA 指令中,當(dāng) [,XR] 省略時(shí),可作立即數(shù)傳送。沒有立即數(shù)運(yùn)算指令。
4)寄存器尋址:Casl 也沒有寄存器尋址(對(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è)無符號(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ù)看成無符號(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)無條件轉(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:程序開始
2)END:程序結(jié)尾
3)常量定義指令 DC:
此偽指令與其它匯編語言中的 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 沒有立即數(shù)運(yùn)算指令,所以需要與立即數(shù)進(jìn)行算術(shù)邏輯運(yùn)算時(shí),都要將立即數(shù)定義為內(nèi)存常數(shù)進(jìn)行運(yùn)算。
4)變量定義指令 DS:用來保留指定字?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é)束程序等宏指令,而沒有定義輸入、輸出符號(hào)指令,這類處理由操作系統(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 開始的區(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 開始的區(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)簡單分支程序
將比較指令(或其它能使標(biāo)志位發(fā)生變化的指令)和條件轉(zhuǎn)移指令結(jié)合,可實(shí)現(xiàn)分支程序。簡單分支程序有兩種形式:
在匯編語言中,采用圖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)多岔分支則程序更為簡練,其思路是在散轉(zhuǎn)表中存放各個(gè)分支程序的入口地址,用查表方法將入口地址放入變址寄存器,然后用JMP指令或CALL指令的間接尋址方式使程序轉(zhuǎn)到此入口。
【例1】根據(jù)鍵盤輸入命令轉(zhuǎn)入各命令處理程序
SB | START | ||
AGAIN | IN |
ALABLE,NLABLE |
;輸入一個(gè)字符串 |
LD | GR1,NLABLE | ;字符串長度 | |
LEA | GR1,0,GR1 | ||
JZE | AGAIN | ;若字符串長度 =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 | ;輸入字符串長度 |
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 | ;字符串長度 | |
LEA | GR1,0,GR1 | ||
JZE | AGAIN | ;若字符串長度 =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),也可用其它條件來控制退出。
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)程序
前面的例子無法實(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】測試字符串STR的長度,并將它保存到L中
SB | START | ||
LEA | GR1,0 | ;字符串長度計(jì)數(shù)器(兼地址指針)清0 | |
LOOP | LD | GR0,STR,GR1 | ;取一字符 |
CPL | GR0,F(xiàn)END | ||
JZE | L1 | ;若是結(jié)束符,退出循環(huán) | |
LEA | GR1,-1,GR1 | ;長度計(jì)數(shù)器+1 | |
JMP | LOOP | ||
L1 | ST | GR0,L | ;長度→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開始的連續(xù)單元中。下面一程序?qū)⑦@組數(shù)在原來的內(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è)單元開始,依次把相鄰兩個(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è)元素進(jìn)行比較,把n-1個(gè)元素遍歷一次需做n-2次比較,這樣,第99個(gè)單元存放全部元素中次小元素。
如此反復(fù),小的元素往下,大的元素向上猶如汽泡上浮,因此這種排序的方法給它一個(gè)形象的名字,叫做冒泡算法。在程序中還設(shè)GR3為交換標(biāo)志,若本次內(nèi)循環(huán)結(jié)束交換標(biāo)志為0,說明沒有交換。即所有的Ai≥Ai+1,排序結(jié)束。
4、子程序
所謂子程序是指完成一定功能的指令序列,在主程序的若干地方可以用CALL指令對(duì)它調(diào)用,子程序結(jié)束時(shí)通過RET指令返回主程序。在子程序中,如果沒有特別說明,則子程序中所要使用到的寄存器要保護(hù)。在子程序的開始用PUSH指令將子程序中要使用的寄存器保護(hù),在返回前用POP指令恢復(fù)。主程序與子程序可以處在同一個(gè)程序中,此時(shí),主程序?qū)ψ映绦虻恼{(diào)用稱為程序內(nèi)的調(diào)用,CASL中也允許主程序與子程序不在同一個(gè)程序中,這樣的調(diào)用就稱為程序間凋用。
在子程序中一般不將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ù)表的首地址存于寄存器傳遞給子程序;也可以通過堆棧傳遞參數(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】內(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)子程序的返回
子程序通過RET指令返回主程序。RET指令的功能是將棧頂?shù)姆祷氐刂分萌隤C。一般情況,應(yīng)該保證返回時(shí)的堆棧指針SP(GR4)與調(diào)用時(shí)一致。以保證正確返回。但CASL中,GR4兼作通用寄存器,變址器和棧頂指針,因此在子程序中可以通過GR4修改返回地址,這樣子程序返回時(shí),就不一定返回到主程序的調(diào)用點(diǎn)下面的一條指令。在早期的程序員CASL試題中常常利用這一技巧。
3)現(xiàn)場保護(hù)
通常情況下,子程序都應(yīng)該保護(hù)它所使用過的寄存器。因PUSH指令不能保護(hù)GR0,所以GR0用ST指令保護(hù),用LD指令恢復(fù)。
【例4】無符號(hào)乘法。
有兩個(gè)無符號(hào)數(shù)N1,N2,下面一子程序?qū)崿F(xiàn)N1×N2返回。調(diào)用子程序時(shí)GR1存放參數(shù)N1、N2和相乘結(jié)果的存放區(qū)域的首地址,如下圖所示。設(shè)相乘過程不會(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 | ;測乘數(shù)N2最高位是否為1 | |
JPZ | L1 | ;若為0,跳過這一位 | |
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ù),所以唯一的問題是乘0還是乘1;顯然,乘0結(jié)果為0,而乘1則結(jié)果與開始的數(shù)(被乘數(shù))相同。因此在二進(jìn)制乘法中每一步都可以簡化成下列運(yùn)算:
如果乘數(shù)中現(xiàn)有位為1,則將被乘數(shù)加到部分積上,為0則不加。剩下的問題是部分積和被乘數(shù)每次相加要進(jìn)行移位,保證每次相加都正確對(duì)準(zhǔn)。乘法過程可分成以下幾步:
(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ù)器
二、匯編語言常用子程序
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 | ;將已處理過的此位 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 | ;將已處理過的 BCD 碼移到高位 |
LD | GR1,0,GR2 | ;GR1 用作臨時(shí)工作寄存器 | |
AND | GR1,C000F | ;屏蔽高 12 位 | |
ST | GR1,0,GR2 | ;對(duì)內(nèi)存單元中的 BCD 碼預(yù)處理 | |
ADD | GR0,0,GR2 | ;將已處理過的此位 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 | ;將已處理過的此位 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 跳過加 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 | ;將已處理過的此 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 | ;將已處理過的十六進(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ù)是無符號(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é)合起來可完成乘數(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 次,得萬位數(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ù)減去 10i | |
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)帖于:軟件水平考試_考試吧
- 推薦給朋友
- 收藏此頁
·軟件工程習(xí)題200題之一 (2004-12-29 23:53:00)
·Casl匯編語言輔導(dǎo)(下) (2004-12-29 23:52:00)
如果軟件水平考試網(wǎng)所轉(zhuǎn)載內(nèi)容不慎侵犯了您的權(quán)益,請(qǐng)與我們聯(lián)系,我們將會(huì)及時(shí)處理。如轉(zhuǎn)載本軟件水平考試網(wǎng)內(nèi)容,請(qǐng)注明出處。