一、Casl匯編語言語法介紹
學習一個匯編語言需要掌握3個要點:CPU 的可編程寄存器結構、尋址方式及指令系統、偽指令。
1、COMETCPU 的可編程寄存器 COMETCPU 字長 16 位,采用從左到右的編號。bit0 在最左邊(最高位),bit15 在最右邊(最低位)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1)16 位通用寄存器五個:
GR0、GR1、GR2、GR3、GR4
通用功能:各種算術邏輯運算
特殊功能:除 GR0 外都可作變址寄存器(地址指針)XR,GR0 可看成累加器。
GR4 兼作堆棧指針(SP)
2)指令計數器 PC 一個(16位)
存放正在執行的那條指令的第 1 個字的地址(一條指令占二個字),指令結束時,PC 中存放下一條指令的地址(一般為原指令地址 +2 )。
3)狀態寄存器 FR 一個(二位)
運算結果 FR0 FR1 大於 0 0 等於 0 1 小於 1 0
可以把 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 │ AND ├ GR,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 決定。
SLA ┐ GR,ADR[,XR] SRA ┘
7)邏輯左移 SLL、邏輯右移 SRL:把操作數看成無符號數。對寄存器操作數進行移位(不管左右移,GR 空出的位補 0 ),位數由有效地址 E 決定。
SLL ┐ GR,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 │ JMI ├ ADR[,XR] JNZ │ JZE ┘
●當地址碼中缺 [XR] 時,所有轉移指令為直接轉移( ADR 即為轉移地址)
當地址碼中有 [XR] 時,所有轉移指令為間接相對接轉移
●JPZ 與 JMI 根據符號位 FR0 作為判斷條件
JNZ 與 JZE 根據零位位 FR1 作為判斷條件
10)進棧 PUSH 與出棧 POP:
(1)進棧指令 PUSH:
PUSH ADR[,XR]
(SP)-1→SP,E→(SP)
(2)出棧指令 POP:
POP GR
((SP))→GR,(SP)+1→SP
注意:出棧指令的目的寄存器是 GR0~GR4,而進棧指令的源操作數不包括 GR0。
11)子程序調用CALL與返回 RET指令
4、偽指令
1)START:程序開始
2)END:程序結尾
3)常量定義指令 DC:
此偽指令與其它匯編語言中的 DB 指令似。利用 DC 指令可定義:
(1)定義十進制常數:
十進制常數名 DC n
其中 -32768 < n ≤65535
(2)定義字符串常數:
字符串常數名 DC '字符串'
(3)定義十六進制常數:
十六進制常數名 DC #h
其中 0000 ≤ h ≤FFFF
(4)定義地址:
地址常數 DC LABLE
其中 LABLE 是程序中的地址標號
因為 Casl 沒有立即數運算指令,所以需要與立即數進行算術邏輯運算時,都要將立即數定義為內存常數進行運算。
4)變量定義指令 DS:用來保留指定字數的存儲區域
[LABLE] DS n
其中 n 是十進制常數(≥0),當 n=0 時,存儲區域不存在,但標號 LABLE 仍然有效,即代表下一字的地址。
5)宏指令:IN、OUT、EXIT
Casl 中有進行輸入、輸出及結束程序等宏指令,而沒有定義輸入、輸出符號指令,這類處理由操作系統完成。
程序中出現宏指令時,Casl 生成調用操作系統的指令串,但是,生成的指令串字數不定。
執行宏指令時,GR 的內容保持不變,而 FR 的內容不確定。
(1)輸入宏指令 IN:
[LABLE] IN ALABLE,NLABLE
宏指令 IN 從輸入裝置上輸入一個記錄,紀錄中的信息(字符)依次按字符數據的形式存放在標號為 ALABLE 開始的區域內,已輸入的字符個數以二進制數形式存放在標號為 NLABLE 的字中,紀錄之間的分隔符號不輸入。
(2)輸入宏指令 OUT:
[ LABLE] OUT ALABLE,NLABLE
宏指令 OUT 將存放在標號為 ALABLE 開始的區域中的字符數據作為一個記錄向輸出裝置輸出,輸出的字符個數由標號為 NLABLE 的字的內容指定。輸出時,若要紀錄間的分隔符號,由操作系統自動插入輸出。
(3)宏指令 EXIT :
[LABLE] EXIT
宏指令 EXIT 表示程序執行的終止,控制返回操作系統。
二、匯編語言常用子程序
1、拆字與拼字:
【例1】將 GR0 中的四位 BCD 碼從高到低依次存放到 GR2 所指的四個內存單元中。
START LEA GR3,4 ;循環計數器 L1 ST GR0,REG ;保護其余幾位 BCD 碼 AND GR0,C000F ;屏蔽高 3 位,留下最低 1 位 BCD 碼 ST GR0,3,GR2 ;將此位 BCD 碼存放到 GR2 所指第四個內存單元 LD GR0,REG ;恢復其余幾位 BCD 碼 SRL GR0,4 ;將已處理過的此位 BCD 碼移出 LEA GR2.-1,GR2 ;地址指針減 1 LEA GR3,-1,GR3 ;循環計數器減 1 JNZ L1 ;未處理完,繼續 RET C000F DC #000F ;十六進制常數,屏蔽屏蔽高 3 位 BCD 碼用 REG DS 1 ;暫存單元 END
【例2】將存放在 GR2 所指的四個內存單元中的四位 BCD 碼依從高到低順序壓縮到 GR0 中 。
START LEA GR0,0 ;GR0 清 0 LEA GR3,4 ;循環計數器 L1 SLL GR0,4 ;將已處理過的 BCD 碼移到高位 LD GR1,0,GR2 ;GR1 用作臨時工作寄存器 AND GR1,C000F ;屏蔽高 12 位 ST GR1,0,GR2 ;對內存單元中的 BCD 碼預處理 ADD GR0,0,GR2 ;將已處理過的此位 BCD 碼加到 GR0 低位 LEA GR2.1,GR2 ;地址指針指向下一位 BCD 碼 LEA GR3,-1,GR3 ;循環計數器減 1 JNZ L1 ;未處理完,繼續 RET C000F DC #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 LEA GR2,3 ;相對於 STR 首址的地址指針 LEA GR3,4 ;循環計數器 L1 ST GR0,REG ;保護其余幾位 BCD 碼 AND GR0,C000F ;屏蔽高 3 位,留下最低 1 位 BCD 碼 ADD GR0,C30 ;轉換成 ASCII 碼 ST GR0,STR,GR2 ;將 ASCII 碼存放到 GR2 所指第四個內存單元 LD GR0,REG ;恢復其余幾位 BCD 碼 SRL GR0,4 ;將已處理過的此位 BCD 碼移出 LEA GR2.-1,GR2 ;地址指針減 1 LEA GR3,-1,GR3 ;循環計數器減 1 JNZ L1 ;未處理完,繼續 RET C000F DC #000F ;十六進制常數,屏蔽高 3 位 BCD 碼用 C30 DC #30 ;十六進制常數 30 STR DS 4 REG DS 1 ;暫存單元 END
【例2】將 GR0 中的 16 位二進制數化成四位十六進制數 ASCII 碼從高到低依次存放到字符串變量 STR 中。
START LEA GR2,3 ;相對於 STR 首址的地址指針 LEA GR3,4 ;循環計數器 L1 ST GR0,REG ;保護其余幾位二進制數 AND GR0,C000F ;屏蔽高 12 位,留下最低 4 位二進制數 CPL GR0,C0A ;< 10 否? JMI L2 ;< 10 跳過加 7 ,只加 30H ADD GR0,C7 ;≥ 10,加 30H 前先加上 7 L2 ADD GR0,C30 ;加上 30H ST GR0,STR,GR2 ;將 ASCII 碼存放到 GR2 所指第四個內存單元 LD GR0,REG ;恢復其余幾位二進制數 SRL GR0,4 ;將已處理過的此 4 位二進制數移出 LEA GR2.-1,GR2 ;地址指針減 1 LEA GR3,-1,GR3 ;循環計數器減 1 JNZ L1 ;未處理完,繼續 RET C000F DC #000F ;十六進制常數,屏蔽屏蔽高 12 位二進制數 C30 DC #30 ;十六進制常數 30 C0A DC #0A ;十六進制常數 0A C7 DC 7 ;常數 7 STR DS 4 REG DS 1 ;暫存單元 END
【例3】將字符串 STR 中的四位十六進制數的 ASCII 碼化成 16 位二進制數放到 GR0 中 。
START LEA GR0,0 ;GR0 清 0 LEA GR2,0 ;相對於 STR 首址的地址指針 LEA GR3,4 ;循環計數器 L1 SLL GR0,4 ;將已處理過的十六進制數移到高位 LD GR1,STR,GR2 ;GR1 用作臨時工作寄存器 AND GR1,C00FF ;屏蔽高 8 位 SUB GR0,C30 ;減去30H CPL GR0,C0A ;< 10 否? JMI L2 ;< 10 ,完成轉換 SUB GR0,C7 ;≥ 10,再減去 7 L2 ST GR1,STR,GR2 ;將 STR 中的 ASCII 碼轉換成十六進制數 ADD GR0,STR,GR2 ;將此位十六進制數加到 GR0 低位 LEA GR2.1,GR2 ;地址指針指向下一位 ASCII 碼 LEA GR3,-1,GR3 ;循環計數器減 1 JNZ L1 ;未處理完,繼續 RET C00FF DC #00FF ;十六進制常數,屏蔽高 8 位用 C30 DC #30 ;十六進制常數 30 C0A DC #0A ;十六進制常數 0A C7 DC 7 ;常數 7 STR DS 4 END
3、利用加減法及移位指令做乘法:
1)左移指令可將操作數乘 2 的整數次方(2、4、8、16);右移指令可將操作數除以 2 的整數次方。
若操作數是無符號數,用邏輯移位指令;若操作數是有符號數,用算術移位指令。
【例1】將 GR0 中的二進制數乘以 8。
SLL GR0,3
【例2】將 GR0 中的帶符號二進制數除以 4。
SRA GR0,2
2)將移位指令和加減法結合起來可完成乘數不是 2 的整數次方的乘法運算。
【例1】將 GR0 中的二進制數乘以 10。
START SLL GR0,1 ST GR0,REG SLL GR0,2 ADD GR0,REG RET REG DS 1 END
【例2】將 GR0 中的二進制數乘以 7。
START ST GR0,REG SLL GR0,3 SUB GR0,REG RET REG DS 1 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 LEA GR1,0 ;減數表及字符串指針 LEA GR2,5 ;循環計數器 L1 LEA GR3,48 ;該十進制位的數碼預置 0 的 ASCII 碼 L2 LEA GR3,1,GR3 ;數碼位的 ASCII 碼加 1 SUB GR0,SNO,GR1 ;操作數減去 10i JPZ L2 ;夠減,繼續 ADD GR0,SNO,GR1 ;不夠減,操作數及數碼位的 ASCII 碼恢復 LEA GR3,-1,GR3 ST GR3,STR,GR1 ;轉換好的該位 ASCII 碼存入結果字符串 LEA GR1,1,GR1 ;地址指針加 1 LEA GR2,-1,GR2 ;循環計數器減 1 JNZ L1 ;未結束,繼續下一位 RET SNO DC 10000 DC 1000 DC 100 DC 10 DC 1 STR DS 5 ;轉換結果字符串 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 LEA GR0,0 ;轉換結果寄存器清 0 LEA GR2,5 ;循環計數器 LEA GR1,0 ;地址指針(偏移量) L1 SLL GR0,1 ;轉換結果*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 ;結果暫存 ADD GR0,REG ;將新的一位 BCD 碼加到轉換結果中 LEA GR1,1,GR1 ;地址指針加 1 LEA GR2,-1,GR2 ;循環計數器減 1 JNZ L1 ;未結束,繼續下一位 RET C000F DC #000F ;十六進制常數,屏蔽高 12 位二進制數 STR DC '35475' REG DS 1 ;暫存單元 END
5、求累加和
【例1】將變量 NUMBER 中的 5 個二進制數累加後放入變量 SUM 中。
START LEA GR2,NUMBER ;地址指針 LEA GR3,5 ;循環計數器 LEA GR0,0 ;累加和清 0 L1 ADD GR0,0,GR2 ;累加 LEA GR2,1,GR2 ;地址指針指向下一個二進制數 LEA GR3,-1,GR3 ;計數器減 1 JNZ L1 ;未完,繼續 ST GR0,SUM ;累加結束,累加和送入 SUM 單元 RET NUMBER DS 5 SUM DS 1 END
三、試題解釋
1、2001年試題三
[程序說明]
子程序 DEHZ 用來對 HZ 編碼的字串做解碼處理。
HZ 編碼是海外華人創造的一種將含有高位為 1 的漢字雙字節字串轉換成易於在網絡中傳輸的ASCII 字符串的變換方式。編碼過程中,被轉換字符串中的原漢字子字符串各字節高位作清零處理,使之成為 ASCII 子字符串,並在其前後兩端分別添加 ~{ 和 ~} 作為標記;而對於原 ASCII 子字符串,則將其中的 ~ 改寫為 ~~,其余字符不變。
DEHZ 解碼子程序則是 HZ 編碼的復原過程。復原 ASCII 子字符串過程中遇有 ~~ 字符則改寫為一個 ~ ,遇有 ~{ 則將其後直至 ~} 標記前的各字節高位置 1,復原為漢字子字符串,同時刪除其前後標記。~的後續字符不屬於以上情況均作為錯誤處理。
調用該子程序時, GR1 存放原始字符串首地址, GR2 存放還原後的目標字符串首地址。工作寄存器 GR3 用作處理漢字子字符串的識別標志,進入子程序時應初始化為處理 ASCII 子字符串。程序按照 CASL 語言的標准約定,字符串的每個字符只占用一個存儲字的低八位。原始字符串和目標字符串均以 0 作為結束標志。
[程序]
START 1 DEHZ PUSH 0,GR3 2 PUSH 0,GR2 3 PUSH 0,GR1 4 LEA GR3,0 5 LOOP __(1)__ 6 CPA GR0,MARK0 7 JNZ GOON 8 LEA GR1,1,GR1 9 LD GR0,0,GR1 10 CPA GR0,MARK0 11 __(2)__ 12 CPA GR0,MARK1,GR3 13 JNZ ERROR 14 __(3)__ 15 LEA GR1,1,GR1 16 JMP LOOP 17 ERROR OUT ERS1R,ERLEN 18 JMP EXIT 19 GOON __(4)__ 20 ST GR0,0,GR2 21 LEA GR2,1,GR2 22 LEA GR1,1,GR1 23 CPA GR0,VO 24 __(5)__ 25 EXIT P0P GR1 26 P0P GR2 27 P0P GR3 28 RET 29 V1 DC 1 30 V0 DC O 31 DC #0080 32 MARK0 DC '~ ' 33 MARK1 DC '{ }' 34 ERSTR DC 'ERROR!' 35 ERLEN DC 6 36 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(結束標志) START 1BEG
PUSH 0,GR1 2 PUSH 0,GR2 3 PUSH 0,GR3 4 L1 __(1)__ 5 LEA GR0,0,GR2 6 JMI FINISH 7 LD GR3,1,GR1 8 LEA GR2,0,GR3 9 AND GR2,C7FFF 10 JZE L3 11 SRL GR3,15 12 LEA GR2,-1,GR2 13 L2 __(2)__ 14 LEA GR2,-4,GR2 15 JPZ L2 16 L3 __(3)__ 17 __(4)__ 18 __(5)__ 19 FINISH POP GR3 20 POP GR2 21 POP GR1 22 RET 23 C7FFF DC #7FFF 24 BONUS DC 10 25 DC -5 26 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 BEG PUSH 0,GR2 2 PUSH 0,GR3 3 LEA GR3,1 4 __ (1) __ 5 L1 SLL GR2,1 6 __ (2) __ 7 LEA GR3,1,GR3 8 L2 JZE L3 9 JMP L1 10 L3 __ (3) __ 11 ST GR3,WORK 12 ADD GR1,WORK 13 POP GR3 14 POP GR2 15 RET 16 WORK DS 1 17 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說明]
子程序 SUM 是將存貯字 A 起的 n(n>0) 個字求和,並將結果存於存貯字 B 中。
調用該子程序時,主程序在 GR1 中給出存放子程序所需參數的起始地址。參數的存放次序如下圖:
(GR1)+0
A
+1
n
+2
B
START SUM LD GR2,0,GR1 LD GR3,1,GR1 LEA GR0,0 L5 ADD GR0,0,GR2 LEA GR2,1,GR2 _ (4) _ JNZ L5 L3 __(5) ST GR0,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
4、1998年試題四
[程序說明]
本程序是統計字符串中數字字符"0"至"9"的出現次數。
字符串中的每個字符是用ASCII碼存貯。一個存貯單元存放兩個字符,每個字符占8位二進位。
程序中,被統計的字符串從左至右存放在STR開始的連續單元中,並假定其長度不超過200,字符串以'·'符作為結束。NCH開始的10個單元存放統計結果。
START MIN 1 MIN LEA GR2,9 2 LEA GR0,0 3 L1 _ (1) _ 4 LEA GR2,-1,GR2 5 JPZ L1 6 LEA GR4,0 7 LEA GR1,0 8 L2 LD GR2,STR,GR1 9 EOR GR4,C1 10 JNZ RL 11 _ (2) _ 12 RL SR GR2,8 13 LEA GR3,0,GR2 14 SUB GR3,C9 15 JNZ L4 16 L3 LEA GR3,0,GR2 17 SUB GR3,CO 18 JM1 L5 19 LEA GR2,1 20 _(3)_ 21 _(4)_ 22 L4 LEA GR4,0,GR4 23 JNZ L2 24 _(5)_ 25 JMP L2 26 L5 SUB GR2,C 27 JNZ L4 28 EXIT 29 C1 DC 1 30 C DC '·' 31 C0 DC '0' 32 C9 DC '9' 33 STR DS 200 34 NCH DS 10 35 END 36
[解]
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 變址尋址)。故 (3) 及 (4) 為:"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。
[程序]
START 1 LEA GR1,0 2 LEA GR3,32 3 L1 ____(1)____ 4 JPZ L2 5 ST GR3,0,GR2 6 LEA GR2,1,GR2 7 LEA GR1,1,GR1 8 LEA GR4,-4,GR1 9 JNZ L1 10 L2 ___(2)___ 11 L3 ___(3)___ 12 JMI L4 13 SUB GR0,SNO,GR1 14 LEA GR3,1,GR3 15 ___(4)___ 16 L4 ST GR3,0,GR2 17 LEA GR2,1,GR2 18 LEA GR1,1,GR1 19 ___(5)___ 20 JNZ L2 21 RET 22 SNO DC 10000 23 DC 1000 24 DC 100 25 DC 10 26 DC 1 27 END 28
[解]
這是一個典型的二化十匯編語言題例,其算法是將被轉換的二進制數依次被 10i(i為 4、3、2、1、0)除,所得的商即為該十進制數位的值,其余數再被下一個 10i 除。一般用減法代替除法,即一邊減10i,一邊計數器加 1,直到不夠減再進行下一位 10i-1。
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
6、1996年試題四
[程序說明]
子程序 OFFSET 用二分法,查找無符號整數 M 在一個長度為 N 的有序(升序)無符號整數列表NTABLE 中的位置。程序中標號為 LOW 和 UP 的兩個存儲字分別用作存放查找空間的上下限。
進入子程序時,在 GR1 中中給出存放子程序所需參數的起始地址。參數的存放次序如下圖:
(GR1)+0
M
1
N
2
NTABLE的首址
START 1 OFFSET PUSH 0,GR2 2 PUSH 0,GR3 3 LD GR0,0,GR1 4 LEA GR2,0 5 ST GR2,LOW 6 ___(1)___ 7 ___(2)___ 8 ST GR2,UP 9 LOOP ADD GR2,LOW 10 SRL GR2,1 11 LEA GR3,0,GR2 12 ___(3)___ 13 ___(4)___ 14 JZE FOUND 15 JPZ INCLOW 16 LEA GR2,-1,GR2 ;M<NTABLE(K) 17 ST GR2,UP 18 JMP CMPLU 19 INCLOW LEA GR2,1,GR2 ;M> NTABLE(K) 20 ST GR2,LOW ;K+1→LOW 21 ___(5)___ 22 CMPLU CPL GR2,LOW 23 ___(6)___ 24 ___(7)___ 25 FOUND LEA GR0,1,GR2 26 POP GR3 27 POP GR2 28 RET 29 LOW DS 1 30 UP DS 1 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"