不同匯編程序允許的偽指令并不相同,以下所述的偽指令僅適用于MASM51系統(tǒng),但一些基本的偽指令在大部份匯編程序中都能使用,當(dāng)使用其它的匯編程序版本時(shí),只要注意一下它們之間的區(qū)別就可以了。MASM51中可用的偽指令有:
一、ORG
偽指令ORG用于為在它之后的程序設(shè)置地址值,它有一個(gè)參數(shù),其格式為:
ORG 表達(dá)式
表達(dá)式可以是一個(gè)具體的數(shù)值,也可以包含變量名,如果包含變量名,則必須保證,當(dāng)?shù)谝淮斡龅竭@條偽指令時(shí),其中的變量必須已有定義(已有具體的數(shù)值),否則,無(wú)定義的值將由0替換,這將會(huì)造成錯(cuò)誤。在列表文件中,由ORG定義的指令地址會(huì)被打印出來(lái)。
ORG指令有什么用途呢?指令被翻譯成機(jī)器碼后,將被存入系統(tǒng)的ROM中,一般情況下,機(jī)器碼總是一個(gè)接一個(gè)地放在存儲(chǔ)器中,但有一些代碼,其位置有特殊要求,典型的是五個(gè)中斷入口,它們必須被放在0003H,000BH,0013H,001BH和0023H的位置,否則就會(huì)出錯(cuò),如果我們編程時(shí)不作特殊處理,讓機(jī)器代碼一個(gè)接一個(gè)地生成,不能保證這些代碼正好處于這些規(guī)定的位置,執(zhí)行就會(huì)出錯(cuò),這時(shí)就要用到ORG偽指令了?慈缦吕樱
例:
INT_0 EQU 1000H
TIME_0 EQU 1010H
INT_1 EQU 1020H
TIME_1 EQU 1030H
SERIAL EQU 1040H
AJMP START ;跳轉(zhuǎn)到主程序起始點(diǎn)
LJMP INT_0 ;外中斷0處理程序
LJMP TIME_0 ;定時(shí)中斷0處理程序
LJMP INT_1 ;外中斷1處理程序
LJMP TIME_1 ;定時(shí)中斷1處理程序
LJMP SERIAL ;串行口中斷程序
START:
NOP
END
上面的程序經(jīng)匯編后列表文件如下:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
08-26-96
1000 = INT_0 EQU 1000H
1010 = TIME_0 EQU 1010H
1020 = INT_1 EQU 1020H
1030 = TIME_1 EQU 1030H
1040 = SERIAL EQU 1040H
0000 0111 AJMP START ;跳轉(zhuǎn)到主程序起始點(diǎn)
0002 021000 LJMP INT_0 ;外中斷0處理程序
0005 021010 LJMP TIME_0 ;定時(shí)中斷0處理程序
0008 021020 LJMP INT_1 ;外中斷1處理程序
000B 021030 LJMP TIME_1 ;定時(shí)中斷1處理程序
000E 021040 LJMP SERIAL ;串行口中斷程序
START:
0011 00 NOP
0000 END
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-26-96
;%T Symbol Name Type Value
INT_0 . . . . . . . . . . . . . I 1000
INT_1 . . . . . . . . . . . . . I 1020
SERIAL. . . . . . . . . . . . . I 1040
START . . . . . . . . . . . . . L 0011
TIME_0. . . . . . . . . . . . . I 1010
TIME_1. . . . . . . . . . . . . I 1030
;%Z
00 Errors (0000)
由列表文件,可以繪出代碼在ROM中的映象圖如下:
|
代碼 |
01H |
11H |
02H |
10H |
00H |
02H |
10H |
10H |
02H |
10H |
20H |
|
地址 |
00H |
01H |
02H |
03H |
04H |
05H |
06H |
07H |
08H |
09H |
0AH |
|
代碼 |
02H |
10H |
30H |
02H |
10H |
40H |
00H |
|
|
|
|
|
地址 |
0BH |
0CH |
0DH |
0EH |
0FH |
10H |
11H |
12H |
13H |
14H |
15 |
由上面的映象圖可知,在03H處的代碼為10H,而不是我們要的02H,所以外斷程序INT_0不能被正確執(zhí)行,其它各中斷程序的情況同樣如此,如在0BH處,本來(lái)存放的應(yīng)當(dāng)是定時(shí)器0中斷程序,但按上述的映象圖,0BH處開(kāi)始的3個(gè)代碼是:02H,10H,30H,這是定時(shí)器1的入口地址,所以,如果定時(shí)器0發(fā)生中斷,所執(zhí)行的其實(shí)是定時(shí)器1的中斷程序,這當(dāng)然不對(duì)。
例2:
INT_0 EQU 1000H
TIME_0 EQU 1010H
INT_1 EQU 1020H
TIME_1 EQU 1030H
SERIAL EQU 1040H
AJMP START ;跳轉(zhuǎn)到主程序起始點(diǎn)
ORG 0003H
LJMP INT_0 ;外中斷0處理程序
ORG 000BH
LJMP TIME_0 ;定時(shí)中斷0處理程序
ORG 0013H
LJMP INT_1 ;外中斷1處理程序
ORG 001BH
LJMP TIME_1 ;定時(shí)中斷1處理程序
ORG 0023H
LJMP SERIAL ;串行口中斷程序
START:
NOP
END
上面的程序經(jīng)過(guò)匯編后列表文件如下:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
08-26-96
1000 = INT_0 EQU 1000H
1010 = TIME_0 EQU 1010H
1020 = INT_1 EQU 1020H
1030 = TIME_1 EQU 1030H
1040 = SERIAL EQU 1040H
0000 0126 AJMP START ;跳轉(zhuǎn)到主程序起始點(diǎn)
0003 ORG 0003H
0003 021000 LJMP INT_0 ;外中斷0處理程序
000B ORG 000BH
000B 021010 LJMP TIME_0 ;定時(shí)中斷0處理程序
0013 ORG 0013H
0013 021020 LJMP INT_1 ;外中斷1處理程序
001B ORG 001BH
001B 021030 LJMP TIME_1 ;定時(shí)中斷1處理程序
0023 ORG 0023H
0023 021040 LJMP SERIAL ;串行口中斷程序
START:
0026 00 NOP
0000 END
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-26-96
;%T Symbol Name Type Value
INT_0 . . . . . . . . . . . . . I 1000
INT_1 . . . . . . . . . . . . . I 1020
SERIAL. . . . . . . . . . . . . I 1040
START . . . . . . . . . . . . . L 0026
TIME_0. . . . . . . . . . . . . I 1010
TIME_1. . . . . . . . . . . . . I 1030
;%Z
00 Errors (0000)
由列表文件,可以繪出代碼在ROM中的映象圖如下:
|
代碼 |
01H |
11H |
|
02H |
10H |
00H |
|
|
|
|
|
|
地址 |
00H |
01H |
02H |
03H |
04H |
05H |
06H |
07H |
08H |
09H |
0AH |
|
代碼 |
02H |
10H |
10H |
|
|
|
|
|
02H |
01H |
20H |
|
地址 |
0BH |
0CH |
0DH |
0EH |
0FH |
10H |
11H |
12H |
13H |
14H |
15H |
|
代碼 |
|
|
|
|
|
02H |
10H |
30H |
|
|
|
|
地址 |
16H |
17H |
18H |
19H |
1AH |
1BH |
1CH |
1DH |
1EH |
1FH |
20H |
|
代碼 |
|
|
02H |
10H |
40H |
00H |
|
|
|
|
|
|
地址 |
21H |
22H |
23H |
24H |
25H |
26H |
27H |
28H |
29H |
2AH |
2BH |
由映象圖可知,各中斷程序的代碼都在其規(guī)定地址處,一旦產(chǎn)生中斷即可執(zhí)行相應(yīng)的程序。至于圖中未填的部分(如02H),根據(jù)各編程器不同而不同,一般為FFH或00H。
二、END
END語(yǔ)句標(biāo)志源代碼的結(jié)束,匯編程序遇到END語(yǔ)句即停止運(yùn)行。若沒(méi)有END語(yǔ)句,匯編將報(bào)錯(cuò)。END語(yǔ)句有一個(gè)參數(shù),可以是數(shù)值0,也可以是表達(dá)式,其格式是:
標(biāo)號(hào): END 表達(dá)式
它的值就是程序的地址并且作為一個(gè)特殊的記錄寫(xiě)入HEX文件。若這個(gè)表達(dá)式省略,HEX文件中其值就是0。
三、EQU
EQU以及其它一些符號(hào)定義偽指令用來(lái)給程序中出現(xiàn)的一些符號(hào)賦值。對(duì)這些符號(hào)名的要求與其它符號(hào)相同,即長(zhǎng)度不限,大小寫(xiě)字母可互換并且必須以字母開(kāi)頭。
由等值指令定義的符號(hào)是匯編符號(hào)表的一部分。等值偽指令有兩種形式。一種用EQU,另一種用字符“=”即
符號(hào)名 EQU 表達(dá)式
符號(hào)名 = 表達(dá)式
兩種形式的效果是一樣的。符號(hào)名在左邊,其對(duì)應(yīng)的值在右邊。值可以是變?cè),其它的符?hào)名或表達(dá)式。只要在兩遍掃描中求出表達(dá)式的值就行,否則引用該符號(hào)名時(shí)將報(bào)錯(cuò)。當(dāng)表達(dá)式的值是字符串時(shí),只取后兩個(gè)字符。若串長(zhǎng)為1,高位字節(jié)被置0,符號(hào)名的值被打印在程序清單中。由等值偽指令定義的符號(hào)名不允許重名。如果經(jīng)定義的符號(hào)名被重定義,則匯編將報(bào)出錯(cuò),并且這個(gè)符號(hào)名按新定義的處理,最好不要在程序中出現(xiàn)重名。
例:0469= ABC EQU 469H
0464= XY EQU ABC-5
02F0= JK = 752
0754 XYJK = XY+JK
在列表文件中最左邊的數(shù)字不是這些偽指令所在的地址而是通過(guò)匯編后賦給符號(hào)名的值。第一條符號(hào)名ABC被起來(lái)469H,第二條XY被賦于A(yíng)BC-5,因此XY的值為469H-5=464H,JK的值為752(即2F0H),XYJK的值XY+JK=464H+2F0H=754H
四、SET
SET偽指令有些類(lèi)似于等值偽指令,它定義了一個(gè)整數(shù)類(lèi)型的符號(hào)名,它的格式為
符號(hào)名 SET 表達(dá)式
SET偽指令與等值偽指令的唯一區(qū)別在于SET偽指令所定義的符號(hào)名右以在程序中多次定義,而不報(bào)錯(cuò)。
例:002D= K57 SET 101101B
8707= K57 SET 34567
五、DATA與BYTE
DATA與BYTE都是用來(lái)定義字節(jié)類(lèi)型的存儲(chǔ)單元,賦予字節(jié)類(lèi)型的存儲(chǔ)單元一個(gè)符號(hào)名,以便在程序中通過(guò)符號(hào)名來(lái)訪(fǎng)問(wèn)這個(gè)存儲(chǔ)單元,以幫助對(duì)程序的理解。
BYTE與DATE之間的區(qū)別類(lèi)似于EQU和SET,BYTE偽指令不能定義重名。
六、WORD
WORD偽指令類(lèi)似于DATE偽指令,只是WORD偽指令定義了一個(gè)字類(lèi)型的符號(hào)名,其格式為:
符號(hào)名 WORD 表達(dá)式
0027= VAL31 WORD 39
0021= PAR7 WORD 21H
一個(gè)字由2個(gè)字節(jié)組成。當(dāng)然,因?yàn)椋福埃担眳R編語(yǔ)言集沒(méi)有字操作,所以程序執(zhí)行時(shí),只處理字節(jié)。WROD偽指令僅僅允許用戶(hù)定義一個(gè)認(rèn)為是字的存儲(chǔ)位置。
七、BIT
BIT偽指令定義了一個(gè)字位類(lèi)型的符號(hào)名,其格式為:
符號(hào)名 BIT 表達(dá)式
這里表達(dá)式的值是一個(gè)位地址,這個(gè)偽指令有助于位的地址符號(hào)化。
例:
002F= LOG3 BIT 47
0014= Y731 BIT 14H
八、ALTNAME
替換名(ALTNAME)偽指令提供用戶(hù)一種手段,以定義一個(gè)符號(hào)名來(lái)替換一個(gè)保留字,此后這個(gè)答名與被替換的保留字均可等效地用于程序中。任何保留類(lèi)型的答名均可被替換。替換名偽指令格式為:
ALTNAME 保留字,新名
例:
0002= ALTNAME R2 COUNT
013A EA MOV A,R2
013B E502 MOV A,COUNT
九、DB
DB偽指令用于定義一個(gè)連續(xù)的存儲(chǔ)區(qū),給該存儲(chǔ)區(qū)的存儲(chǔ)單元賦值。該偽指令的參數(shù)即為存儲(chǔ)單元的值,在表達(dá)式中對(duì)變?cè)獋(gè)數(shù)沒(méi)有限制,只要此條偽指令能容納在源程序的一行內(nèi),其格式為:
標(biāo)號(hào): DB 表達(dá)式
只要表達(dá)式不是字符串,每一表達(dá)式值都被賦給一個(gè)字節(jié)。計(jì)算表達(dá)式值時(shí)按16位處理,但其結(jié)果只取低8位,若多個(gè)表達(dá)式出現(xiàn)在一個(gè)DB偽指令中,它們必須以逗號(hào)分開(kāi)。
表達(dá)式中有字符串時(shí),以單引號(hào)“'”作分隔符,每個(gè)字符占一個(gè)字節(jié),字符串不加改變地被存在各字節(jié)中,并不將小寫(xiě)字母轉(zhuǎn)換成大寫(xiě)字母。
例如:
DB 00H 01H 03H 46H
DB 'This is a demo!'
十、DW
DW為以字節(jié)為單元(十六位二進(jìn)制)來(lái)給一個(gè)的存儲(chǔ)區(qū)賦值,其格式為:
標(biāo)號(hào): DW 表達(dá)式
例如:
0000 3035 D46B DW 12341,54379,10110100101110B
0004 2D2E
0006 4344 4243 DW 'ABCD','BC','A'
000A 0041
000C 2868 02E8 DW 456*375h,83+295h,'YZ',72h-456
0010 595A FEAA
十一、DS
DS為定義存儲(chǔ)內(nèi)容的偽指令,用它定義一個(gè)存儲(chǔ)區(qū),并用指定的參數(shù)填滿(mǎn)該存儲(chǔ)區(qū)。
DS偽指令包含兩個(gè)變?cè)谝粋(gè)變?cè)x了存儲(chǔ)區(qū)的長(zhǎng)度的字節(jié)數(shù),在匯編時(shí),匯編程序?qū)⑻^(guò)這些單元把其它指令匯編在這些字節(jié)之后,因此在使用DS偽指令時(shí)第一個(gè)變?cè)豢苫盍Φ诙䝼(gè)變?cè)硎驹谶@些單元中真入什么值,第二個(gè)變?cè)梢曰盍盍r(shí)這些字節(jié)將不處理。下例中0173處有一條DS 9,則空出9個(gè)字節(jié),下一第指令被匯編到017C處;在017C處空出1BH個(gè)單元,在這些字節(jié)中被27H所填充。
DS指令的格式如下:
標(biāo)號(hào): DS 表達(dá)式1,表達(dá)式2
表達(dá)式1定義了存儲(chǔ)區(qū)的長(zhǎng)度(以字節(jié)為單位)。這個(gè)變?cè)荒苁÷浴1磉_(dá)式2是可選擇的,它的值低8位用以填入所定義的存儲(chǔ)區(qū)。
若省略則這部分存儲(chǔ)單元不處理。
例:
0000 04 INC A
0001 DS 9
000A 04 INC A
000B DS 1BH,27H
0026 04 INC A
十二、INCLUDE
INCLUDE偽指令用于鏈接源文件,即將一個(gè)源文件插入到另一個(gè)源文件中。它有一個(gè)參數(shù),指出將要插入的文件名,該文件名中可包括驅(qū)動(dòng)器名和路徑名。若文件沒(méi)有擴(kuò)展名,則默認(rèn)為是ASM。但待插入的文件必須是可以打開(kāi)的。若文件打開(kāi)操作失敗,則產(chǎn)生致命錯(cuò)誤,匯編將停止運(yùn)行。反之,匯編程序?qū)⑽募䞍?nèi)容讀入并按源代碼處理。當(dāng)遇到文件結(jié)速符時(shí),匯編程序返回到INCLUDE偽指令處繼續(xù)身下處理源程序。被插入的文件在程序清單中以“I”開(kāi)頭。
本宏匯編版本支持級(jí)嵌套,可在程序中用INCLUDE偽指令插入任意多個(gè)文件,但是,在一般情況下DOS允許打開(kāi)的文件數(shù)量是有限的,如果用戶(hù)需要打開(kāi)較多的文件,則必須在CONFIG.SYS文件中加入FILES=40或更多的值,若超過(guò)8級(jí)嵌套或打開(kāi)的文件太多,則產(chǎn)生致命錯(cuò)誤,匯編中止運(yùn)行。
INCLUDE偽指令提供了模塊化程序設(shè)計(jì)手段,在匯編程序處理主程序時(shí),模塊被插入,盡管這不等價(jià)于鏈接和裝配可重定位的目標(biāo)模塊,但它具有類(lèi)似的功能,被插入的源文件中不應(yīng)該包含END偽指令,否則,匯編就會(huì)提前停止運(yùn)行,END偽指令只能出現(xiàn)在主程序中。此外,在主程序進(jìn)行匯編前所有附加的源文件必須通過(guò)匯編,產(chǎn)生相應(yīng)的HEX及LST文件,由于附加的文件沒(méi)有END偽指令,因此,附加文件匯編時(shí),匯編程序?qū)@示:“沒(méi)有結(jié)束語(yǔ)句”的錯(cuò)誤,但并不影響與主程序的鏈接。
下面是一個(gè)使用INCLUDE偽指令的例子,其主程序的源文件MAIN.ASM為:
;MAIN.ASM
ORG 27H
START:
CLR A
MOV R3,A
INCLUDE MOD1
INC R5
INCLUDE MOD2.ASM
DEC R3
END START
主程序?yàn)閹в校牛危膫沃噶畹耐暾脑次募3绦蛑杏袃蒊NCLUDE偽指令,分別將兩附加的文件MOD1.ASM及MOD2.ASM鏈接到主程序中。以下是這兩個(gè)文件。
;MOD1.ASM
MOV R2,#31H
MOV R5,#18H
;MOD2.ASM
MOV R6,#47H
ANL A,#07H
MOV R1,A
注意MOD1.ASM及MOD2.ASM均沒(méi)有END指令。
在進(jìn)行匯編時(shí)必須先對(duì)MOD1.ASM和MOD2.ASM進(jìn)行匯編,然后在匯編MAIN.ASM,由于上兩個(gè)文件沒(méi)有END偽指令,所以在匯編時(shí)會(huì)出現(xiàn)錯(cuò)誤提示,不用管它,繼續(xù)下面的工作,就可以得到正確的結(jié)果。
以下是形成的列表文件:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
;MOD2.ASM
MOV R6,#47H
ANL A,#07H
MOV R1,A
08-27-96
;MAIN.ASM
0027 ORG 27H
START:
0027 E4 CLR A
0028 FB MOV R3,A
I INCLUDE MOD1
I ;MOD1.ASM
I0029 7A31 MOV R2,#31H
I002B 7D18 MOV R5,#18H
I
002D 0D INC R5
I INCLUDE MOD2.ASM
I ;MOD2.ASM
I002E 7E47 MOV R6,#47H
I0030 5407 ANL A,#07H
I0032 F9 MOV R1,A
0033 1B DEC R3
0027 END START
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-27-96
;%T Symbol Name Type Value
START . . . . . . . . . . . . . L 0027
;%Z
00 Errors (0000)
十三、TITL
TITLE偽指令用于在列表文件頁(yè)頭建立一個(gè)標(biāo)題,其格式為:
$TITLE 標(biāo)題行
這里標(biāo)量行就是將出現(xiàn)在頁(yè)頭的標(biāo)量與通常的字符串定義不同。這里標(biāo)量行不加引號(hào)。匯編從$TITLE之后的第一個(gè)可打印字符開(kāi)始,到回車(chē)符之間的字符串作為標(biāo)量標(biāo)量的最大長(zhǎng)度是60個(gè)字符,基標(biāo)量行省略,則標(biāo)題行為空行。若TITLE偽指令在一頁(yè),它說(shuō)明的標(biāo)量行包含在本頁(yè),否則,標(biāo)題將出現(xiàn)在下頁(yè)頁(yè)頭。
十四、PAGE
PAGE偽指令用于形成新的一中定義一面的行數(shù)。其格式為:
$PAGE 表達(dá)式
若表達(dá) 式缺省則開(kāi)始新的一頁(yè),若有表達(dá)式,則每頁(yè)行數(shù)重新定義。匯編開(kāi)始時(shí)頁(yè)長(zhǎng)為66行。一頁(yè)中除出頁(yè)外,剩余55行用于打印源程序,這一格式適用于標(biāo)準(zhǔn)打印紙。
如果變?cè)敌∮冢叮,?yè)內(nèi)可打印的源代碼行將相應(yīng)減少。頁(yè)長(zhǎng)最小值為12。若小于12時(shí),每頁(yè)內(nèi)除頁(yè)上只打印一行源程序。
頁(yè)長(zhǎng)變?cè)牵保段蛔止?jié),因而每頁(yè)最長(zhǎng)可定義到65535行,這時(shí)分頁(yè)打印變?yōu)檫B續(xù)打印,在屏幕顯示程序清單或在卷筒紙上打印程序清單時(shí),常常使用連續(xù)打印,如果在啟動(dòng)匯編時(shí)用/N選項(xiàng),頁(yè)長(zhǎng)就是65535。
十五、LIST與NOLIST
它們的格式為:
$LIST
$NOLIST
LIST偽指令使匯編時(shí)主生程序清單,但即使不用該指令,匯編也會(huì)自動(dòng)產(chǎn)生清單。但如果使用了NOLIST偽指令后需要繼續(xù)主生清單則必須使用LIST偽指令。
NOLIST偽指令使匯編時(shí)不產(chǎn)生清單,所有包含此偽指令及在這條偽指令之后的語(yǔ)句都不進(jìn)入列表文件。當(dāng)不需要任何列表文件,并且不需要顯示程序清單時(shí),可以在啟動(dòng)匯編時(shí)不加.L附加項(xiàng),且在源代碼的第一行加上NOLIST指令。
使用NOLIST偽指令與附加項(xiàng)/L不同之處是NOLIST偽指令可加在源程序中,與LIST偽指令配合使用,使源程序中某些部分不產(chǎn)生清單。而不加附加項(xiàng)/L則不產(chǎn)生任何程序清單。不過(guò),不管有無(wú)$NOLIST偽指令,程序在匯編時(shí)檢查到的錯(cuò)誤都將在屏幕上顯示出錯(cuò)的源代碼行及錯(cuò)誤信息
十六、NOCODE
NOCODE偽指令使得在匯編時(shí),條件匯編程序結(jié)構(gòu)中那些真值為假的條件不產(chǎn)生清單。有關(guān)條件匯編結(jié)構(gòu)在下面介紹。如果沒(méi)有這條偽指令,匯編將主生所有條件下的清單,不論其真值是否為真。但是假的條件,不產(chǎn)生目標(biāo)碼。而NOCODE偽指令使匯編清單中只列出那些由匯編程序用到的部分,因此,當(dāng)使用NOCODE偽指令時(shí),程序清單與源程序并非逐行對(duì)應(yīng)。