[Chapter Eight][Previous] [Next] [Art of Assembly][Randall Hyde]
Art of Assembly: Chapter Eight
- 8.13 - Conditional Assembly
- 8.13.1 - IF Directive
- 8.13.2 - IFE directive
- 8.13.3 - IFDEF and IFNDEF
- 8.13.4 - IFB, IFNB
- 8.13.5 - IFIDN, IFDIF, IFIDNI, and IFDIFI
8.13 Conditional Assembly
MASM provides a very powerful conditional assembly facility. With conditional assembly, you can decide, based on certain conditions, whether MASM will assemble the code. There are several conditional assembly directives, the following section covers most of them.
It is important that you realize that these directives evaluate their expressions at assembly time, not at run time. The if
conditional assembly directive is not the same as a Pascal or C "if" statement. If you are familiar with C, the #ifdef
directive in C is roughly equivalent to some of MASM's conditional assembly directives.
MASM's conditional assembly directives are important because they let you generate different object code for different operating environments and different situations. For example, suppose you want to write a program that will run on all machines but you would like to optimize the code for 80386 and later processors. Obviously, you cannot execute 80386 code on an 8086 processor, so how can you solve this problem?
One possible solution is to determine the processor type at run time and execute different sections of code in the program depending on the presence or absence of a 386 or later CPU. The problem with this approach is that your program needs to contain two code sequences - an optimal 80386 sequence and a compatible 8086 sequence. On any given system the CPU will only execute one of these code sequences in the program, so the other sequence will be wasting memory and may have adverse affects on any cache in the system.
A second possibility is to write two versions of the code, one that uses only 8086 instructions and one that uses the full 80386 instruction set. During installation, the user (or the installation program) selects the 80386 version if they have an 80386 or later processor. Otherwise they select the 8086 version. While this marginally increases the cost of the software since it will require more disk space, the program will consume less memory while running. The problem with this approach is that you will need to maintain two separate versions of the program. If you correct a bug in the 8086 version of the code, you will probably need to correct that same bug in the 80386 program. Maintaining multiple source files is a difficult task.
A third solution is to use conditional assembly. With conditional assembly, you can merge the 8086 and 80386 versions of the code into the same source file. During assembly, you can conditionally choose whether MASM assembles the 8086 or the 80386 version. By assembling the code twice, you can produce an 8086 and an 80386 version of the code. Since both versions of the code appear in the same source file, the program will be much easier to maintain since you will not have to correct the same bug in two separate source files. You may need to correct the same bug twice in two separate code sequences in the program, but generally the bug will appear in two adjacent code sequences, so it is less likely that you will forget to make the change in both places.
MASM's conditional assembly directives are especially useful within macros. They can help you produce efficient code when a macro would normally produce sub-optimal code. For more information about macros and how you can use conditional assembly within a macro, see "Macros" on page 400.
Macros and conditional assembly actually provide "a programming language within a programming language." Macros and conditional assembly let you write programs (in the "macro language") that write segments of assembly language code for you. This introduces an independent way to generate bugs in your application programs. Not only can a bug develop in your assembly language code, you can also introduce bugs in your macro code (e.g., conditional assembly), that wind up producing bugs in your assembly language code. Keep in mind that if you get too sophisticated when using conditional assembly, you can produce programs that are very difficult to read, understand, and debug.
8.13.1 IF Directive
The if
directive uses the following syntax:
if expression
<sequence of statements>
else ;This is optional!
<sequence of statements>
endif
MASM evaluates expression. If it is a non-zero value, then MASM will assemble the statements between the if
and else
directives
(or endif
, if the else
isn't present). If the expression evaluates to zero (false) and an else
section is present, MASM will assemble the statements between the else
directive and the endif
directive. If the else
section is not present and expression evaluates to false, then MASM will not assemble any of the code between the if
and endif
directives.
The important thing to remember is that expression has to be an expression that MASM can evaluate at assembly time. That is, it must evaluate to a constant. Manifest constants (equates) and values that MASM's type operators produce are commonly found in if
directive expressions. For example, suppose you want to assemble code for two different processors as described above. You could use statements like the following:
Processor = 80386 ;Set to 8086 for 8086-only code
.
.
.
if Processor eq 80386
shl ax, 4
else ;Must be 8086 processor.
mov cl, 4
shl ax, cl
endif
There are other ways to accomplish this same thing. MASM provides built-in variables that tell you if you are assembling code for some specific processor. More on that later.
8.13.2 IFE directive
The ife
directive is used exactly like the if
directive, except it assembles the code after the ife
directive only if the expression evaluates to zero (false), rather than true (non-zero).
8.13.3 IFDEF and IFNDEF
These two directives require a single symbol as the operand. Ifdef
will assemble the associated code if the symbol is defined, Ifndef
will assemble the associated code if the symbol isn't defined. Use else
and endif
to terminate the conditional assembly sequences.
These directives are especially popular for including or not including code in an assembly language program to handle certain special cases. For example, you could use statements like the following to include debugging statements in your code:
ifdef DEBUG
<place debugging statements here>
endif
To activate the debugging code, simply define the symbol DEBUG
somewhere at the beginning of your program (before the first ifdef
referencing DEBUG
). To automatically eliminate the debugging code, simply delete the definition of DEBUG
. You may define DEBUG
using a simple statement like:
DEBUG = 0
Note that the value you assign to DEBUG
is unimportant. Only the fact that you have defined (or have not defined) this symbol is important.
8.13.4 IFB, IFNB
These directives, useful mainly in macros (see "Macros" on page 400) check to see if an operand is blank (ifb
) or not blank (ifnb
). Consider the following code:
Blank textequ <>
NotBlank textequ <not blank>
ifb Blank
<this code will assemble>
endif
ifb NotBlank
<this code will not>
endif
The ifnb
works in an opposite manner to ifb
. That is, it would assemble the statements above that ifb
does not and vice versa.
8.13.5 IFIDN, IFDIF, IFIDNI, and IFDIFI
These conditional assembly directives take two operands and process the associated code if the operands are identical (ifidn
), different (ifdif
), identical ignoring case (ifidni
), or different ignoring case (ifdifi
). The syntax is
ifidn op1, op2
<statements to assemble if <op1> == <op2>>
endif
ifdif op1, op2
<statements to assemble if <op1> != <op2>>
endif
ifidni op1, op2
<statements to assemble if <op1> == <op2>>
endif
ifdifi op1, op2
<statements to assemble if <op1> != <op2>>
endif
The difference between the IFxxx
and IFxxxI
statements above is that the IFxxxI
statements ignore differences in alphabetic case when comparing operands.
-
8.13 - Conditional Assembly
- 8.13.1 - IF Directive
- 8.13.2 - IFE directive
- 8.13.3 - IFDEF and IFNDEF
- 8.13.4 - IFB, IFNB
- 8.13.5 - IFIDN, IFDIF, IFIDNI, and IFDIFI
Art of Assembly: Chapter Eight - 26 SEP 1996
[Chapter Eight][Previous] [Next] [Art of Assembly][Randall Hyde]
Number of Web Site Hits since Jan 1, 2000: