ITEEDU

灵活的运用带参数的宏可以十分方便地编写程序,这是因为宏的参数不仅可以是指令的操作数,而且还可以是具体的指令,甚至于是某个指令的一部分。比如下面这个例子就是采用指令作为宏的参数:

         ope  MACRO     pa1,pa2,pa3,pa4
                mov       ax,pa1
              	pa2	pa3
              	pa4
              ENDM

如果我们这样调用宏OPE:
OPE  200H,DEC,AX,CWD
那么编译之后这个宏将被展开为:
mov  ax,200h
dec  ax
cwd

参数中的200H与AX是指令操作数,而DEC与CWD却是实实在在的指令。如果我们换用其它指令,比如说这样调用OPE:
OPE  CX,PUSH,AX,CLC

这时编译程序就会把OPE宏展开为:
mov  ax,cx
push  ax
clc

可见这个宏可以称为千变万化了。

宏OPE的变化还是很普通的,下面这个例子所显示出的变化就更吸引人了:
compare MACRO pa1,pa2,pa3,pa4
cmp pa1,pa2
j&pa3 pa4
ENDM

如果这样来调用宏COMPARE:
COMPARE AX,200H,NZ,EXIT

则编译之后这个宏会被展开为:
cmp   ax,200h
jnz   exit

参数中的"NZ"其实是作为指令"JNZ"的一部分给出的。另一部分"J"在宏的内部。这里要注意字符"&"不可以丢掉。与OPE宏一样,如果把参数做些变化,则这个宏就会被展开其它样子。比如:
COMPARE AX,BX,LE,NEXT

展开之后就是:
cmp   ax,bx
jle   next

带参数的宏还有其它一些活用的例子,限于篇幅不再详细讨论了。下面给出了一个宏汇编程序实例,这个程序可以将一个字符串中的大小写字母互相转换,将此程序编译连接之后大家可以自己用DEBUG观察反汇编结果,以研究源程序中应用宏的技巧。

DEMO.ASM
       print  MACRO     p1	;输出字符串的宏
              mov       dx,offset p1
              mov       ah,09
              int       21h
              ENDM
			
        comp  MACRO     pa1,pa2,pa3	;用于进行数据比较的宏
              cmp       al,pa1	;将参数PA1与AL寄存器中的数据比较
              j&pa2     next&pa3	;根据PA2给出的条件及PA3给出的部分
              ENDM      ;目的地址进行转移
			
        code  segment
              assume    cs:code,ds:code
              org       100h
        main  proc      near
              print     msg	;输出转换前的字符串MSG
			
              mov       si,offset msg	;SI、DI寄存器指向字符串
              mov       di,si
      next1:
              lodsb     ;取得一个字符
              comp      24h,z,3	;将其与'$'进行比较,若相等转NEXT3
              comp      20h,le,2	;将其与空格相比较,若小于或等于空格符
			;转NEXT2
              xor       al,20h	;将大小写字母互换
      next2:
              stosb     ;将转换后的字符存回字符串
              jmp       next1	;转NEXT1继续
      next3:
              print     msg	;输出转换后的字符串
              ret       ;结束进程
         msg  db        'Best	Wish To YOU',0dh,0ah,24h
        main  endp
        code  ends
              end       main

除了宏汇编技术之外,条件汇编也是一种高级的汇编技术。所谓条件汇编,指得是把源程序分成几个部分,编译时如果具备了某个条件则编译其中一个部分,如果相应条件不具备则编译其它部分。所以说,条件实际上是提供给编译程序处理的。

在具体讨论条件汇编技术之前我们先来看一看示例程序CHILD.ASM:

CHILD.ASM

        code  segment
              assume    cs:code
              org       100h
        main  proc      near
              mov       ah,09
              mov       dx,offset msg
              int       21h
              int       20h
         msg  db        'Hello	,cowboy!',0dh,0ah,07h,24h
        main  endp
        code  ends
              end       main

这个程序的功能很简单,它只是在屏幕上显示一行文字--"Hello,cowboy!"。现在如果假设有一位很任性的小姑娘看到了这个程序显示的文字,她十分希望这个程序能显示出"Hello,cowgirl!",那么这个程序就要做些修改了。

说句老实话,修改程序比编写程序还要烦人,象这样的小程序当然看不出什么,对于一些比较大的程序来说修改工作可不比编写工作轻松。我们之所以强调要把程序中频繁使用的数据用"EQU"伪指令定义成常量,为的就是修改起来方便一些。