CS 221 Lab #12 -- Intro. to Macros Defining and Using Macros For each symbolic instruction that you code, the assembler generates one machine-language instruction. On the other hand, for each coded statement in a high-level language such as C++ or Visual BASIC, the compiler may generate many machine-language instructions. In this regard, you can think of a high-level language as consisting of a set of macro statements. The assembler has facilities that you can use to define macros. You define a unique name for the macro, along with the set of assembly language instructions that the macro is to generate. Then, wherever you need to code the set of instructions, simply code the name of the macro, and the assembler automatically generates your defined instructions. Macros are useful for the following purposes: To simplify and reduce the amount of repetitive coding. To reduce errors caused by repetitive coding. To make an assembly language program more readable. Examples of functions that may be implemented by macros are input/output operations that load registers and perform interrupts, conversions of ASCII and binary data, multiword arithmetic operations, mouse initialization, and string-handling routines. You may catalog macros in a library where they are available to every program. A program may use a macro once (such as initializing segment addresses) or many times (such as displaying data). A library typically also contains cataloged procedures. The choice of coding an operation as a macro or as a procedure depends largely on these factors: A macro generally executes faster because there is no need to call and return. A procedure, on the other hand. generally results in a smaller program because the code appears only once. In general, a macro is used where it is not coded many times in a program and the requirement is fairly simple. Here is the basic format of a macro definition: macro name MACRO [parameter-list] [instructions] ENDM ;Define macro ;Body of macro ;End of macro The MACRO directive on the first line tells the assembler that the instructions that follow up to ENDM, are to be part of a macro definition. The ENDM (“end macro”) directive ends the macro definition. The instructions between MACRO and ENDM comprise the body of the macro definition. To include a macro within a program, you first define it or copy it from a macro library. The macro definition appears before the coding of any segment. SIMPLE MACRO DEFINITIONS Let’s first examine a simple macro definition that initializes segment registers for an .EXE program: INITZ MACRO ;Define macro MOV AX, @data ;Body of MOV DS,AX ;macro MOV ES,AX ;definition ENDM ;End of macro The name of this macro is INITZ. The data items referenced in the macro definition— @data, AX, DS, and ES—must be defined elsewhere in the program or must otherwise be known to the assembler. You may subsequently use the macro instruction INITZ in the code segment where you want to initialize the registers. When the assembler encounters the macro instruction INITZ, it scans its table of symbolic instructions and, failing to find an entry, checks for macro instructions. Because the program contains a definition of the macro INITZ. the assembler substitutes the body of the definition, generating the instructions—the macro expansion. A program would use the macro instruction INITZ only once, although other macros are designed to be used any number of times, and each time the assembler generates the macro expansion. As well, here’s the definition of a second macro named FINISH that handles normal exiting from a program: FINISH MACRO MOV AX,4C00H INT 21H ENDM ;Define macro ;Request ;end of processing ;End of macro The program below provides a source listing of an assembled program that defines and uses both INITZ and FINISH. ; your name goes here TITLE MACR1 Simple macro definitions INITZ MACRO MOV AX,@data MOV DS,AX MOV ES,AX ENDM ;Define macro ;Initialize ;segment ;registers ;End macro FINISH MACRO MOV AX,4C00H INT 21H ENDM ;Define macro ;End processing ;End macro ;----------------------------------------MODEL SMALL .186 .STACK 54 .DATA DB ‘Test of macro’, 13, 10, ‘$’ MSG BEGIN .CODE PROC FAR INITZ MOV AH, 09H LEA DX,MSG INT 21H FINISH BEGIN ENDP END BEGIN ;Macro instruction ;Request display ;Message Create the source file, assemble it and save your source and listing file. Note that macro definitions, when assembled, do not generate any object code; it is the macro expansions that generate object code. As well, a macro expansion does not print directives like ASSUME or PAGE that are coded in the macro definition. It’s hardly worth bothering to define a macro that is to be used only once, but you could catalog the macro in a library for use with all programs. USING PARAMETERS IN MACROS To make a macro more flexible, you can define parameters in the operand as dummy arguments. The following macro definition named PROMPT provides for the use of INT 21 H function 09H to display messages: PROMPT MACRO MESSGE MOV AH, 09H LEA DX,MESSGE INT 21H ENDM ;Dummy argument ;End of macro When using this macro instruction, you have to supply the name of the message, which references a data area terminated by a dollar sign. Also, the macro could contain instructions that push and pop the used registers AH and DX. A dummy argument in a macro definition tells the assembler to match its name with any occurrence of the same name in the macro body. For example, the dummy argument MESSGE is also an operand in the LEA instruction. Suppose that the program defines a prompt named MESSAGE2 as MESSAGE2 DB ‘Enter the date as mm/dd/yy’,’$’ You now want to use the macro instruction PROMPT to display MESSAGE2. To this end. supply the name MESSAGE2 as a parameter: PROMPT MESSAGE2 The parameter (MESSAGE2) in the macro instruction matches the dummy argument (MESSGE) in the original macro definition. The assembler has already matched the argument in the original macro definition with the operand in the LEA statement. It now substitutes the parameter(s) of the macro instruction MESSAGE2 with the dummy argument, MESSGE. in the macro definition. The assembler substitutes MESSAGE2 for the occurrence of MESSGE in the LEA instruction and would substitute it for any other occurrence of MESSGE. Edit the source file created earlier to make use of the PROMPT macro as the file with a different name. Reassemble the file and save the source and listing file. A dummy argument may contain any valid name, including a register name such as CX. You may define a macro with any number of dummy arguments. separated by commas. up to column 120 of a line (depending on the assembler version). The assembler substitutes parameters of the macro instruction for dummy arguments in the macro definition, entry for entry, from left to right. NESTED MACROS A macro definition may contain a reference to one or more other defined (nested) macros. Consider the following two macro definitions SET_CURSOR and DISPLAY: SET_CURSOR MACRO ROW, COL MOV AH, 02H MOV BX,0 MOV DH,ROW MOV DL, COL INT 10H ENDM DSPLAY MACRO MESSGE MOV AH, 09H LEA DX, MESSGE INT 21H ENDM A third macro named CURS_DISPLAY could request the SET_CURSOR and DSPLAY macros. CURS_DISPLAY defines the parameters for both nested macros in this way: CURS_DISPLAY MACRO M_ROW, M_COL, MESSGE PUSHA SET_CURSOR M_ROW, M_COL DSPLAY MESSGE POPA ENDM You may code CURS_DISPLAY with constants, variables, or registers for row and column, as CURS_DISPLAY 6, 15, ERROR MSSGE ;Constants CURS_DISPLAY ROW, COLUMN, ERROR_MSSGE ;Variables CURS_DISPLAY CH, CL, ERROR_MESSGE ;Registers Edit the source file and save it with a different name to include these new macro definitions and assemble the file and save the source and listing file. To receive credit for this lab email the source and listing files as one zipped file to kuroskit@ecc.edud using the subject heading “CS221 Lab12”.