C macros offer a convenient way to insert assembly code into C 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)
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. And 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 statements on the same line to the right of the macro invocation. Without the closing brace, QuickC cannot tell where assembly code stops, and it sees 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 QuickC ignores everything after the comment, all the way to the end of the logical line. To prevent errors, use 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 expressions.
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.