C macros offer a convenient way to insert assembly code into your source code, but they demand extra care because a macro expands into a single logical line. To create trouble-free macros, follow these rules:
Enclose the __asm block in braces.
Put the __asm keyword in front of each assembly instruction.
Use old-style C comments ( /* comment */ ) instead of assembly-style comments ( ; comment ) or single-line C comments ( // comment ).
To illustrate, the following example defines a simple macro:
#define BEEP __asm \
/* Beep sound */ \
{ \
__asm mov ah, 2 \
__asm mov dl, 7 \
__asm int 21h \
}
At first glance, the last three __asm keywords seem superfluous. They are needed, however, because the macro expands into a single line:
__asm /* Beep sound */ { __asm mov ah, 2 __asm mov dl, 7 __asm int 21h }
The third and fourth __asm keywords are needed as statement separators. The only statement separators recognized in __asm blocks are the newline character and __asm keyword. Since a block defined as a macro is one logical line, you must separate each instruction with __asm.
The braces are essential as well. If you omit them, the compiler can be confused by C or C++ statements on the same line to the right of the macro invocation. Without the closing brace, the compiler cannot tell where assembly code stops, and it sees C or C++ statements after the __asm block as assembly instructions.
Summary: Use C comments in __asm blocks written as macros.
Assembly-style comments that start with a semicolon (;) continue to the end of the line. This causes problems in macros because the compiler ignores everything after the comment, all the way to the end of the logical line. The same is true of single-line C or C++ comments ( // comment ). To prevent errors, use old-style C comments ( /* comment */ ) in __asm blocks defined as macros.
An __asm block written as a C macro can take arguments. Unlike an ordinary C macro, however, an __asm macro cannot return a value. So you cannot use such macros in C or C++ expressions.
Be careful not to invoke macros of this type indiscriminately. For instance, invoking an assembly-language macro in a function declared with the __fastcall con-vention may cause unexpected results. (See “Using and Preserving Registers”.)
Summary: You can convert MASM macros to C macros.
Note that some MASM-style macros can be written as C macros. Below is
a MASM macro that sets the video page to the value specified in the page
argument:
setpage MACRO page
mov ah, 5
mov al, page
int 10h
ENDM
The following code defines setpage as a C macro:
#define setpage( page ) __asm \
{ \
__asm mov ah, 5 \
__asm mov al, page \
__asm int 10h \
}
Both macros do the same job.