INTRODUCTION TO MACROS
A
macro is a symbolic name given to one or more assembly language
statements. A macro may be used to generate instructions or data
definitions.
Syntax of macro definition (for MASM and TASM):
macro_name MACRO d1, d2, . . . , dn
statement1
statement2
. . .
statementk
ENDM
where d1, d2, . . . , dn is an optional list of dummy parameters. Dummy parameters are temporary variables; they are not declared by data definition directives (DB, DW, DD, . . .). They can be used as input as well as output parameters.
A
macro definition can appear anywhere in an assembly language program
before the END directive; however for MASM and TASM the definition of a
macro must appear before a call to that macro and a macro definition
cannot appear inside another macro definition. It is usual to place all
macro definitions at the beginning of a program before the segment
definitions.
A
macro definition is not assembled until the macro is called. Each macro
call is replaced by the statements in the macro definition (i.e., each
call expands the macro).
Syntax of a macro call:
macro_name a1, a2, . . . , aN
where a1, a2, . . . , aN is an optional
list of actual arguments. An actual argument can be an immediate value
(i.e., a constant), a variable, or a register name. Argument names may
be duplicates of other names (labels, variables, etc.).
A
macro call for a macro designed to generate assembly language
instructions must appear in a code segment. A macro call for a macro
designed to generate data definitions must appear in a portion of a
program where it will not be treated as an instruction by the assembler.
Example of macro definitions and calls to those macros:
DISPLAY_CHAR MACRO CHAR
PUSH AX
PUSH DX
MOV AH , 02H
MOV DL , CHAR
INT 21H
POP DX
POP AX
ENDM
. . .
.CODE
. . .
DISPLAY_CHAR ‘A’
. . .
MOV BL , ‘X’
DISPLAY_CHAR BL
. . .
|
READ_STRING MACRO BUFFER_NAME
PUSH AX
PUSH DX
MOV DX , OFFSET BUFFER_NAME
MOV AH, 0AH
INT 21H
POP DX
POP AX
ENDM
. . .
.DATA
INPUT_BUFFER DB 71, 72 DUP(?)
. . .
.CODE
. . .
READ_STRING INPUT_BUFFER
. . .
|
READ_CHAR MACRO
;; Read character with echo
MOV AH , 01H
INT 21H
ENDM
.CODE
. . .
READ_CHAR
. . .
|
CRLF MACRO
;; Move cursor to beginning of new line
PUSH AX
PUSH DX
MOV AH , 02H
MOV DL , 0DH
INT 21H
MOV DL , 0AH
INT 21H
POP DX
POP AX
ENDM
. . .
.CODE
. . .
CRLF
. . .
|
DISPLAY_STRING MACRO STRING
PUSH AX
PUSH DX
MOV AH , 09H
MOV DX , OFFSET STRING
INT 21H
POP DX
POP AX
ENDM
. . .
.DATA
PROMPT1 DB ‘ID# ?’, 0DH , 0AH , ‘$’
PROMPT2 DB ‘NAME ?’ , 0DH , 0AH , ‘$’
. . .
. CODE
. . .
DISPLAY_STRING PROMPT1
. . .
DISPLAY_STRING PROMPT2
. . .
|
SWAP MACRO WORD1 , WORD2
;;Exchanges two word memory operands
PUSH AX
MOV AX , WORD1
XCHG AX , WORD2
MOV WORD1 , AX
POP AX
ENDM
. . .
.DATA
VAR1 DW 2FE4H
VAR2 DW 5000H
. . .
.CODE
. . .
SWAP VAR1 , VAR2
. . .
|
A macro may be called from the data segment to allocate memory:
ALLOC MACRO ARRAY_NAME , NUMBYTES
ARRAY_NAME DB NUMBYTES DUP(?)
ENDM
.DATA
ALLOC ARRAY1 , 20
ALLOC ARRAY2 , 50
. . .
the calls will generate:
ARRAY1 DB 20 DUP(?)
ARRAY2 DB 50 DUP(?)
|
DISPLAY_BUFFER MACRO BUFFER
PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV AH , 40H
MOV BX , 01H
MOV CH , 00H
MOV CL , BUFFER[1]
LEA DX , BUFFER[2]
INT 21H
POP DX
POP CX
POP BX
POP AX
ENDM
|
Invalid macro calls:
A macro call is invalid if the macro expansion for that call produces an invalid assembly language statement.
Example, consider:
MOVW MACRO WORD1 , WORD2
;; Copies one word to another
MOV WORD1 , WORD2
ENDM
.DATA
VAR1 DW 12ACH
VAR2 DW 6200H
. . .
The call:
MOVW VAR1 , VAR2
generates the code:
MOV VAR1 , VAR2
which is invalid, because it is a direct memory to memory transfer.
The call:
MOVW VAR2 , BL
generates the code:
MOV VAR2 , BL
which is invalid because the operands are of different sizes.
Register actual parameters
Care
must be taken when using register actual parameters; a register actual
parameter should not conflict with the usage of that register in the
macro.
Consider: DISPLAY_CHAR MACRO CHAR
PUSH AX
PUSH DX
MOV AH , 02H
MOV DL , CHAR
INT 21H
POP DX
POP AX
ENDM
. . .
.CODE
. . .
MOV AH , ‘K’
DISPLAY_CHAR AH
. . .
The call: DISPLAY_CHAR AH
expands to: PUSH AX
PUSH DX
MOV AH , 02H
MOV DL , AH
INT 21H
POP DX
POP AX
thus K is not displayed because its ASCII code is replaced by 02H before the invocation of INT 21H.
A macro calling another macro
For MASM and TASM a macro can contain calls to other previously defined macros. A macro X may contain calls to another macro Y defined later
in the program provided that the call to the macro X appears after both
macro definitions. Thus, provided all macro definitions appear before
the segment definitions, the macros may be written in any order.
Example:
DISPLAY_CHAR MACRO CHAR
PUSH AX
PUSH DX
MOV AH , 02H
MOV DL , CHAR
INT 21H
POP DX
POP AX
ENDM
CRLF MACRO
DIPLAY_CHAR 0DH
DISPLAY_CHAR 0AH
ENDM
A macro calling a procedure
A macro can contain calls to one or more procedures.
Example:
MDSPLY_STRING MACRO STRING
PUSH DX
MOV DX , OFFSET STRING
CALL DSPLY_STRING
POP DX
ENDM
. . .
.DATA
MESSAGE1 DB ‘ICS 232 ’, 0DH, 0AH, ‘$’
MESSAGE2 DB ‘ICS 301 ’, 0DH, 0AH, ‘$’
. . .
.CODE
. . .
MAIN PROC
. . .
MDSPLY_STRING MESSAGE1
. . .
MDSPLY_STRING MESSAGE2
. . .
MAIN ENDP
DSPLY_STRING PROC
PUSH AX
MOV AH, 09H
INT 21H
POP AX
RET
DSPLY_STRING ENDP
END MAIN
The LOCAL directive for generating unique labels in a macro expansion
A
macro with loops or jumps contains one or more labels. If such a macro
is called more than once in a program, duplicate labels appear when the
macro calls are expanded, resulting in an assembly error. Similarly a
macro containing a data definition, if called more than once, will
result in an assembly error. This problem can be avoided by using local labels or local identifiers in the macro. To declare them, we use the LOCAL directive, whose syntax is:
LOCAL list-of-labels
where
list-of-labels is a list of labels and/or identifiers separated by
commas. The LOCAL directive must be the first statement after the MACRO
directive. Not even a comment can separate a MACRO directive and a LOCAL
directive.
Every
time a macro is expanded, MASM or TASM assigns a unique label to each
local label or identifier in each expansion. These labels are of the
form:
??d1d2d3d4
where di
is a hexadecimal digit. Thus the labels range from ??0000 to ??FFFF.
Since a local label or identifier is assigned the next unique label from
the list ??0000 - ??FFFF in each macro expansion, a local label or
identifier may have the same name as a global label or a global
identifier (i.e. a label or identifier defined outside a macro).
Example:
MIN2 MACRO FIRST , SECOND
LOCAL END_IF
;; Puts minimum of two signed words in the AX register
MOV AX , FIRST
CMP AX , SECOND
JLE END_IF
MOV AX , SECOND
END_IF:
ENDM
This
macro returns, in the AX register, the minimum of arguments
corresponding to the parameters FIRST and SECOND. The contents of the
register AX are compared to the parameter SECOND, if AX is less or equal
to SECOND a jump is taken to the label END_IF; otherwise the
instruction MOV AX , SECOND is executed. (Jumps, Conditional jumps, and Loop instructions will be discussed in detail in the next chapter)
Assuming that call:
MIN2 VAR1 , VAR2
to the above macro is the first macro call in the program, it will expand to:
MOV AX , VAR1
CMP AX , VAR2
JLE ??0000
MOV AX , VAR2
??0000:
and assuming that the call:
MIN2 VAR4 , VAR2
to
the above macro is the third macro call in the program, after a second
macro call to a different macro in which four local labels where
defined, the call will expand to:
MOV AX , VAR4
CMP AX , VAR2
JLE ??0005
MOV AX , VAR2
??0005:
Visibility of global identifiers in a macro
A
global identifier is an identifier defined in the program body outside
all macros. An instruction in a macro can reference any global
identifier in the program in which the macro is defined. However, an
instruction defined outside a macro cannot reference a local identifier.
References within a macro to an identifier that is both local to that
macro and global to the program within which the macro appears will be
resolved in favor of its local definition.
TOWNS MACRO
LOCAL TOWN, DONE
PUSH AX
PUSH DX
PUSH DS
MOV AX, CS
MOV DS, AX
MOV DX , OFFSET TOWN ; local TOWN
CALL DISPLAY_STRING ; DISPLAY_STRING is a global identifier
POP DS
POP AX
MOV DX , OFFSET COUNTRY ; COUNTRY is a global identifier
CALL DISPLAY_STRING
POP DX
JMP DONE
TOWN DB 'DHAHRAN', 0DH , 0AH , '$'
DONE:
ENDM
.MODEL SMALL
.STACK 0400H
.DATA
TOWN DB 'RIYADH', 0DH , 0AH , '$'
COUNTRY DB 'SAUDI ARABIA', 0DH , 0AH , '$'
.CODE
MAIN PROC
MOV AX, @DATA
MOV DS , AX
MOV DX , OFFSET TOWN ;global TOWN
CALL DISPLAY_STRING
TOWNS ; a macro call
MOV AX , 4C00H
INT 21H
MAIN ENDP
DISPLAY_STRING PROC
PUSH AX
MOV AH , 09H
INT 21H
POP AX
RET
DISPLAY_STRING ENDP
END MAIN
The output of the previous program is:
RIYADH
DHAHRAN
SAUDI ARABIA
PLACING MACRO DEFINITIONS IN THEIR OWN FILE
Macro
definitions can be placed in their own file. Common extensions to the
text file containing macro definitions are LIB, H, and MAC. We use the
INCLUDE directive to indicate that an assembly language program file
will include a file that contains external macro definitions. Example:
INCLUDE C:\PROGS\MACROS.LIB
A
file containing macro definitions may contain macros that are not
required in a particular assembly language program. To remove these
unwanted macros in the program we first INCLUDE all the macros and then
use the PURGE directive to remove the unwanted ones. For example suppose
a macro file MACROS.H contains macros PROMPT and DIVIDE which are not
required in the current assembly language program, we write:
INCLUDE C:\MACROS.H
PURGE PROMPT , DIVIDE
MACROS versus PROCEDURES
Both
procedures and macros can improve a program when, if they are not used,
the program would contain repeated occurrences of a group of
instructions. The decision of whether to use a macro or procedure is
often based on one or more of the following considerations:
1. Assembly time
A
program containing macros usually takes longer to assemble than a
similar program containing procedures, because it takes time to expand
the macros.
2. Execution time
The
code generated by a macro expansion generally executes faster than a
procedure call, because there is no overhead of the CALL and RET
instructions.
3. Program size
A
program with macros is generally larger than a similar program with
procedures, because each macro call inserts a new copy of its code in
the program.
4. Parameter passing
Parameter passing mechanism of macros is more convenient than parameter passing mechanisms of procedures.
SYSTEM-DEFINED MACROS
MASM 6.0 and latter versions supports a number of system-defined macro calls. Examples of such macro calls are:
.STARTUP and .EXIT
.STARTUP
macro call in a program with a data segment directs the assembler to
generate instructions that, when executed, set the DS register to
address the data segment.
.EXIT macro call directs the assembler to generate the instructions that, when executed, will return control to DOS. The call .EXIT generates:
MOV AH , 4CH
INT 21H
and the call .EXIT 0 generates:
MOV AL , 0
MOV AH , 4CH
INT 21H
DEFAULT VALUES FOR MACRO ARGUMENTS
In MASM 6.0 and above, an argument to a macro may have a default value.
Example: DISPLAY_STRING MACRO string , length , flag := < 0 >
. . .
ENDM
The
dummy parameter flag := < 0 > indicates that if the third actual
argument is omitted from a call to this macro, then the default value of
0 is assumed for that argument.
0 comments:
Post a Comment