|
宏指令是匯編功能的另一種擴(kuò)充。在我們編寫程序時,常常會遇到這種情況:一些程序段它們的結(jié)構(gòu)相同,但在不同情況下使用的參數(shù)不同,這時可以把那變化的參數(shù)定義為形參,采用宏指令的方法來解決。在匯編時,匯編程序?qū)⑻钊胂鄳?yīng)的實(shí)參,把它們逐條匯編并生成到相應(yīng)的程序中去。
一個宏指令是匯編語句的一個代碼段,其中可以包含有形參,所謂形參是指它的值由引用宏指令時定義,在編寫宏指令時它僅僅是一個符號而已。每個宏指令都有一個宏指令名,在程序中可以通過引用它的名字以及給定所需要的參數(shù)使用它。宏指令通在匯編語句的命令中使用,參數(shù)出現(xiàn)在參數(shù)部分中,宏指令每次在程序中引用時,通過實(shí)參對形參的替換,使程序中宏指令中的形參獲得實(shí)際值。一個宏指令必須在它的第一次使用之前被定義。通常,所有的宏指令的定義都集中在程序的首部,宏指令的定義格式如下:
宏指令名 MACRO 形參表
(宏指令體)
ENDM
MACRO和ENDM語句是宏指令定義的標(biāo)志,它們指出了宏指令的首部和尾部。每個MACRO語句必須有一個匹配的ENDM語句。這些語句不使用標(biāo)號。
宏指令名按照匯編程序中的其它符號名約定,宏指令名被加到匯編程序符號表中,并賦給一個宏指令類型。因而它必須有唯一的名字。其名字將包括在匯編程序列表輸出的匯編符號清單中。
形參表是在宏指令定義中使用的形參集合。這些參數(shù)用符號表示,且僅僅在宏指令定義中使用,而不被加到匯編符號表中。它們只能在宏指令中的代碼塊中使用。各個形參在參數(shù)表中應(yīng)該用逗號隔開。宏匯編中,每個宏指令最多可支持40個參數(shù)。但是,參數(shù)表必須與MACFO指令在同一行上,由于每一代碼行最大長度為80個字符,因形參的數(shù)量也受這個條件限制,參數(shù)表是任選的,所以一個宏指令也可以是無參的。
宏指令是程序塊,它可以是任何匯編語言或偽指令,但由于匯編程序不支持嵌套的宏指令,因此,在宏指令體內(nèi)不能再使用宏指令或?qū)ζ渌曛噶钸M(jìn)行定義。形參可以在代碼段語句的任何域中使用,包括標(biāo)號、命令、參數(shù)和注解。形參經(jīng)常被用作為參數(shù),但是也有可以在其它域中使用。
一個宏指令的主要特點(diǎn)是形參的使用。當(dāng)宏指令在程序段中被調(diào)用時,調(diào)用處的實(shí)際參數(shù)替換定義中的形參。因此,宏指令每次被調(diào)用時,通過使用時提供的一個唯一的實(shí)際參數(shù)集,就生成一個唯一的代碼段。一個簡單的宏指令定義如下所示:
ABC MACRO P1,P2,P3
MOV A,P1
MOV R4,P2
P3
DEC R5
ENDM
JK MACRO P1,X5,OPC1,ARG1,ARG2
INC X5
MOV A,P1
OPC1 ARG1,ARG2
ENDM
CLR A
MOV R3,A
ABC R2,#25H,INC R3
NOP
JK @R0,R2,ADD,A,R6
NOP
ABC #4FH,#39H,DEC A
NOP
END
該程序中前部是兩個宏指令定義,前一個宏指令為ABC,第二個為JK。后部為主程序,在主程序中ABC、JK分別被引用。匯編后的列表文件如下:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
08-27-96
ABC MACRO P1,P2,P3
MOV A,P1
MOV R4,P2
P3
DEC R5
ENDM
JK MACRO P1,X5,OPC1,ARG1,ARG2
INC X5
MOV A,P1
OPC1 ARG1,ARG2
ENDM
0000 E4 CLR A
0001 FB MOV R3,A
0002 ABC R2,#25H,INC R3
+0002 EA MOV A,R2
+0003 7C25 MOV R4,#25H
+0005 0B INC R3
+0006 1D DEC R5
0007 00 NOP
0008 JK @R0,R2,ADD,A,R6
+0008 0A INC R2
+0009 E6 MOV A,@R0
+000A 2E ADD A,R6
000B 00 NOP
000C ABC #4FH,#39H,DEC A
+000C 744F MOV A,#4FH
+000E 7C39 MOV R4,#39H
+0010 14 DEC A
+0011 1D DEC R5
0012 00 NOP
0000 END
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-27-96
;%T Symbol Name Type Value
ABC . . . . . . . . . . . . . . M 0000
JK. . . . . . . . . . . . . . . M 0000
;%Z
00 Errors (0000)
在列表文件中,在調(diào)用宏指令處,實(shí)參數(shù)被充填到宏指令的形參處,并把宏指令體擴(kuò)充到程序中形成代碼。在這個例子中實(shí)參不僅代替了指令中的參數(shù)部分,而且還能代替整個指令。文件中最前列帶“+”的語句為引用宏指令擴(kuò)展的部分。宏指令被引用時,參數(shù)表上實(shí)參表應(yīng)與所替代的形參相對應(yīng)。在表中出現(xiàn)的參數(shù)必須用逗號隔開,匯編程序取逗號之間或與第一個逗號之間,或最后一個逗號與行尾之間的任何字符作為實(shí)際參數(shù)。這樣,可以使用多個符號,甚至一個整條指令作為一個參數(shù),只要在數(shù)中沒有逗號就行。一個逗號不能作為一個參數(shù)的一部分被傳遞。匯編程序?qū)V去每個參數(shù)的前面和后面的空格,僅僅保留第一個到最后一個可打印字符。
此外,宏指令的實(shí)際參數(shù)表可以不與形參表完全匹配,即實(shí)際參數(shù)的數(shù)量可以多于或少于形參表中的形參個數(shù)。當(dāng)參數(shù)空缺時,相應(yīng)的形參在宏擴(kuò)展時被取消,如果實(shí)際參數(shù)比形參多,則多余的實(shí)際參數(shù)將被忽略。最后一個在表中間的參數(shù)可以通過在參數(shù)表中間放兩個逗號來賦空值。參見下面的例子。
ABC MACRO P1,P2,P3
MOV A,P1
MOV R4,P2
P3
DEC R5
ENDM
JK MACRO P1,X5,OPC1,ARG1,ARG2
INC X5
MOV A,P1
OPC1 ARG1,ARG2
ENDM
NOP
JK #33H,R3,NOP
SWAP A
NOP
JK R4,R2,ADDC,A,@R1,#66H
NOP
JK #40H,R4,,DEC R2
NOP
END
宏指令的另一個特點(diǎn)是形參可以被用作一個標(biāo)號,如果一個形參被用作一個標(biāo)號,當(dāng)引用宏指令時,實(shí)參將成為標(biāo)號。這就要求每次宏指令調(diào)用時,該實(shí)參不能相同。以避免標(biāo)號重復(fù)定義錯誤。例:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
08-27-96
ABC MACRO P1,P2,P3
MOV A,P1
MOV R4,P2
P3
DEC R5
ENDM
JK MACRO P1,X5,OPC1,ARG1,ARG2
INC X5
MOV A,P1
OPC1 ARG1,ARG2
ENDM
0000 00 NOP
0001 JK #33H,R3,NOP
+0001 0B INC R3
+0002 7433 MOV A,#33H
+0004 00 NOP ,
0005 C4 SWAP A
0006 00 NOP
0007 JK R4,R2,ADDC,A,@R1,#66H
+0007 0A INC R2
+0008 EC MOV A,R4
+0009 37 ADDC A,@R1
000A 00 NOP
000B JK #40H,R4,,DEC R2
+000B 0C INC R4
+000C 7440 MOV A,#40H
+000E 1A DEC R2,
000F 00 NOP
0000 END
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-27-96
;%T Symbol Name Type Value
ABC . . . . . . . . . . . . . . M 0B0D
JK. . . . . . . . . . . . . . . M 0000
;%Z
00 Errors (0000)
若在宏指信中使用標(biāo)號,由于這些標(biāo)號不是形參,所以不會被實(shí)參所替代。這樣,在程序中多次引用是否會出現(xiàn)標(biāo)號重復(fù)呢?在作宏匯編時,匯編程序會在所有標(biāo)號尾部增加一個唯 一的四位數(shù),以使多次引用時標(biāo)號不會重復(fù)。例:
LMAC MACRO P1,P2,L1
ANL A,P1
JZ L1
ORL A,P2
L1: MOV @R1,A
INC R1
ENDM
MOV R1,#2AH
MOV A,#65H
LMAC R3,#0F0H,R3ANDA0
MOV A,#23H
LMAC R5,#07H,R5ANDA0
NOP
END
程序中有二個標(biāo)號MATCH1及NOMATCH,宏指令被二次引用,經(jīng)匯編后其列表文件如下:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
08-27-96
LMAC MACRO P1,P2,L1
ANL A,P1
JZ L1
ORL A,P2
L1: MOV @R1,A
INC R1
ENDM
0000 792A MOV R1,#2AH
0002 7465 MOV A,#65H
0004 LMAC R3,#0F0H,R3ANDA0
+0004 5B ANL A,R3
+0005 6002 JZ R3ANDA0
+0007 44F0 ORL A,#0F0H
+0009 F7 R3ANDA0: MOV @R1,A
+000A 09 INC R1
000B 7423 MOV A,#23H
000D LMAC R5,#07H,R5ANDA0
+000D 5D ANL A,R5
+000E 6002 JZ R5ANDA0
+0010 4407 ORL A,#07H
+0012 F7 R5ANDA0: MOV @R1,A
+0013 09 INC R1
0014 00 NOP
0000 END
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-27-96
;%T Symbol Name Type Value
LMAC. . . . . . . . . . . . . . M 0000
R3ANDA0 . . . . . . . . . . . . L 0009
R5ANDA0 . . . . . . . . . . . . L 0012
;%Z
00 Errors (0000)
若在宏指令中使用標(biāo)號,由于這些標(biāo)號不是形參,所以不會被實(shí)參所替代。這樣,在程序中多次引用是否會出現(xiàn)標(biāo)號重復(fù)呢,這一點(diǎn)宏匯編程序已作了考慮,在作宏匯編時,匯編程序會在所有標(biāo)號尾部增加一個唯一的四位數(shù),以使多次引用時標(biāo)號不會重復(fù)。下面的例子說明了多次引用宏指令時內(nèi)部標(biāo)號的處理。
例:
CHK MACRO N1,N2
XRL A,N1
JZ MATCH1
XRL A,N2
JNZ NOMATCH
ADD A,#15H
MATCH1:
ADD A,#7
MOV R4,A
NOMATCH:
MOV R5,A
ENDM
MOV A,#23H
CHK #65H,R3
MOV A,@R0
CHK R2,#23H
NOP
END
程序中有二個標(biāo)號MATCH1及NOMATCH。宏指令被二次引用。經(jīng)匯編后其列表文件如下:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
08-27-96
CHK MACRO N1,N2
XRL A,N1
JZ MATCH1
XRL A,N2
JNZ NOMATCH
ADD A,#15H
MATCH1:
ADD A,#7
MOV R4,A
NOMATCH:
MOV R5,A
ENDM
0000 7423 MOV A,#23H
0002 CHK #65H,R3
+0002 6465 XRL A,#65H
+0004 6005 JZ MATCH10001
+0006 6B XRL A,R3
+0007 7005 JNZ NOMATCH0001
+0009 2415 ADD A,#15H
+ MATCH10001:
+000B 2407 ADD A,#7
+000D FC MOV R4,A
+ NOMATCH0001:
+000E FD MOV R5,A
000F E6 MOV A,@R0
0010 CHK R2,#23H
+0010 6A XRL A,R2
+0011 6006 JZ MATCH10002
+0013 6423 XRL A,#23H
+0015 7005 JNZ NOMATCH0002
+0017 2415 ADD A,#15H
+ MATCH10002:
+0019 2407 ADD A,#7
+001B FC MOV R4,A
+ NOMATCH0002:
+001C FD MOV R5,A
001D 00 NOP
0000 END
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-27-96
;%T Symbol Name Type Value
CHK . . . . . . . . . . . . . . M 0000
MATCH10001. . . . . . . . . . . L 000B
MATCH10002. . . . . . . . . . . L 0019
NOMATCH0001 . . . . . . . . . . L 000E
NOMATCH0002 . . . . . . . . . . L 001C
;%Z
00 Errors (0000)
從列表文件中我們可以看到,匯編程序已對宏指令中的標(biāo)號作了處理,在第一次引用時,宏指令中的標(biāo)號MATCH1及NOMATCH分別衩擴(kuò)展為MATCH1001及NOMATCH0001,而第二次被引用時相應(yīng)的標(biāo)號被擴(kuò)展為MATCH1002及NOMATCH0002,從而避免在同一程序中標(biāo)號的重復(fù)。
“&”在宏指令中作為連接操作符!埃Α蓖ǔ3霈F(xiàn)在帶有形參的字符串中。為了區(qū)分字符串中哪些字符是形參,需要在形參與固定字符間加入“&”例如:
CON MACRO X1,X2,SI,L1
MOV R2,#X1
MOV R2,#X1
ADD A,#X1+5-X2
DB 'STRING&SI&'
JNZ LAB&L1
LAB&L1:
XRL A,R3
ENDM
CLR A
CON 23H,65H,SPECIAL,57
END
列表文件如下:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
08-27-96
CON MACRO X1,X2,SI,L1
MOV R2,#X1
MOV R2,#X1
ADD A,#X1+5-X2
DB 'STRING&SI&'
JNZ LAB&L1
LAB&L1:
XRL A,R3
ENDM
0000 E4 CLR A
0001 CON 23H,65H,SPECIAL,57
+0001 7A23 MOV R2,#23H
+0003 7A23 MOV R2,#23H
+0005 24C3 ADD A,#23H+5-65H
+0007 53 54 52 DB 'STRINGSPECIAL'
+000A 49 4E 47 53 50 45 43 49 41 4C
+0014 7000 JNZ LAB57
+ LAB57:
+0016 6B XRL A,R3
0000 END
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-27-96
;%T Symbol Name Type Value
CON . . . . . . . . . . . . . . M 0000
LAB57 . . . . . . . . . . . . . L 0016
;%Z
00 Errors (0000)
在算術(shù)表達(dá)式中所有的加數(shù)否需要連接操作符,這是因?yàn)樗阈g(shù)操作符本身具有符號與數(shù)之間的自然分隔符作用。立即操作數(shù)(由#符號引導(dǎo))可以用一個空格把它與一個形參分開,在這種情況下也不需要字符“&”。
最后,所有的宏指令所支持的功能可以合并起來使用,從而組成一個相當(dāng)復(fù)雜的宏指令,例如宏指令可以包括條件結(jié)構(gòu),或者宏指令可以是一個條件結(jié)構(gòu)的一部分,但是宏指令不可以嵌套,條件結(jié)構(gòu)不可以超過宏指令的邊界。即宏指令必須完全在一個條件結(jié)構(gòu)中,或者條件結(jié)構(gòu)必須在一條宏指令中?梢酝ㄟ^形參來決定條件表達(dá)式的值。當(dāng)宏指令衩調(diào)用時,傳遞的實(shí)際參數(shù)值將決定每一條指令的生成代碼。如:
CON MACRO C1,C2,P1,P2,P3
MOV A,P1
IF C1
INC R3
MOV R4,A
ENDIF
IF C2
MOV R5,P2
ADDC A,P3
ELSE
MOV R1,P2
XRL A,R3
ENDIF
MOV @R1,A
ENDM
CLR A
MOV R3,#2AH
CON 0,0,#23H,#65H,R6
END
列表文件如下:
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 1
08-27-96
CON MACRO C1,C2,P1,P2,P3
MOV A,P1
IF C1
INC R3
MOV R4,A
ENDIF
IF C2
MOV R5,P2
ADDC A,P3
ELSE
MOV R1,P2
XRL A,R3
ENDIF
MOV @R1,A
ENDM
0000 E4 CLR A
0001 7B2A MOV R3,#2AH
0003 CON 0,0,#23H,#65H,R6
+0003 7423 MOV A,#23H
+ IF 0
+ INC R3
+ MOV R4,A
+ ENDIF
+ IF 0
+ MOV R5,#65H
+ ADDC A,R6
+ ELSE
+0005 7965 MOV R1,#65H
+0007 6B XRL A,R3
+ ENDIF
+0008 F7 MOV @R1,A
0000 END
The Cybernetic Micro Systems 8051 Family Assembler, Version 3.03 Page 2
08-27-96
;%T Symbol Name Type Value
CON . . . . . . . . . . . . . . M 0000
;%Z
00 Errors (0000)
程序中宏指令帶有條件結(jié)構(gòu),并可以通過形參C1確定判別條件。
-
第七節(jié) 匯編程序的出錯信息
一個匯編程序往往不可能一次編寫就完全正確,總會有一些錯誤存在,MASM51在匯編時可以對源程序中存在的一些語法錯誤判別,并給出出錯信息,出錯信息將出現(xiàn)在屏幕上,并被寫入到列表文件中去,我們可以根據(jù)出錯信息對照源程序進(jìn)行修改。
一般出錯信息的格式為:
描述性信息(aaaa)
描述性信息向用戶提供錯誤的類型,以提供用戶分析與糾正錯誤。aaaa是四位十六進(jìn)制數(shù)字,它指出的是上一個錯誤出現(xiàn)的地址,以便 用戶在較長的列表文件中找到上一個錯誤的所在。
錯誤數(shù)量的報(bào)告記錄在列表文件的最后,其格式為:
XX Errors(0000)
其中XX為十六進(jìn)制數(shù)表示的錯誤數(shù)量。
宏匯編能提供的錯誤信息有:
(1)Undefined symbol
表示在源程序的語句中使用的符號未被定義,實(shí)際上可能是符號名拼錯或在源程序中缺少一個該符號的等價(jià)指令。
(2)Missing Argumentin Expression
表示表達(dá)式中算術(shù)運(yùn)算符后面沒有操作數(shù)。
(3)Unblaanced Parentheses
每一個左括號必須與一個右括號配套,如果表達(dá)式中多余或缺少括號,將出現(xiàn)上述提示信息。
(4)ILLEGAL EQUATE
表示把兩個不同類型的量用等價(jià)偽指令連在一起,例如保留字的值1寄存器名等,它們不允許用等值偽指令來改變。
(5)BADLY ROFMED ARGUMENT
表示一個數(shù)字參數(shù)使用了非法的數(shù)字。例如二進(jìn)制中出現(xiàn)除0與1以外的其他數(shù)字。
(6)MISSING END STATEMENT
源文件結(jié)束處沒有END語句。源文件的結(jié)束處必須有一個END語句。
(7)LABEL NAME CONFLICTS WITH SYMBOL NAME
標(biāo)號名與符號名相同。
(8)MULTIPLY DEFINED LABEL
相同標(biāo)號多次出現(xiàn)。
(9)LABEL ADDRESS CHANGED ON PASS 2
標(biāo)號的值在兩次掃描中改變。這個錯誤往往是在源程序的不同處用了同一個標(biāo)號名,只要用字處理軟件查找這個標(biāo)號,就可以改正。
(10)UNRECOGNIZED STATEMENT OR UNDEFINED ARGUMENT
表示有未定義的指令、或源代碼。出現(xiàn)一個語法類型的錯誤。該類錯誤可能由拼錯命令名產(chǎn)生或由于記錯命令的用法產(chǎn)生,改正起來較為簡單。
(11)ADDRESS OUT OF RANGE
轉(zhuǎn)移地址超出該語句的范圍,例如SJMP轉(zhuǎn)移地址超過+127~-128的范圍,另外JB、JNB、JZ、JNZ等指令也容易發(fā)生類錯誤。如果是SJMP、AJMP、ACALL等指令發(fā)生錯誤,則改正較為容易,只要將指令改為范圍較在的即可,如將SJMP改為AJMP,將AJMP改為LJMP,將ACLL改為LCALL等,如果是JZ、JB、JNZ、JNB等指令發(fā)生此類錯誤,則要使用一些技工技巧,如下面程序1所示,NEXT標(biāo)號已超出了JZ指令作用的范圍,則可以改成程序2,使用一個中間標(biāo)號NEXT1,然后從NEXT1跳轉(zhuǎn)到NEXT處。
例:
.
.
JB NEXT1
.
.
.
NEXT1:
AJMP NEXT
.
.
(12)VALUE OUT OF RANGE
用一個非法的值來說明一個語句。 |