EXPERIMENT NINE DEVELOPING MACRO SEQUENCES INTRODUCTION Although not essential to programming, macro sequences relieve the programmer of retyping the same instructions and also allow additional instructions to be placed into memory. This is also accomplished by using procedures and library files if desired. Macros also allow the creation of your own pseudo language for instruction sequences that often appear in programming. A macro is a roll-your-own instruction that contains any number of instructions and up to 32 parameters. The macro becomes a new instruction in the program that can be stored in a disk file and included in all programs if needed. OBJECTIVES 1. Develop macro sequences for common programming tasks such as reading a key or displaying data on the video display. 2. Show how parameters are carried to a macro sequence. 3. Organize macro sequences in a library of macros called an include file. 4. Use local variables in a macro sequence to access local data and jump addresses. PROCEDURE The macro sequence is developed by using the MACRO and statements provided by the assembler. The MACRO statement identifies the start of the macro sequence and the statement identifies the end. Associated with the MACRO sequence is the name of the macro and any parameters that are carried with the macro to the instructions between the MACRO and statements. Example 9-1 shows a simple macro sequence that displays a single character on the video display. Note how the MACRO and statement are used and also how a parameter is carried to the macro. Comments within macro sequences use double semicolons in place of single semicolons. It is important that the name of the macro sequence is a little different so it is not mistakenly used for a label in a program. The first letter of a label can begin with a letter (A-Z) or any of the following 4 special characters: @, $, _, or?. In this text we use the (underscore) to start a macro. Microsoft suggests that the @ symbol is reserved for future expansions. A dollar sign is used to represent the program counter, and a question mark seems awkward. 1
Example 9-1 _DISP MACRO P1 ;;identify start of _DISP macro MOV AH,2 ;;use function 2 to display P1 ;;identify the end of DISP To illustrate the operation of the _DISP macro, a program is written (see Example 9-2) that uses the _DISP macro to display various data on the video display. Note that the source program appears in Example 9-2 (a) and the assembled output is listed in Example 9-2 (b). All statements inserted by use of a macro are preceded by a number (1, 2, etc) to show that the statements are macro statements and to show the level of nesting. In this example, there are no nested macros, so a one is displayed to the left of each expanded macro instruction. Example 9-2 (a) CODE SEGMENT 'code' ;indicate start of code segment ASSUME CS:CODE ;identify CODE as CS _DISP MACRO P1 ;identify start of _DISP macro MOV AH,2 ;;use function 2 to display PI ;identify the end of _DISP PROC FAR ;start main program _DISP 'A' ;display the letter A _DISP 30H ;display the number 0 MOV BL,'Z' ;load BL with a letter Z _DISP BL ;display contents of BL MOV AX,4C00H ;exit to DOS CODE ENDP ENDS END Example 9-2 (b) 0000 CODE SEGMENT 'code' ;indicate start of code segment ASSUME CS:CODE ;identify CODE as CS _DISP MACRO P1 ;identify start of _DISP macro MOV AH,2 ;;use function 2 to display PI INT 21 H ;identify end of _DISP 2
0000 PROC FAR ;start main program _DISP 'A' ;display the letter A 0000 B4 02 1 MOV AH,2 0002 B2 41 1 MOV DL,'A' 0004 CD 21 1 _DISP 30H ;display the number 0 0006 B4 02 1 MOV AH,2 0008 B2 30 1 MOV DL,30H OOOA CD 21 1 000C B3 5A MOV BL,'Z' ;load BL with a letter Z _DISP BL ;display contents of BL OOOE B4 02 1 MOV AH,2 0010 8A D3 1 MOV DL,BL 0012 CD 21 1 0014 B8 4C00 MOV AX,4C00H ;exit to DOS 0017 CD 21 0019 ENDP 0019 CODE ENDS END STEP 1: Modify the program listed in Example 9-2 so it displays your name on the video display. Use the _DISP macro to display each letter of your name. Macros are often included in libraries of macros called include files that are loaded into the object program at assembly time. The include file is an ASCII text file created with PWB, but not assembled. In most cases, the file name extension.inc indicates an include file. To invoke an include file for use by a program, the INCLUDE directive is placed at the start of a program with the name of the macro file to include placed to its right. Example 9-3 shows the contents of a file called MACS.INC that contains four macros that are useful in developing programs. Two display data on the video display, one reads a key, and another exits to DOS. Note that this file is not assembled, it is only an ASCII text file that contains macros. Example 9-3 _DISP MACRO P1 ;display Pl macro MOV AH,2 _KEY MACRO ;read key with echo macro MOV AH,1 _STRING MACRO WHERE ;display string DS:DX macro MOV AH,9 3
MOV INT DX,OFFSET WHERE 21H _EXIT MACRO ;exit to DOS macro MOV AX,4C00H STEP 2: Store the macros listed in Example 9-3 in a file called MACS.INC. Place this in any directory of your choosing. Now write the program listed in Example 9-4, assemble it and execute it. Example 9-4 uses the MACS.INC file to access the video display, keyboard, and exit to DOS. Make sure to place the correct disk drive and directory with the include statement in Example 9-4. Example 9-4 CODE SEGMENT 'code' ;indicate start of code segment ASSUME CS:CODE ;identify CODE as CS INCLUDE MACS.INC ;include macro file MES1 DB 13,10,10,'Type any key to continue: $' PROC FAR ;start main procedure MOV AX,CS ;make DS = CS MOV DS,AX _STRING MES1 ;display MES1 _KEY ;read a key _DISP 13 ;display carriage return _DISP 10 ;display line feed _EXIT CODE ENDP ENDS END Notice the ease at which the program, in Example 9-4, is written because of the presence of macros and also notice its clarity. The code segment and data segment registers overlap the code and data segments in this example so a single segment is used for the program. This is accomplished by copying the contents of CS into DS. This is required in this program to display the character string MES1. This technique is often used in short programs. STEP 3: Write a program that uses the macro include file of Example 9-3 to display the ASCII contents of memory locations F800:0000 through and including F800:OOFF. Note that this is accomplished by addressing segment F800H with the DS register and then by addressing each location through an indirect register such as SI. An example is MOV AL,[SI] or if the _DISP macro is used directly, _DISP [SI]. Note that _DISP [SI] addresses byte-sized memory because of the way that the _DISP macro is written. Make 4
sure to display a few carriage return (13) /line feed (10) combinations before displaying the contents of memory with the STRING macro. In the space provide, write the information displayed when this program is executed. (In many cases this will display the name and address of the BIOS manufacturer.) Using local variables in macros. In many macros a jump must be made within a macro sequence. This requires the use of a local variable, defined with the LOCAL directive. Such a case is listed in the macro of Example 9-5. This macro reads a key from the keyboard without an echo. It ends with carry cleared for a standard ASCII character and with carry set for an extended ASCII character. The extended ASCII character set are characters with the codes 80H-FFH. In addition, it maintains a random number in register BP within the ranges passed to the macro as parameters LO and HI. Example 9-5 _KEYS MACRO LO,HI ; start macro LOCAL K1,K2,K3 ;identify local labels K1: MOV BP,LO-1 ;start BP at LO-1 K2: INC BP ;increment BP CMP BP,HI+1 ;test for above HI JE K1 ;if above HI MOV AH,6 ;read key, no echo MOV DL,-1 K3: JE K2 ; if no key typed OR AL,0 ;test for extended code JNE K3 ;regular ASCII code ;get extended ASCII code STC ;set carry In this example local variables are defined as K1, K2, and K3. It is very important that any variables used within a macro are defined as local. This allows the assembler to insert its own variables, which are unique for each local variable, each time that the macro is invoked. Variables inserted by the assembler are numbered and replace the local variables. STEP 4: Write a program that uses the macro (store the macro in your macro include file) of Example 9-5 to accept and the display random numbers between 1 and 9. Your program should display the character string prompt Press any key to display a random number: before invoking the _KEYS macro. Upon return from _KEYS, BP will contain a random number between 1 and 9 that is converted to an ASCII-coded number (31H-39H) by adding a 30H. This number is then displayed with the _DISP macro listed in Example 5
9-3. Repeat this program until the control plus C key (an ASCII 03H) is typed at the prompt. To type control plus C hold down the control key (Ctrl) and then press C. QUESTIONS 9-1. Which assembly language statements delineate a macro sequence? 9-2. How are parameters passed to a macro sequence? 9-3. Where can macro sequences be stored for inclusion in any program? 9-4. What is the purpose of the LOCAL directive? 9-5. What is the purpose of the INCLUDE directive? 9-6. Develop a macro sequence that displays a character string at any memory location. This requires that both the offset and segment addresses are passed to the macro as parameters. 9-7. Develop a macro sequence that identifies your software as yours. This macro must display your name, course number, and other information required to identify the software as yours. 9-8. Develop a macro called _CRLF that displays a carriage return and line feed combination. It may be wise to use the _DISP macro in this macro. This is called nesting. Note that the _DISP macro must appear before being used in the _CRLF macro. 9-9. How is a comment used within a macro sequence? 9-10. Write a macro sequence that displays a character string that ends with a zero (00H) instead of the customary dollar sign (24H). The segment and offset addresses are parameters passed to this macro. 6