调用宏的方法是把宏名插入到程序中,后面可能跟有宏的实参。宏调用语法如下:
Macroname 必须是源代码中在此之前被定义宏的名称。每个实参都是文本值,用以替换宏的一个形参。实参的顺序要与形参一致,但是两者的数量不须相同。如果传递的实参数太 多,则汇编器会发出警告。如果传递给宏的实参数太少,则未填充的形参保持为空。
上一节《MACRO和ENDM伪指令》中定义了宏 mPutChar。调用 mPutChar 时,可以传递任何字符或 ASCII 码。下面的语句调用了 mPutChar,并向其传递了字母 “A”:
汇编器的预处理程序将这条语句展开为下述代码,以列表文件的形式展开如下:
左侧的 1 表示宏展开的层次,如果在宏的内部又调用了其他的宏,那么该值将会增加。下面的循环显示了字母表中前 20 个字母:
该循环由预处理程序在下面的代码中展开(源列表文件中可见),其中,宏调用在其展开的前面:
提示:与过程相比,宏执行起来更快,其原因是过程的 CALL 和 RET 指令需要额外的开销。但是,使用宏也有缺点:重复使用大型宏会增加程序的大小,因为,每次调用宏都会在程序中插入宏代码的一个新副本。
调试使用了宏的程序相当具有挑战性。程序汇编之后,检查其列表文件(扩展名为 .LST) 以确保每个宏都按照程序员的要求展开。然后,在Visual Studio 调试器中启动该程序,在调试窗口点击右键,从弹出菜单中选择Go to Disassemblyo每个宏调用的后面都紧 跟其生成代码。示例如下:
mWriteAt 15,10,"Hi there"
push edx
mov dh, 0Ah
mov dl, 0Fh
call _Gotoxy@0 (401551h)
pop edx
push edx
mov edx,offset ??0000 (405004h)
call _WriteString@0 (401D64h)
pop edx
由于 Irvine32 链接库使用的是 STDCALL 调用规范,因此函数名用下划线 (_) 开始。