【发布时间】:2019-11-19 20:18:12
【问题描述】:
我想知道 MASM 中的 macros 和 procedures 有什么区别?
如果我调用 macro 而不是 procedure 来执行完全相同的操作,那么程序将执行的操作或汇编程序将如何组装我的代码有什么不同吗?
如果不是,我可能想了解为什么macros 存在?
谢谢。
【问题讨论】:
-
宏的存在使内联变得容易(例如,使用不同的寄存器选择)
我想知道 MASM 中的 macros 和 procedures 有什么区别?
如果我调用 macro 而不是 procedure 来执行完全相同的操作,那么程序将执行的操作或汇编程序将如何组装我的代码有什么不同吗?
如果不是,我可能想了解为什么macros 存在?
谢谢。
【问题讨论】:
宏只是文本替换。因此,每当您“调用”宏时,该调用将在编译时被宏的全部内容替换。当您调用一个过程时,通常只有该过程的一个实例,因此您将分支到程序中的不同位置。
考虑以下示例:
.586
.model flat, stdcall
option casemap :none
.code
; Multiply the argument by 3/2
Mul3_2 MACRO reg
lea reg,[reg + reg*2]
shr reg,1
ENDM
; Multiply the argument by 3/2 and return in eax
Mul3_2Proc PROC arg:DWORD
mov eax,[arg]
lea eax,[eax + eax*2]
shr eax,1
ret
Mul3_2Proc ENDP
main PROC
Mul3_2 eax
Mul3_2 ebx
invoke Mul3_2Proc,eax ; Equivalent to push eax / call Mul3_2Proc
invoke Mul3_2Proc,ebx
main ENDP
END main
如果我们让 MASM 的预处理器扩展我们的宏,我们会得到:
.586
.model flat, stdcall
option casemap :none
.code
; Multiply the argument by 3/2 and return in eax
Mul3_2Proc PROC arg:DWORD
mov eax,[arg]
lea eax,[eax + eax*2]
shr eax,1
ret
Mul3_2Proc ENDP
main PROC
lea eax,[eax + eax*2]
shr eax,1
lea ebx,[ebx + ebx*2]
shr ebx,1
invoke Mul3_2Proc,eax ; Equivalent to push eax / call Mul3_2Proc
invoke Mul3_2Proc,ebx
main ENDP
END main
如您所见,在我们使用Mul3_2 宏的两个地方,该宏的内容已被插入,reg 替换为我们作为参数传递给宏的任何内容。宏本身不再存在于我们的代码中,因为它已经达到了它的目的。
另一方面,我们调用Mul3_2Proc 过程的两次事件保持不变。在运行时,每个位置都会跳转 (call) 到 Mul3_2Proc,然后在完成后,return 会返回调用站点。
【讨论】:
在我看来,宏返回一个值
所以你可以写:
mov ax, myMacro( ...arguments... )
类似于 VB.NET 中的 Function 与 Sub(或 C# 中的 void)
【讨论】:
mov 到 AX 的源操作数.即作为 C 预处理器之类的文本替换。 没有类似于 VB.NET 中的函数或非 void C 函数。宏 = 宏体的内联(如果它由指令组成)。宏和函数可以返回值(在任何你想要的寄存器中)。