In MASm (Microsoft Macro Assembler) and other assembly languages, conditional control flow directives allow the programmer to modify the flow of program execution based on certain conditions. These directives are closely related to conditional jump and branch instructions and are used to change the order of execution based on flag states or specific conditions.
These directives typically work with conditional assembly constructs and flags, enabling the programmer to selectively include or exclude code during assembly, depending on the condition.
Let's explore the conditional control flow concepts and the relevant directives in MASM:
MASM provides several conditional assembly directives that allow you to control the inclusion of code during assembly time. These directives work based on evaluation of conditions at the assembly level, not runtime. They are commonly used to manage different code paths, optimize for specific configurations, or target different platforms.
IF Directive
The IF directive allows you to conditionally include or exclude a block of code based on a condition evaluated during assembly. The condition is usually a comparison of constants or expressions.
Syntax:
IF condition
; code block to include if condition is true
ENDIF
Example:
.IF DEBUG
; Code for debugging (only included if DEBUG is defined)
mov ah, 09h
lea dx, msg
int 21h
.ENDIF
In this example, the block of code will only be included in the assembly if the condition DEBUG is true or defined. If DEBUG is undefined, this block is ignored.
ELSE Directive
The ELSE directive provides an alternative block of code that is assembled when the IF condition is false. It's used in combination with IF.
Syntax:
IF condition
; code block if condition is true
ELSE
; code block if condition is false
ENDIF
Example:
.IF DEBUG
; Debugging code
mov ah, 09h
lea dx, msg
int 21h
.ELSE
; Release code
mov ah, 4Ch
int 21h
.ENDIF
ELSEIF Directive
The ELSEIF directive allows multiple conditions to be tested in sequence. It works similarly to ELSE, but with an additional conditional check before the ELSE block.
Syntax:
IF condition1
; code block if condition1 is true
ELSEIF condition2
; code block if condition2 is true
ELSE
; code block if all previous conditions are false
ENDIF
Example:
.IF DEBUG
; Debugging code
mov ah, 09h
lea dx, msg
int 21h
.ELSEIF RELEASE
; Release code
mov ah, 4Ch
int 21h
.ELSE
; Default case code
; Maybe show an error message or something else
mov ah, 09h
lea dx, errorMsg
int 21h
.ENDIF
In this case, DEBUG code is assembled if DEBUG is defined, RELEASE code if RELEASE is defined, and an error message if neither condition is met.
WHILE Directive
The WHILE directive allows a block of code to be included in assembly if a specific condition is true. This directive allows for repeating code based on a condition being met, which can be useful for loops or repetitive sections.
Syntax:
WHILE condition
; block of code to include while condition is true
ENDW
Example:
.WHILE COUNT > 0
; Some code that gets assembled while COUNT is greater than 0
dec COUNT
.ENDW
This assembly code will keep including the block as long as the COUNT variable is greater than 0.
While the previous directives control the flow at the assembly-time level, MASM (and assembly languages in general) also allows conditional jumps that control the runtime execution flow based on processor flags or values in registers. These jumps are commonly used for implementing loops, if-else constructs, and branching logic.
These jump instructions alter the flow of execution at runtime, based on the state of certain flags, such as Zero Flag (ZF), Sign Flag (SF), Carry Flag (CF), etc.
JE / JZ (Jump if Equal / Jump if Zero)
Jumps if the Zero Flag (ZF) is set, which typically indicates equality (result of a comparison or subtraction is zero).
Example:
cmp ax, bx ; Compare AX with BX
je EqualLabel ; Jump to EqualLabel if AX == BX
JNE / JNZ (Jump if Not Equal / Jump if Not Zero)
Jumps if the Zero Flag (ZF) is clear, meaning the values are not equal.
Example:
cmp ax, bx ; Compare AX with BX
jne NotEqualLabel ; Jump if AX != BX
JG / JNLE (Jump if Greater / Jump if Not Less or Equal)
Jumps if the signed comparison indicates that the first value is greater than the second.
Example:
cmp ax, bx
jg GreaterLabel ; Jump if AX > BX (signed comparison)
JL / JNGE (Jump if Less / Jump if Not Greater or Equal)
Jumps if the signed comparison indicates that the first value is less than the second.
Example:
cmp ax, bx
jl LessLabel ; Jump if AX < BX (signed comparison)
JGE / JNL (Jump if Greater or Equal / Jump if Not Less)
Jumps if the signed comparison indicates that the first value is greater than or equal to the second.
Example:
cmp ax, bx
jge GreaterOrEqualLabel ; Jump if AX >= BX
JC / JNC (Jump if Carry / Jump if No Carry)
Jumps if the Carry Flag (CF) is set (for unsigned comparisons) or clear.
Example:
cmp ax, bx
jc CarrySetLabel ; Jump if carry flag is set (AX < BX unsigned)
JZ / JNZ (Jump if Zero / Jump if Not Zero)
These jumps are used for checking if two values are equal or not.
Example:
cmp ax, bx
jz EqualValue ; Jump if AX == BX (Zero Flag is set)
jnz NotEqualValue ; Jump if AX != BX (Zero Flag is clear)
The conditional control flow directives are particularly useful during debugging or when creating software that must run in different environments or with different configurations.
For example, if you have code that is only useful for debugging or logging, you can wrap it in conditional directives:
.IF DEBUG
; Debugging code
lea dx, debugMessage
mov ah, 09h
int 21h
.ELSE
; Regular code
lea dx, normalMessage
mov ah, 09h
int 21h
.ENDIF
In this example, if the DEBUG symbol is defined during assembly, the code for debugging (e.g., printing a debug message) is included. Otherwise, the regular code is included.
IF, ELSE, WHILE, and ENDIF are used to control what code gets assembled based on certain conditions. They help customize the code for different configurations or environments.JE, JNE, JG, JL, JC, etc., control the flow of execution during runtime based on the results of comparisons and flags.Conditional control flow allows assembly programmers to write more adaptable code, enabling different execution paths based on values or compilation parameters.
Open this section to load past papers