9.3.2 Expansion Operator (%)

The expansion operator (%) expands text macros or converts constant expressions into their text representations. It performs these tasks differently in different contexts, as discussed below.

9.3.2.1 The Expansion Operator with Constants

The expansion operator can be used in any context where a text value is expected but a numeric value is supplied. In these contexts, it can be thought of as a conversion operator to convert numeric values to text values.

The expansion operator forces immediate evaluation of a constant expression and replaces it with a text value consisting of the digits of the result. The digits are generated in the current radix (default decimal).

This application of the expansion operator is useful when defining a text macro:

a TEXTEQU <3 + 4> ; a = "3 + 4"

b TEXTEQU %3 + 4 ; b = "7"

When assigning text macros, numeric equates can be used in the constant expressions, but text macros cannot:

num EQU 4 ; num = 4

numstr TEXTEQU <4> ; numstr = <4>

a TEXTEQU %3 + num ; a = <7>

b TEXTEQU %3 + numstr ; b = <7>

The expansion operator can be used when passing macro arguments. If you want the value rather than the text of an expression to be passed, use the expansion operator. Use of the expansion operator depends on whether you want the expression to be evaluated inside the macro on each use, or outside the macro once. The following macro

work MACRO arg

mov ax, arg * 4

ENDM

can be called with these statements:

work 2 + 3 ; Passes "2 + 3"

; Code: mov ax, 2 + 3 * 4 (14)

work %2 + 3 ; Passes 5

; Code: mov ax, 5 * 4 (20)

Notice that because of operator precedence, results can vary depending on whether the expansion operator is used. Sometimes parentheses can be used inside the macro to force evaluation in a particular order:

work MACRO arg

mov ax, (arg) * 4

ENDM

work 2 + 3 ; Code: mov ax, (2 + 3) * 4 (20)

work %2 + 3 ; Code: mov ax, (5) * 4 (20)

This example generates the same code regardless of whether you pass the argument as a value or as text, but in some cases you need to specify how the argument is passed.

The value for a default argument must be text, but frequently you need to give a constant value. The expansion operator is one way to force the conversion. The following statements are equivalent:

work MACRO arg:=<07h>

work MACRO arg:=%07h

The expansion operator also has several uses with macro functions. See Section 9.6.

9.3.2.2 The Expansion Operator with Symbols

When you use the expansion operator on a macro argument, any text macros or numeric equates in the argument are expanded:

num EQU 4

numstr TEXTEQU <4>

work 2 + num ; Passes "2 + num"

work %2 + num ; Passes "6"

work 2 + numstr ; Passes "2 + numstr"

work %2 + numstr ; Passes "6"

The arguments can optionally be enclosed in parentheses. For example, these two statements are equivalent:

work %2 + num

work %(2 + num)

9.3.2.3 The Expansion Operator as the First Character on a Line

The expansion operator has a different meaning when used as the first character on a line. In this case, it instructs the assembler to expand any text macros and macro functions it finds on the rest of the line.

This feature makes it possible to use text macros with directives such as ECHO, TITLE, and SUBTITLE that take an argument consisting of a single text value. For instance, ECHO displays its argument to the standard output device during assembly. Such expansion can be useful for debugging macros and expressions, but the requirement that its argument be a single text value may have unexpected results:

ECHO Bytes per element: %(SIZEOF array / LENGTHOF array)

Instead of evaluating the expression, this line just echoes it:

Bytes per element: %(SIZEOF array / LENGTHOF array)

However, you can achieve the desired result by assigning the text of the expression to a text macro and then using the expansion operator at the beginning of the line to force expansion of the text macro.

temp TEXTEQU %(SIZEOF array / LENGTHOF array)

% ECHO Bytes per element: temp

Note that you cannot get the same results by simply putting the % at the beginning of the first echo line, because % expands only text macros, not numeric equates or constant expressions.

Here are more examples of the use of the expansion operator at the start of a line:

; Assume memmod, lang, and os are passed in with /D option

% SUBTITLE Model: memmod Language: lang Operating System: os

; Assume num defined earlier

tnum TEXTEQU %num

% .ERRE num LE 255, <Failed because tnum !> 255>