Thursday, 24 November 2011

INTRODUCTION TO MACROS


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