汇编语言宏的特性
1) 规定形参
利用 REQ 限定符,可以指定必需的宏形参。如果被调用的宏没有实参与规定形参相匹配,那么汇编器将显示出错消息。如果一个宏有多个规定形参,则每个形参都要使用 REQ 限定符。下面是宏 mPutChar,形参 char 是必需的:
mPutchar MACRO char:REQ push eax mov al,char call WriteChar pop eax ENDM
2) 宏注释
宏定义中的注释行一般都出现在每次宏展开的时候。如果希望忽略宏展开时的注释,就在它们的前面添加双分号 (;;)。示例如下:mPutchar MACRO char:REQ push eax ;; 提示:char 必须包含 8 个比特 mov al, char call WriteChar pop eax ENDM
3) ECHO 伪指令
在程序汇编时,ECHO 伪指令写一个字符串到标准输出。下面的 mPutChar 在汇编时会显示消息“Expanding the mPutChar macro” :mPutchar MACRO char:REQ ECHO Expanding the mPutchar macro push eax mov al,char call WriteChar pop eax ENDMVisual Studio 2012 的控制台窗口不会捕捉 ECHO 伪指令的输出,除非在编写程序时将其设置为生成详细输出。设置方法如下:从 Tool 菜单选择 Options,选择 Projects and Solutions,选择 Build and Run,再从 MSBuild project build output verbosity 下拉列表中选择 Detailed。或者打开一个命令提示符并汇编程序。
首先,执行如下命令,调整 Visual Studio 当前版本的路径:
"C:\Program Files\Microsoft Visual Studio 11.0\VC\bin\vcvars32"
然后,键入如下指令,其中 filename.asm 是程序的源代码文件名:ml.exe /c /I "c:\Irvine" filename.asm
4) LOCAL 伪指令
宏定义中常常包含了标号,并会在其代码中对这些标号进行自引用。例如,下面的宏 makeString 声明了一个变量 string,且将其初始化为字符数组:makestring MACRO text .data string BYTE text,0 ENDM假设两次调用宏:
makeString "Hello"
makeString "Goodbye"
makeString "Hello"
1 .data
1 string BYTE "Hello",0
makeString "Goodbye"
1 .data
1 string BYTE "Goodbye",0 ;错误!
使用 LOCAL
为了避免标号重命名带来的问题,可以对一个宏定义内的标号使用 LOCAL 伪指令。若标号被标记为 LOCAL,那么每次进行宏展开时,预处理程序就把标号名转换为唯一的标识符。下面是使用了 LOCAL 的宏 makeString:makeString MACRO text LOCAL string .data string BYTE text,0 ENDM假设和前面一样,也是两次调用宏,预处理程序生成的代码会将每个string替换成唯一 的标识符:
makeString "Hello"
1 .data
1 ??0000 BYTE "Hello",0
makeString "Goodbye"
1 .data
1 ??0001 BYTE "Goodbye",0
5) 包含代码和数据的宏
宏通常既包含代码又包含数据。例如,下面的宏mWrite在控制台显示文本字符串:mWrite MACRO text LOCAL string ;;local号 .data ;;定义字符串 string BYTE text,0 .code push edx mov edx, OFFSET string call WriteString pop edx ENDM下面的语句两次调用宏,并向其传递不同的字符串文本:
mWrite "Please enter your first name"
mWrite "Please enter your last name"
mWrite "Please enter your first name"
1 .data
1 ??0000 BYTE "Please enter your first name",0
1 .code
1 push edx
1 mov edx, OFFSET ??0000
1 call WriteString
1 pop edx
mWrite "Please enter your last name"
1 .data
1 ??0001 BYTE "Please enter your last name", 0
1 .code
1 push edx
1 mov edx, OFFSET ??0001
1 call Writestring
1 pop edx
6) 宏嵌套
被其他宏调用的宏称为被嵌套的宏 (nested macro)。当汇编器的预处理程序遇到对被嵌套宏的调用时,它会就地展开该宏。传递给主调宏的形参也将直接传递给它的被嵌套宏。提示:使用模块方法创建宏。保持它们的简短性,以便将它们组合到更复杂的宏内。这样有助于减少程序中的复制代码量。
【示例】下面的宏 mWritein 写一个字符串文本到控制台,并添加换行符。它调用宏 mWrite 和 Crlf 过程:
mWriteln MACRO text mWrite text call Crlf ENDM形参 text 被直接传递给 mWrite。假设用下述语句调用 mWriteln:
mWriteln "My Sample Macro Program"
在结果代码展开,语句旁边的嵌套级数(2)表示被调用的是一个嵌套宏:
mWriteln "My Sample Macro Program"
2 .data
2 ??0002 BYTE "My Sample Macro Program",0
2 .code
2 push edx
2 mov edx,OFFSET ??0002
2 call WriteString
2 pop edx
1 call Crlf