This chapter describes how to define and use macros. You can use the same macro language regardless of your target processor.
NOTE The macro language is similar to Hitachi assembler syntax with some extensions.
This chapter includes the following topics:
This section, which describes how to define macros, includes the following topics:
A macro definition is one or more assembly statements that define:
You can use the following methods to define a macro:
Defining a macro with the .macro directive Defining a macro with the #define directive
One way to define a macro is to use the .macro directive. Listing 4.1 shows the syntax of a macro definition using the .macro directive.
Macro definition syntax using the .macro directive:
name: .macro [ parameter ] [ ,parameter ] ... macro_body .endm
The .macro directive indicates the first line of a macro definition. Every macro definition must end with the .endm directive.
Table 4.1 describes the syntax elements shown in Listing 4.1.
Macro syntax descriptions for .macro directive:
| Syntax Element |
Description |
|---|---|
You can specify a conditional assembly block within a macro. Based on the result of the tested condition, you can use the .mexit directive to stop macro execution before the assembler reaches the .endm directive.
Listing 4.2 shows a macro that uses the .mexit directive.
Conditional macro using the .mexit directive:
# define a macro addto .macro dest,val .if val==0 no-op .mexit # execution goes to the statement # immediately after the .endm directive .elseif val==1 # use compact instruction inc dest .mexit # execution goes to the statement # immediately after the .endm directive .endif # if val is not equal to either 0 or 1, # add dest and val add dest,val # end macro definition .endm
Listing 4.3 shows assembly language code that calls the addto macro shown in Listing 4.2.
Assembly code that calls the addto macro:
# specify an executable code section .text xor eax,eax # call the addto macro addto eax,0 addto eax,1 addto eax,2 addto eax,3
Listing 4.4 shows the expanded addto macro calls shown in Listing 4.3.
xor eax,eax nop inc eax add eax,2 add eax,3
Another way to define a macro is to use the #define directive. Listing 4.5 shows the syntax of a macro definition using the #define directive.
Macro definition syntax using the #define directive:
#define name [ (parms) ] assembly_statement [ ; ] [ \ ] assembly_statement [ ; ] [ \ ]
assembly_statement
parms ::= parameter [ ,parameter ]...
NOTE If you specify parameters for a macro, you must enclose the parameters in parentheses.
Table 4.2 describes the syntax elements shown in Listing 4.5.
Macro syntax descriptions for #define directive:
You can refer to parameters directly by name. Listing 4.6 shows the setup macro, which moves an integer into a register and branches to the label _final_setup.
setup: .macro name mov eax, name call _final_setup .endm
Listing 4.7 shows one way to invoke the setup macro.
#define VECT 0 setup VECT
Listing 4.8 shows how the assembler expands the setup macro after the preceding call.
move eax, VECT call _final_setup
When you refer to named macro parameters in the macro body, you can precede or follow the macro parameter with &&. This lets you embed the parameter in a string. For example, Listing 4.9 shows the smallnum macro, which creates a small float by appending the string E-20 to the macro argument.
smallnum: .macro mantissa .float mantissa&&E-20 .endm
Listing 4.10 shows one way to invoke the smallnum macro.
smallnum 10
Listing 4.11 shows how the assembler expands the smallnum macro after the preceding call.
.float 10E-20
When you use a local label (a label that begins with @) in a macro, the scope of the label is limited to the expansion of the macro. For more information, see "Local labels".
You can generate unique labels and equates within a macro with the following characters: \@. Each time you invoke the macro, the assembler generates a unique symbol of the form ??nnnn, such as ??0001 or ??0002.
You refer to unique labels and equates (those that use \@) in your code with the same methods used for regular labels and equates. The assembler replaces the \@ sequence with a unique numeric string and increments the value of the string each time you invoke the macro.
Listing 4.12 shows a macro that uses unique labels and equates.
my_macro: .macro foo\@ = my_count my_count .set my_count + 1 add ebx, foo\@ jmp label\@ add eax, ebx label\@: nop .endm
Listing 4.13 shows a call to the my_macro macro twice (with my_count initialized to 0).
my_count .set 0 my_macro my_macro
Listing 4.14 shows the expanded my_macro code after the calls in Listing 4.13.
foo??0000 = my_count my_count .set my_count + 1 add ebx, foo??0000 jmp label??0000 add eax, ebx label??0000 nop foo??0001 = my_count my_count .set my_count + 1 add ebx, foo??0001 jmp label??0001 add eax, ebx label??0001 nop
Referring to the Number of Arguments
To refer to the number of non-null arguments passed to a macro, use the special symbol narg. You can use it only during macro expansion.
Invoking Macros
To invoke a macro, use its name in your assembler listing.
When invoking a macro, you must separate parameters with commas. To pass a parameter that includes a comma, enclose the parameter in angle brackets.
For example, Listing 4.15 shows a macro named pattern, which repeats a pattern of bytes passed to it the number of times specified in the macro call.
pattern: .macro times,bytes
.rept times
.byte bytes
.endr
.endm
Listing 4.16 shows a statement that calls pattern, passing a parameter that includes a comma.
Calling a macro with an argument that contains commas:
.data
halfgrey: pattern 4,<0xAA,0x55>
The call in Listing 4.16 generates the same data as the code shown in Listing 4.17.
Alternate way to generate a repeating pattern of bytes:
halfgrey: .byte 0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55