Svin: OK, now who here is NOT named Svin? I see you there. PEEKER! Seriously, I do lots of work with macros. They are tricky little beasts, but are capable of lots of powerful actions for you. An aside: HTML does a poor job with angle brackets. I use LOTS of them below, and they will disappear along with stuff between them, so I substituted [ ] brackets instead. You may wish to copy this text and make that substitution before continuing. Just change ALL the [ and ]'s Let's define a small macro to make some text for us: GimmyStrings MACRO label:req, strings:vararg LOCAL outline, str, count count TEXTEQU [0] .data FOR str, ; start a macro loop count TEXTEQU %count + 1 ;; inc count outline CATSTR , count, [ BYTE ], ,[, 0] ENDM ENDM If you give this macro the following: GimmyStrings MyString, "String number 1", "String number 2", "String number 3" It will generate this: MyString1 BYTE "String number 1", 0 MyString2 BYTE "String number 2", 0 MyString3 BYTE "String number 3", 0 Pretty handy perhaps. But it's a tool for us today. Let's go through it line by line to see how it does this. Line 1: GimmyStrings MACRO label:req, strings:vararg ':req' means required, the arg must be there. 'vararg' means ANY NUMBER (and zero is a number) of arguments. A bad opening. Defines the label OK, but allows for NO strings to follow. That would make a compile error. If you really wished this to be so, you would have to check in the macro for "no strings," and do something appropriate like define a null string Line 2: LOCAL outline, str, count These are macro variables we define for use inside the macro each time we use it. Without LOCAL, they would conflict the 2nd time the macro is run Line 3: count TEXTEQU [0] We init count. Brackets are used to make count equal not to zero, but the ASCII for zero. It is truly saved as text. Most macro tricks depend on the difference between text and value. Line 4: .data Simple, changes the section for the following. Trouble, cause we don't know what we changed it FROM so we could reset it. But kinda all we have Line 5: FOR str, ; start a macro loop Whoa, pretty powerful line. It starts a loop, each iteration of the loop assigns the next ARGUMENT we were passed in the macro. Again, we use brackets because we want the text typed, and not any values. Line 6: count TEXTEQU %count + 1 ;; inc count Actually, this is doing a lot of work. the % operator is for 'text expansion,' meaning 'take "count" and give me it's text value. First loop through it would be 'count TEXTEQU 0 + 1', which gets evaluated to '1', converted BACK to text and assigned to count as '1' Line 7: outline CATSTR , count, [ BYTE ], ,[, 0] CATSTR will concatenate as many strings as it is passed. We know to use brackets to define string, so why '' and not just 'label'? Parsing order. First MASM expands the variables, so '' becomes ''... Without the brackets MASM would convert label to it's value, but since it's value doesn't begin and end with brackets, MASM again tried to expand it as a variable. Since it is not such, an error is raised. So, label is replaced by it's value, inside the brackets, then it performs the cat. count IS a TEXTEQU, so it is text, and CATS in fine. Ahhh, now it makes sense. Line 8: outline Perhaps the most important line of the macro, yet curiously, the most innocent looking. In Line 7 we did all that crazy concatenation to make 'outline' have a text string value of MyString1 BYTE "String number 1", 0 ... HEY, that's a valid line of assembly!!! So this line just drops that text into the source. After the macro expansion pass of the compiler, it will look for the code and such, and THEN the line gets compiled. Cool, huh? Line 9: ENDM Just ends the FOR loop Line 10: ENDM Ends the macro So, there is a hopefully helpful example of how to emit multiple lines from one macro. Do
Posted on 2001-01-20 00:37:00 by Ernie
Thank you, Ernie. All that you wrote will be carefully studied. I really need some big and detailed tutorial on how to write macros in MASM. With lots of exercises and examples :) I can't understand why I still haven't seen one. It is somwthing a lot of people needs.
Posted on 2001-01-20 05:05:00 by The Svin
I understood why couldn't make multiline whith my macros :) I should have defiended text as VARARG Thanks Ernie now it works! Otherwise MASM treated every comma as a sign to separate aruments So new versions of the macros are: ;data in code sect: ErrZ macro text:VARARG LOCAL name LOCAL lbl jmp lbl name db text,0 lbl: push eax push eax push offset name push eax call MessageBox endm ErrInvH macro text:VARARG LOCAL name LOCAL lbl jmp lbl name db text,0 lbl: not eax push eax push eax push offset name push eax call MessageBox endm ;data in data section: ErrZ macro text:VARARG LOCAL name .data name db text,0 .code push eax push eax push offset name push eax call MessageBox endm ErrInvH macro text:VARARG LOCAL name .data name db text,0 .code Thanks again! not eax push eax push eax push offset name push eax call MessageBox endm
Posted on 2001-01-20 14:24:00 by The Svin