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.
No comments:
Post a Comment