51匯編偽指令
偽指令是對匯編起某種控制作用的特殊命令,其格式與通常的操作指令一樣,并可加在匯編程序的任何地方,但它們并不產生機器指令。
許多偽指令要求帶參數,這在定義偽指令時由“表達式”域指出,任何數值與表達式勻可以作為參數。
不同匯編程序允許的偽指令并不相同,以下所述的偽指令僅適用于MASM51系統,但一些基本的偽指令在大部份匯編程序中都能使用,當使用其它的匯編程序版本時,只要注意一下它們之間的區別就可以了。MASM51中可用的偽指令有:
ORG 設置程序起始地址
END 標志源代碼結束
EQU 定義常數
SET 定義整型數
DATA 給字節類型符號定值
BYTE 給字節類型符號定值
WROD 給字類型符號定值
BIT 給位地址取名
ALTNAME 用自定義名取代保留字
DB 給一塊連續的存儲區裝載字節型數據
DW 給一塊連續的存儲區裝載字型數據
DS 預留一個連續的存儲區或裝入指定字節。
INCLUDE 將一個源文件插入程序中
TITLE 列表文件中加入標題行
NOLIST 匯編時不產生列表文件
NOCODE 條件匯編時,條件為假的不產生清單
一、ORG
偽指令ORG用于為在它之后的程序設置地址值,它有一個參數,其格式為:
ORG 表達式
表達式可以是一個具體的數值,也可以包含變量名,如果包含變量名,則必須保證,當第一次遇到這條偽指令時,其中的變量必須已有定義(已有具體的數值),否則,無定義的值將由0替換,這將會造成錯誤。在列表文件中,由ORG定義的指令地址會被打印出來。
ORG指令有什么用途呢?指令被翻譯成機器碼后,將被存入系統的ROM中,一般情況下,機器碼總是一個接一個地放在存儲器中,但有一些代碼,其位置有特殊要求,典型的是五個中斷入口,它們必須被放在0003H,000BH,0013H,001BH和0023H的位置,否則就會出錯,如果我們編程時不作特殊處理,讓機器代碼一個接一個地生成,不能保證這些代碼正好處于這些規定的位置,執行就會出錯,這時就要用到ORG偽指令了。看如下例子:
例:
INT_0 EQU 1000H
TIME_0 EQU 1010H
INT_1 EQU 1020H
TIME_1 EQU 1030H
SERIAL EQU 1040H
AJMP START ;跳轉到主程序起始點
LJMP INT_0 ;外中斷0處理程序
LJMP TIME_0 ;定時中斷0處理程序
LJMP INT_1 ;外中斷1處理程序
LJMP TIME_1 ;定時中斷1處理程序
LJMP SERIAL ;串行口中斷程序
START:
NOP
END
上面的程序經匯編后列表文件如下:
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 ;跳轉到主程序起始點
0002 021000 LJMP INT_0 ;外中斷0處理程序
0005 021010 LJMP TIME_0 ;定時中斷0處理程序
0008 021020 LJMP INT_1 ;外中斷1處理程序
000B 021030 LJMP TIME_1 ;定時中斷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不能被正確執行,其它各中斷程序的情況同樣如此,如在0BH處,本來存放的應當是定時器0中斷程序,但按上述的映象圖,0BH處開始的3個代碼是:02H,10H,30H,這是定時器1的入口地址,所以,如果定時器0發生中斷,所執行的其實是定時器1的中斷程序,這當然不對。
例2:
INT_0 EQU 1000H
TIME_0 EQU 1010H
INT_1 EQU 1020H
TIME_1 EQU 1030H
SERIAL EQU 1040H
AJMP START ;跳轉到主程序起始點
ORG 0003H
LJMP INT_0 ;外中斷0處理程序
ORG 000BH
LJMP TIME_0 ;定時中斷0處理程序
ORG 0013H
LJMP INT_1 ;外中斷1處理程序
ORG 001BH
LJMP TIME_1 ;定時中斷1處理程序
ORG 0023H
LJMP SERIAL ;串行口中斷程序
START:
NOP
END
上面的程序經過匯編后列表文件如下:
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 ;跳轉到主程序起始點
0003 ORG 0003H
0003 021000 LJMP INT_0 ;外中斷0處理程序
000B ORG 000BH
000B 021010 LJMP TIME_0 ;定時中斷0處理程序
0013 ORG 0013H
0013 021020 LJMP INT_1 ;外中斷1處理程序
001B ORG 001BH
001B 021030 LJMP TIME_1 ;定時中斷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 |
由映象圖可知,各中斷程序的代碼都在其規定地址處,一旦產生中斷即可執行相應的程序。至于圖中未填的部分(如02H),根據各編程器不同而不同,一般為FFH或00H。
二、END
END語句標志源代碼的結束,匯編程序遇到END語句即停止運行。若沒有END語句,匯編將報錯。END語句有一個參數,可以是數值0,也可以是表達式,其格式是:
標號: END 表達式
它的值就是程序的地址并且作為一個特殊的記錄寫入HEX文件。若這個表達式省略,HEX文件中其值就是0。
三、EQUEQU以及其它一些符號定義偽指令用來給程序中出現的一些符號賦值。對這些符號名的要求與其它符號相同,即長度不限,大小寫字母可互換并且必須以字母開頭。
由等值指令定義的符號是匯編符號表的一部分。等值偽指令有兩種形式。一種用EQU,另一種用字符“=”即
符號名 EQU 表達式
符號名 = 表達式
兩種形式的效果是一樣的。符號名在左邊,其對應的值在右邊。值可以是變元,其它的符號名或表達式。只要在兩遍掃描中求出表達式的值就行,否則引用該符號名時將報錯。當表達式的值是字符串時,只取后兩個字符。若串長為1,高位字節被置0,符號名的值被打印在程序清單中。由等值偽指令定義的符號名不允許重名。如果經定義的符號名被重定義,則匯編將報出錯,并且這個符號名按新定義的處理,最好不要在程序中出現重名。
例:0469= ABC EQU 469H
0464= XY EQU ABC-5
02F0= JK = 752
0754 XYJK = XY+JK
在列表文件中最左邊的數字不是這些偽指令所在的地址而是通過匯編后賦給符號名的值。第一條符號名ABC被起來469H,第二條XY被賦于ABC-5,因此XY的值為469H-5=464H,JK的值為752(即2F0H),XYJK的值XY+JK=464H+2F0H=754H
四、SETSET偽指令有些類似于等值偽指令,它定義了一個整數類型的符號名,它的格式為
符號名 SET 表達式
SET偽指令與等值偽指令的唯一區別在于SET偽指令所定義的符號名右以在程序中多次定義,而不報錯。
例:002D= K57 SET 101101B
8707= K57 SET 34567
五、DATA與BYTE
DATA與BYTE都是用來定義字節類型的存儲單元,賦予字節類型的存儲單元一個符號名,以便在程序中通過符號名來訪問這個存儲單元,以幫助對程序的理解。
BYTE與DATE之間的區別類似于EQU和SET,BYTE偽指令不能定義重名。
六、WORD
WORD偽指令類似于DATE偽指令,只是WORD偽指令定義了一個字類型的符號名,其格式為:
符號名 WORD 表達式
0027= VAL31 WORD 39
0021= PAR7 WORD 21H
一個字由2個字節組成。當然,因為8051匯編語言集沒有字操作,所以程序執行時,只處理字節。WROD偽指令僅僅允許用戶定義一個認為是字的存儲位置。
七、BIT
BIT偽指令定義了一個字位類型的符號名,其格式為:
符號名 BIT 表達式
這里表達式的值是一個位地址,這個偽指令有助于位的地址符號化。
例:
002F= LOG3 BIT 47
0014= Y731 BIT 14H
八、ALTNAME
替換名(ALTNAME)偽指令提供用戶一種手段,以定義一個符號名來替換一個保留字,此后這個答名與被替換的保留字均可等效地用于程序中。任何保留類型的答名均可被替換。替換名偽指令格式為:
ALTNAME 保留字,新名
例:
0002= ALTNAME R2 COUNT
013A EA MOV A,R2
013B E502 MOV A,COUNT
九、DBDB偽指令用于定義一個連續的存儲區,給該存儲區的存儲單元賦值。該偽指令的參數即為存儲單元的值,在表達式中對變元個數沒有限制,只要此條偽指令能容納在源程序的一行內,其格式為:
標號: DB 表達式
只要表達式不是字符串,每一表達式值都被賦給一個字節。計算表達式值時按16位處理,但其結果只取低8位,若多個表達式出現在一個DB偽指令中,它們必須以逗號分開。
表達式中有字符串時,以單引號“'”作分隔符,每個字符占一個字節,字符串不加改變地被存在各字節中,并不將小寫字母轉換成大寫字母。
例如:
DB 00H 01H 03H 46H
DB 'This is a demo!'
十、DW
DW為以字節為單元(十六位二進制)來給一個的存儲區賦值,其格式為:
標號: DW 表達式
例如:
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為定義存儲內容的偽指令,用它定義一個存儲區,并用指定的參數填滿該存儲區。
DS偽指令包含兩個變元,第一個變元定義了存儲區的長度的字節數,在匯編時,匯編程序將跳過這些單元把其它指令匯編在這些字節之后,因此在使用DS偽指令時第一個變元不可活力第二個變元表示在這些單元中真入什么值,第二個變元可以活力活力時這些字節將不處理。下例中0173處有一條DS 9,則空出9個字節,下一第指令被匯編到017C處;在017C處空出1BH個單元,在這些字節中被27H所填充。
DS指令的格式如下:
標號: DS 表達式1,表達式2
表達式1定義了存儲區的長度(以字節為單位)。這個變元不能省略。表達式2是可選擇的,它的值低8位用以填入所定義的存儲區。
若省略則這部分存儲單元不處理。
例:
0000 04 INC A
0001 DS 9
000A 04 INC A
000B DS 1BH,27H
0026 04 INC A
十二、INCLUDE
INCLUDE偽指令用于鏈接源文件,即將一個源文件插入到另一個源文件中。它有一個參數,指出將要插入的文件名,該文件名中可包括驅動器名和路徑名。若文件沒有擴展名,則默認為是ASM。但待插入的文件必須是可以打開的。若文件打開操作失敗,則產生致命錯誤,匯編將停止運行。反之,匯編程序將文件內容讀入并按源代碼處理。當遇到文件結速符時,匯編程序返回到INCLUDE偽指令處繼續身下處理源程序。被插入的文件在程序清單中以“I”開頭。
本宏匯編版本支持級嵌套,可在程序中用INCLUDE偽指令插入任意多個文件,但是,在一般情況下DOS允許打開的文件數量是有限的,如果用戶需要打開較多的文件,則必須在CONFIG.SYS文件中加入FILES=40或更多的值,若超過8級嵌套或打開的文件太多,則產生致命錯誤,匯編中止運行。
INCLUDE偽指令提供了模塊化程序設計手段,在匯編程序處理主程序時,模塊被插入,盡管這不等價于鏈接和裝配可重定位的目標模塊,但它具有類似的功能,被插入的源文件中不應該包含END偽指令,否則,匯編就會提前停止運行,END偽指令只能出現在主程序中。此外,在主程序進行匯編前所有附加的源文件必須通過匯編,產生相應的HEX及LST文件,由于附加的文件沒有END偽指令,因此,附加文件匯編時,匯編程序將顯示:“沒有結束語句”的錯誤,但并不影響與主程序的鏈接。
下面是一個使用INCLUDE偽指令的例子,其主程序的源文件MAIN.ASM為:
;MAIN.ASM
ORG 27H
START:
CLR A
MOV R3,A
INCLUDE MOD1
INC R5
INCLUDE MOD2.ASM
DEC R3
END START
主程序為帶有END偽指令的完整的源文件。程序中有兩INCLUDE偽指令,分別將兩附加的文件MOD1.ASM及MOD2.ASM鏈接到主程序中。以下是這兩個文件。
;MOD1.ASM
MOV R2,#31H
MOV R5,#18H
;MOD2.ASM
MOV R6,#47H
ANL A,#07H
MOV R1,A
注意MOD1.ASM及MOD2.ASM均沒有END指令。
在進行匯編時必須先對MOD1.ASM和MOD2.ASM進行匯編,然后在匯編MAIN.ASM,由于上兩個文件沒有END偽指令,所以在匯編時會出現錯誤提示,不用管它,繼續下面的工作,就可以得到正確的結果。
以下是形成的列表文件:
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)
十三、TITLTITLE偽指令用于在列表文件頁頭建立一個標題,其格式為:
$TITLE 標題行
這里標量行就是將出現在頁頭的標量與通常的字符串定義不同。這里標量行不加引號。匯編從$TITLE之后的第一個可打印字符開始,到回車符之間的字符串作為標量標量的最大長度是60個字符,基標量行省略,則標題行為空行。若TITLE偽指令在一頁,它說明的標量行包含在本頁,否則,標題將出現在下頁頁頭。
十四、PAGEPAGE偽指令用于形成新的一中定義一面的行數。其格式為:
$PAGE 表達式
若表達 式缺省則開始新的一頁,若有表達式,則每頁行數重新定義。匯編開始時頁長為66行。一頁中除出頁外,剩余55行用于打印源程序,這一格式適用于標準打印紙。
如果變元值小于66,頁內可打印的源代碼行將相應減少。頁長最小值為12。若小于12時,每頁內除頁上只打印一行源程序。
頁長變元是16位字節,因而每頁最長可定義到65535行,這時分頁打印變為連續打印,在屏幕顯示程序清單或在卷筒紙上打印程序清單時,常常使用連續打印,如果在啟動匯編時用/N選項,頁長就是65535。
十五、LIST與NOLIST它們的格式為:
$LIST
$NOLIST
LIST偽指令使匯編時主生程序清單,但即使不用該指令,匯編也會自動產生清單。但如果使用了NOLIST偽指令后需要繼續主生清單則必須使用LIST偽指令。
NOLIST偽指令使匯編時不產生清單,所有包含此偽指令及在這條偽指令之后的語句都不進入列表文件。當不需要任何列表文件,并且不需要顯示程序清單時,可以在啟動匯編時不加.L附加項,且在源代碼的第一行加上NOLIST指令。
使用NOLIST偽指令與附加項/L不同之處是NOLIST偽指令可加在源程序中,與LIST偽指令配合使用,使源程序中某些部分不產生清單。而不加附加項/L則不產生任何程序清單。不過,不管有無$NOLIST偽指令,程序在匯編時檢查到的錯誤都將在屏幕上顯示出錯的源代碼行及錯誤信息
其格式為 $NOCODE
NOCODE偽指令使得在匯編時,條件匯編程序結構中那些真值為假的條件不產生清單。有關條件匯編結構在下面介紹。如果沒有這條偽指令,匯編將主生所有條件下的清單,不論其真值是否為真。但是假的條件,不產生目標碼。而NOCODE偽指令使匯編清單中只列出那些由匯編程序用到的部分,因此,當使用NOCODE偽指令時,程序清單與源程序并非逐行對應。
評論
查看更多