As you are working you will find that you have to type (and document) the same lines of code over and over. To simplify your task you may create macros. Macros are similar to the preprocessor in C or C++. When you assemble a source file, all macros are expanded. This can lead to large files when you are done compiling. Typically you will want to use procedures for blocks of code that are repeated often. However, for a block of code that is only used once in a program, but you need in every program you write, you may want to create a macro file like the following. The other time you may want to have macros is where you have written a procedure, but setting up the stack to pass the parameters is tedious. In this case, a macro with several parameters is probably your best route. I will give you an example of how to set up a macro with parameters to call a procedure that will print a string to the screen later on in the course. For now you can start to work on your own macros. Remember, the macros provided in the book are much to complex for this course, and may not be used in the projects. You may write your own versions of those in the books.
TITLE IO.MAC ;======================================================================= ; ExitProgram () -- Terminates current application ; PreCond -- None ; PostCond -- Nothing (no registers modified) ; Notes -- Assumes nothing about our current segment ;======================================================================= ExitProgram MACRO mov ax, 4c00h ;standard exit code int 21h ENDM
So if we combine this with our hello world program we would write it as
TITLE hi_world.asm ;======================================================================= ; Hello World application - prints "Hello World" to the screen ;======================================================================= include io.mac ;Some Useful Constants STDIN EQU 0 STDOUT EQU 1 STDERR EQU 2 LF EQU 0Ah CR EQU 0Dh _DATA SEGMENT USE16 BYTE PUBLIC 'DATA' myString DB "Hello World", CR, LF, "$" _DATA ENDS _TEXT SEGMENT USE16 WORD PUBLIC 'CODE' ASSUME cs:_TEXT, ds:_DATA Start: mov ax, _DATA ; set DS to point to our data segment mov ds, ax mov ah, 09h ; function: print string $ terminated mov dx, OFFSET myString ; pointer to string int 21h ExitProgram _TEXT ENDS _STACK SEGMENT USE16 STACK 'STACK' DW 100 dup(?) _STACK ENDS END Start
One last point to bring up here. If you are using labels (for jumping) in a macro, think about what is going to happen. The assembler blindly substitutes a copy of your macro code at each point you use it. If you have a label in your macro it is going to be copied with the same name each time. To avoid this problem look into the LOCAL directive (used within a macro or procedure) or the LOCALS keyword (applies to your entire file). Both of these typically use the @ symbol as the first character of their name. These can get really fancy (don't waste time on it), but you are welcome to use them.Last Modified: January 26, 1999 - Barry E. Mapen