Ax51汇编程序支持的宏处理语言(MPL)是一种字符串替换工具,使您能够编写可修复的代码块(宏)并将其插入源文本中的一个或多个位置。
宏处理器查看源文件的方式与汇编程序不同。
MPL 的一个有价值的功能是条件组装。在宏中使用条件汇编会导致紧凑的配置相关代码,这对于良好的程序设计至关重要。此外,它还生成尽可能紧凑的代码。
注意:
在汇编程序中使用 MPL 宏相对容易。
所有 MPL 预定义和用户定义的函数都必须以元字符开头。默认情况下,元字符是百分比 (‘%’) 字符。但是,元字符可能会被元炭MPL 函数。
所有 MPL 预定义和用户定义的函数都必须以元字符开头。默认情况下,元字符是百分号 (‘%’)。但是,元字符可能会被元炭MPL 函数。
定义 MPL 函数创建一个宏。定义函数的语法为:
%DEFINE (macro-name <[>parameter-list<]>) (macro-body)
%*DEFINE (macro-name <[>parameter-list<]>) (macro-body)
% | 是元字符用于指示宏函数 |
---|---|
* | 指定在文本模式下展开宏。 |
macro-name | 是宏的名称。宏名称最多可以包含 31 个字符,并且必须以 A-Z、a-z、_ 或 ?。后续字符可以是 A-Z、A-Z、_、?,或 0-9。 |
parameter-list | 是括在分隔符内并用分隔符分隔的参数列表。 |
macro-body | 是展开以替换宏名称和参数列表的文本。它可能包含对其他宏的调用。如果是这样,这些宏也会展开。定义宏时,在调用宏之前,宏主体中包含的那些宏调用不会展开。 |
注意:
没有参数(或参数)的宏定义如下:
%*DEFINE (macro-name) (macro-body)
该定义需要宏名称和在调用宏时展开的宏主体。例如,以下宏定义:
%*DEFINE (my_asdf) (asdf)
当调用时:
%my_asdf
扩展到:
asdf
具有参数(或参数)的宏定义如下:
%*DEFINE (macro-name <[>parameter-list<]>) (macro-body)
参数列表列出了传递给宏的形式参数。参数列表中的参数在宏主体中用于在调用宏时填充值。这允许您设计为许多操作生成代码的泛型宏。
参数列表中的参数由唯一标识符(您选择的)指定,这些标识符由宏分隔符(通常是括号和逗号)分隔。参数列表括在括号内,各个参数用逗号分隔。这只是一个约定,而不是一个要求。
参数列表规范的唯一要求是宏参数的传递方式和定义宏时使用的分隔符相同。例如,以下宏定义中的参数列表:
%*DEFINE (BMOVE (src, dst, cnt)) (...)
是(src,dst,cnt)。若要调用此宏,必须使用相同的分隔符指定参数。例如:
%BMOVE (1, 2, 3)
但是,没有理由必须将参数括在括号内或必须用逗号分隔。例如:
%*DEFINE (BMOVE src dst cnt) (...)
若要调用此宏,必须按如下方式指定参数:
%BMOVE 1 2 3
宏主体中的参数用参数名称表示,前面是元字符(在上面的示例中为 %src、%dst 和 %cnt)。以下宏定义显示了一个更完整的示例
%*DEFINE (BMOVE (src, dst, cnt)) LOCAL lab (
MOV R2,#%cnt
MOV R1,#%src
MOV R0,#%dst
%lab: MOV A,@R1
MOV @R0,A
INC R0
INC R1
DJNZ R2,lab
)
参数可以在宏主体中以任意次数和任意顺序使用。如果参数与宏同名并在宏正文中使用,则会展开该参数(而不是调用宏)。
如果宏与其中一个参数同名,则无法在宏主体中调用该宏,因为这会导致无限递归。
下面定义了一个名为 BMOVE 的宏,该宏采用三个参数:源、目标和计数。宏生成的代码将任意数量的字节从内存的一部分复制到另一部分。
%*DEFINE (BMOVE (src, dst, cnt)) LOCAL lab (
MOV R2,#%cnt
MOV R1,#%src
MOV R0,#%dst
%lab: MOV A,@R1
MOV @R0,A
INC R0
INC R1
DJNZ R2,lab
)
若要调用此宏,请指定元字符后跟宏名称和参数列表(如果有)。实际参数必须具有平衡的文本,并且可以包含对其他宏的调用。例如,可以按如下方式调用上述宏:
%BMOVE (array1,array2,10)
宏扩展为:
MOV R2,#10
MOV R1,#array1
MOV R0,#array2
??LAB?0: MOV A,@R1
MOV @R0,A
INC R0
INC R1
DJNZ R2,??LAB?0
注意:
MPL 宏可能包括作为分支目标的本地标签。固定的标签名称会导致错误,如果多次调用宏。发生这种情况是因为同一标签名称在源文件中只能使用一次。此问题可以通过使用局部符号来解决。本地宏符号附加一个唯一的序列号,每次调用宏时,该数字都会递增。
必须在宏定义行中声明本地符号:
%*DEFINE (macro-name <[>parameter-list<]>) <[>LOCAL local-list<]> (macro-body)
其中,本地列表是宏的本地符号的列表(用逗号或空格分隔)。
局部符号在宏宏体中使用时必须以元字符为前缀。例如:
%*DEFINE (BMOVE (src, dst, cnt)) LOCAL lab (
MOV R2,#%cnt
MOV R1,#%src
MOV R0,#%dst
%lab: MOV A,@R1
MOV @R0,A
INC R0
INC R1
DJNZ R2,lab
)
MPL 宏处理器将平衡文本字符串解释为数值表达式,当它们用于以下 MPL 函数的参数时:
数值表达式的处理方式如下:
MPL 数值表达式的算术是使用有符号 16 位整数执行的。关系运算符的结果为 0 (FALSE) 或 1 (TRUE)。
可以使用下表中指定的后缀和字符以十六进制(以 16 为基数)、十进制(以 10 为基数)、八进制(以 8 为基数)和二进制(以 2 为基数)指定数字:
MPL 宏处理器支持 ASCII 字符串,这些字符串可能包含一个或两个用单引号 (“'”) 括起来的字符。例如:
注意:
宏处理器无法访问汇编程序的符号表。因此,在宏处理过程中,标签以及 SET 和 EQU 符号的值是未知的。但是,您可以使用设置宏函数来定义宏符号。