flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > Macro tutorials

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
Guest





Guest 29 Sep 2003, 03:34
Hello All:

Though I am not very sure whether this is the right place for such a request, I'm asking it here.

Macros are considered one of the power user's tool. And like me, I believe many of us are unable to understand and use its power fully. I would like to request more advanced and experienced FASM users to start/post a macro tutorial broken into small small parts and which shows beginner to advanced use of macros here in this thread. This should help many of us immensely, if you can explain and demonstrate from some simple to complex macros, and the art of writing and debug them.

I am sure, later Privalov can also compile some examples from here to finish up the Master Tutorial. Smile

So could you please help?

Thanks.
Post 29 Sep 2003, 03:34
Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 29 Sep 2003, 04:45
Do you want tutorials about macros like this?
Code:
macro sz name, [data]{
  common label name
  forward db data
  common .size = $-name
}    

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 29 Sep 2003, 04:45
View user's profile Send private message Visit poster's website Reply with quote
Guest





Guest 29 Sep 2003, 07:25
Thanks Scientica for your answer.

Yes in this line, that is how should a beginner start writing macros, perhaps some explanations of what you have written, some possible pitfalls that might occur while writing the macros. This way from simple to more complex macro writing techniques/helps would be really nice. Very Happy
Post 29 Sep 2003, 07:25
Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 29 Sep 2003, 12:43
Ok here is the explanation for it, let's hope I can explain it Wink - If not just ask for a clarifiaction and I'll try my best to explain it in another way.

Code:
macro sz name, [data]{
  common label name
  forward db data
  common .size = $-name
}    

This macro creates a string contauning the "data", and it "adds" an "local equate" (thing as in local label) with the name "size" which contains the size of the string. The data argument can basically be anythung that would be valid after a "db". The .size "member" is accessed by typing: name.size (where the name is the name you specify (the first argument to the macro))

Here are a few examples on what the output will be with different arguments

Code:
;(in data section)
sz szStringFooBar, "Foo Bar!",0
;..
;(in the code section)
mov esi, szStringFooBar
mov ecx, szStringFooBar.size
;---------------------------------------------------
;This would give the same ouput as writing:
szStringFooBar db "Foo Bar!",0
;...
mov esi, szStringFooBar
mov ecx, 9 ; the size of the string is 9
;---------------------------------------------------
;one could also write:
;---------------------------------------------------
szStringFooBar db "Foo Bar!",0
 .size = $ - szStringFooBar
;and then make use of:
mov ecx, szStringFooBar.size
    


Code:
;Here are a few more valid strings
sz szString, "Hello Dword!",0
sz szString2, "Hello',9,'Dword!",13.10,'there is a tab between Hello and Dword, and this on a new line : )',0
sz szYAS, "YAS means Yet Another String",0
sz szJustSomeValues, 254, 75h,196,35,64h,35h,0
    


btw, I think that you should register, it's easier to remember a nick name rather then the Guest i Macroinstructions. And you're able to post in the other forums too.

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 29 Sep 2003, 12:43
View user's profile Send private message Visit poster's website Reply with quote
prana



Joined: 28 Aug 2003
Posts: 51
prana 29 Sep 2003, 17:28
Scientica, it's really great! Very Happy

Btw my login screwed up a little, I managed to fix it.

I am sure you can teach us some more tricks and techniques like this.

Please keep posting and explain the topic with such examples.

Thanks a lot!
Post 29 Sep 2003, 17:28
View user's profile Send private message Reply with quote
prana



Joined: 28 Aug 2003
Posts: 51
prana 30 Sep 2003, 02:02
I'm having trouble to understand the following things, could some one kindly explain them with some examples and when to use them?

1) The difference btw '=' and 'equ'
2) The '.<var-name>' and '..<var-name>'
3) The 'forward', 'common', and 'reverse' - why they are required, and are there any other directives for macros? I'm really confused with this directives even though I've gone thru the manual. Pls explain a little.
4) The 'fix' directive
5) The '#','##', '@', '@@', and '%' symbols.


Please help me! Confused
Post 30 Sep 2003, 02:02
View user's profile Send private message Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 30 Sep 2003, 05:46
Ok, I a little short on time - I'll try to give as many answers as I have time for right now.

1) the differece is that equ will replace the equate with the value. Here is an example
Code:
org 100h
equate0 = $
equate1 equ $
mov eax, equate0 ; will result in 100h, since the value of $ was 100h at the time it was defined.
org 200h
mov ebx, equate1  ;will be the same as writing "mov ebx, $", since equate1 [b]equ[/b]als $    


2) '.<var-name>' are local labels, these are local to the previous label, for instance:
Code:
MasterLabel:
;...
.sublabel:
; .sublabel can be referenced as .sublabel when you still are under the MasterLabel (if you define another global label)
; if you are under another global label you can still access the local label like this:
SomeOtherMistressLabel:
mov ebx, MasterLabel.sublabel

Please note that declaring for instance a string will create a global label thus:
MasterLabel:
StringThis db 'String',0
.sublabel:
; typing MasterLabel.sublabel will yield an error, because there is no local by the name .sublabel under MasterLabel, but there is one under StringThis (named: StringThis.sublabel), if you put a "." before the StringThis then it'll be local and MasterLabel.sublabe will be legal.
; thus this is how it would look like:
MasterLabel:
.StringThis db 'String',0
.sublabel:
    


3) As I'm a little short on time I'll explain this later unless no one else replies bofre that.

4) The 'fix' directive is like equ, but it's processed among the first of all directives, try search teh boad for teh first thread containing fix.

5) From the manual
Quote:
It can be used to call indirectly (by the pointer stored in memory) the
procedure using STDCALL convention.
Inside macroinstruction also special operator "#" can be used. This
operator causes two names to be concatenated into one name. It can be useful,
because it's done after the arguments and local names are replaced with their
values. The following macroinstruction will generate the conditional jump
according to the "cond" argument:

macro jif op1,cond,op2,label
{
cmp op1,op2
j#cond label
}


Code:
  The "@@" name means anonymous label, you can have defined many of them in
the source. Symbol "@b" (or equivalent "@r") references the nearest preceding
anonymous label, symbol "@f" references the nearest following anonymous label.
These special symbol are case-insensitive.    


Code:
2.2.1  Repeating blocks of instructions

"times" directive repeats one instruction specified number of times. It
should be followed by numerical expression specifying number of repeats and
the instruction to repeat (optionally colon can be used to separate number and
instruction). When special symbol "%" is used inside the instruction, it is
equal to the number of current repeat. For example "times 5 db %" will define
five bytes with values 1, 2, 3, 4, 5. Recursive use of "times" directive is
also allowed, so "times 3 times % db %" will define six bytes with values
1, 1, 2, 1, 2, 3.
  "repeat" directive repeats the whole block of instructions. It should be
followed by numerical expression specifying number of repeats. Instructions
to repeat are expected in next lines, ended with the "end repeat" directive,
for example:

    repeat 8
        mov byte [bx],%
        inc bx
    end repeat

The generated code will store byte values from one to eight in the memory
addressed by BX register.
  Number of repeats can be zero, in that case the instructions are not
assembled at all.    


G2G School now, bye Smile

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 30 Sep 2003, 05:46
View user's profile Send private message Visit poster's website Reply with quote
prana



Joined: 28 Aug 2003
Posts: 51
prana 30 Sep 2003, 07:16
Thanks a lot! Very Happy
Pls keep posted.
Post 30 Sep 2003, 07:16
View user's profile Send private message Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 30 Sep 2003, 15:17
prana wrote:
3) The 'forward', 'common', and 'reverse' - why they are required, and are there any other directives for macros? I'm really confused with this directives even though I've gone thru the manual. Pls explain a little.

3) Ok, you've read the manual, first: don't panic (Wink), but let's take a look at the docs first: (It's not as much reading as it seems). Second: panic!!! Twisted Evil Laughing Wink
Code:
If after the "macro" directive you enclose some group of arguments' names in
square brackets, it will allow giving more values for this group of arguments
when using that macroinstruction. Any more argument given after the last
argument of such group will begin the new group and will become the first
argument of it. That's why after closing the square bracket no more argument
names can follow. The contents of macroinstruction will be processed for each
such group of arguments separately. The simplest example is to enclose one
argument name in square brackets:

    macro stoschar [char]
     {
        mov al,char
        stosb
     }

This macroinstruction accepts unlimited number of arguments, and each one
will be processed into these two instructions separately. For example
"stoschar 1,2,3" will be assembled as the following instructions:

    mov al,1
    stosb
    mov al,2
    stosb
    mov al,3
    stosb
......
  "forward", "reverse" and "common" directives divide macroinstruction into
blocks, each one processed after the processing of previous is finished. They
differ in behavior only if macroinstruction allows multiple groups of
arguments. Block of instructions that follows "forward" directive is processed
for each group of arguments, from first to last - exactly like the default
block (not preceded by any of these directives). Block that follows "reverse"
directive is processed for each group of argument in reverse order - from last
to first. Block that follows "common" directive is processed only once,
commonly for all groups of arguments. Local name defined in one of the blocks
is available in all the following blocks when processing the same group of
arguments as when it was defined, and when it is defined in common block it is
available in all the following blocks not depending on which group of
arguments is processed.    

The first macro showed is this:
Code:
macro stoschar [char]
{
   mov al,char
   stosb
}    

It could be written as:
Code:
macro stoschar [char]
{
forward
   mov al,char
   stosb
}    

what forward does is that for each argument in char (in the example [char] is three arguments: 1, 2 and 3) is perfomes the code untill either:
1) The macro end.
2) forward, reverse or common is encountered.
The revese does the same as forward, but it starts with the last argument in [char].
Code:
macro stoschar [char] {
reverse
   mov al,char
   stosb
}
stoschar 1,2,3
;above would be assembled as:
    mov al,3
    stosb
    mov al,2
    stosb
    mov al,1
    stosb    


common is only processed one, where as forward and common is processed for every argument in [char].

Here is another example from the docs:
Code:
    macro stdcall proc,[arg]
     {
      reverse push arg
      common call proc
     }

;can also be written as:
    macro stdcall proc,[arg]  {
      reverse
        push arg
      common
        call proc
     }

stdcall AnyProc, 1,2,3
    

What happens here is:
First, for every argument in [arg] starting with the last argument do this:
"push arg" (where arg is the "current" argument in [arg], in the first "pass" in the macro arg will be 3, in the second "pass" arg will be 2, and in the last it will be 1).
Then, do this (once): "call proc" (where proc will be equal to AnyProc).

So in short, "stdcall AnyProc, 1,2,3" it will compile as:
Code:
push 3
push 2
push 1
call AnyProc    


I attach an example file, it contains an example of the use of [var] but with one difference, take a look and see Smile
(btw, compile the file with this command: "fasm test.asm tmp.htm" and open it in a web browser)

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 30 Sep 2003, 15:17
View user's profile Send private message Visit poster's website Reply with quote
prana



Joined: 28 Aug 2003
Posts: 51
prana 01 Oct 2003, 01:37
scientica, this is just great Very Happy

Your last post cleared up a lot of confusion I had Smile
Just one question, why the "..<var-name>" is used?


Also to the moderator/s of this board, I'm sometimes unable to see attchments posted with messages Evil or Very Mad
Why so? As for now I'm unable to see the test.asm that scientica has posted. Shocked I'm using IE 6.

Thanks scientica, also pls keep us posted with new lessons.
Thanks a lot Very Happy
Post 01 Oct 2003, 01:37
View user's profile Send private message Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 01 Oct 2003, 04:25
-- I'm not sure I can post - but if you can read this I could --

The file test.asm isn't attached in the posts (when I posted I got debug mode error and (doublepost)^2+1 and the file didn't want to come up), but I've made a raw copy and attached the file on the other forum board.win32asmcommunity.net. Btw I could delete the doubleposts after "a few" attepts to deltre them (using the "x" button)

I'll try to answer that later to day (soon time for shcool (where I'm up for a 5 hour math competition -- I've chosen it my slef, am I mad? Yes Very Happy) then tonight there is yet another competition I'm in for ). But mean while you can try to search teh other forum (I think the issue is explained there)

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 01 Oct 2003, 04:25
View user's profile Send private message Visit poster's website Reply with quote
prana



Joined: 28 Aug 2003
Posts: 51
prana 01 Oct 2003, 04:32
Well I'll try to grab that file from board.win32asmcommunity.net.
Very Happy

Just two questions now:

1) why the "..<var-name>" is used?
2) how can I get an interim look of my source file with all macros expanded?

Please help.


In btw, all the best for your competition Wink
Post 01 Oct 2003, 04:32
View user's profile Send private message Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 01 Oct 2003, 15:01
prana wrote:
Well I'll try to grab that file from board.win32asmcommunity.net.
Very Happy

Just two questions now:

1) why the "..<var-name>" is used?
2) how can I get an interim look of my source file with all macros expanded?

Please help.


In btw, all the best for your competition Wink

1) To tell the truth I had forgotten the maeing of the ..labels :oop: , but I knew there was an thread about somewhere, here it is: "What are ..variables?" - http://board.win32asmcommunity.net/showthread.php?s=&threadid=6956&highlight
2) Don't know, but I remember seeing a post (on this board) with a listing version of fasm - seach for it.

by the way, first competition done (the 5 hour math competition (Don't know exactly when I get to know how bad (Wink) it went )) one more to go in a few hours time.

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 01 Oct 2003, 15:01
View user's profile Send private message Visit poster's website Reply with quote
prana



Joined: 28 Aug 2003
Posts: 51
prana 01 Oct 2003, 16:55
Thanks for the thread friend Cool

However still searching for the listing feature of fasm - does it produce a .lst file?

In btw, congrats for finishing the first competition, carry on Wink
Post 01 Oct 2003, 16:55
View user's profile Send private message Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 01 Oct 2003, 18:25
Here is the thread I'm speaking of: http://board.flatassembler.net/topic.php?t=213&highlight=listing

btw, in a few hours I should have the result for the last competition.

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 01 Oct 2003, 18:25
View user's profile Send private message Visit poster's website Reply with quote
prana



Joined: 28 Aug 2003
Posts: 51
prana 02 Oct 2003, 08:17
Thanks for the link pal Cool

However, pls keep us posted with any new techniques you invent Idea
For some time I'll be busy writing macros now Wink

And any idea when Privalov will finish the tutorial? I can hardly wait for it!

Btw, how was your score? Must be a good news, all the best Very Happy
Post 02 Oct 2003, 08:17
View user's profile Send private message Reply with quote
scientica
Retired moderator


Joined: 16 Jun 2003
Posts: 689
Location: Linköping, Sweden
scientica 02 Oct 2003, 14:41
I still haven't gotten any info on the first competition, the second however, well the class which I competed with (my kid brothers class), unfortainly we didn't score enought points to be in the top 3 (don't know exactly in what place we ended up in).

Perhaps the WinStyle (in styleeditor.asm of the Fresh project) macro would be of interest? (I'll explain it later, must do some homework first.)

_________________
... a professor saying: "use this proprietary software to learn computer science" is the same as English professor handing you a copy of Shakespeare and saying: "use this book to learn Shakespeare without opening the book itself.
- Bradley Kuhn
Post 02 Oct 2003, 14:41
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 03 Oct 2003, 13:32
Thanks for your work scientica! You was faster than me, I was also planning to make some tutorial about writing macroinstructions, but I managed only to finish the introduction about symbolic constants. I'm posting it here - if you find it useful, I may write more about using symbolic constants in macros, and then about using the "fix" variant - but those should be later parts, as we can use your work as the "part 2" of this tutorial.


Part 1 - Symbolic constants

Symbolic constants are those defined with "equ" keyword - in opposite to those defined with the "=" operator, which are called the numerical constants. Numerical constants are just a special variant of labels, which have assigned some value (absolute, or some relative address) and can be used in the numerical expressions. Any numerical expression is calculated by assembler each time it has to generate the code for instruction containing that expression, as the values of labels and numerical constants may very between the assembly passes. The only difference between regular label and numerical constant is that the constant can be redefined (but when it is redefined at least once in the source, it cannot be back-referenced).

Symbolic constants are completely different - they can have any value, not necessarily a numerical expression, and they are replaced with that value everywhere in source starting from the line following the one containing the "equ" definition. It is done by preprocessor, and only such source goes to the main assembler module (it is also processed by the parser module in the meantime, but that's another story). Let's see on small example how does it work and how does it differ from numerical constant processing. Look at the following two definitions:
Code:
symbolic equ $
numerical = $    

The dollar sign is the special symbol that in numerical expressions is interpreted as the value of current address in output code. So when we define numerical constant with the value of that expression, it will be just equal to the address of the point in code, where it was defined. Each time assembler sees that constant in some expression, it will calculate the final value using that address.
But the symbolic constant will be just replaced with the dollar sign everywhere it occurs later in the source, so the assembler will see just the dollar sign in every place we use this constant, and will calculate the value using the current address.
For example, if we put the above definition at the beginning of source (with binary output), the "numerical" will have value of 0, so the following instructions:
Code:
db numerical
db numerical    

both define the zero byte. But if instead we wrote this:
Code:
db symbolic
db symbolic    

these instruction will be seen by assembler as:
Code:
db $
db $    

And so the first one defines the zero byte, but the second one defines byte of value 1.
To finally punctuate the difference between symbolic and numerical constants, I'll provide one more example in this context:
Code:
dd symbolic+numerical    

will be seen by assembler as:
Code:
dd $+numerical    

The numerical constants are never replaced with anything - their values are only used in the calculations. And the definitions of numerical constants are interpreted at assembly time, while symbolic constants are already processed at this stage, and their definitions are no longer visible.

Numerical constants are recommended for the purpose of defining any equates, as they are usually processed faster. The symbolic constants may be useful for more complex applications, like various syntax adjustments, for example defining some shortcuts:
Code:
b equ byte
w equ word
d equ dword    

With such definitions we can then use single letter operators to specify the size of operand in assembly instruction.

Any symbolic constant can be redefined, in such case its name is not replaced with its value, but all symbolic constants after the "equ" operator are processed normally. Therefore such two definitions:
Code:
symbolic equ $
symbolic equ symbolic+1    

will leave us with constant having value "$+1".

There is also the "restore" directive that allows us to get back the value of symbolic constant that was redefined. For example if after the two lines from the example above we put the following:
Code:
restore symbolic    

we will get back the value "$" assigned to that constant. If we repeat it, it will get back the initial meaning, so "symbolic" word won't be anymore replaced with anything other.
As you can see, symbolic constants in arguments for the "restore" directive are not replaced with their values, as in the above example we would get the "restore $+1" instruction, which makes no sense. This rule applies to all the directives interpreted by preprocessor - they are immune to the symbolic constant processing, and the "restore" is one of them.
Post 03 Oct 2003, 13:32
View user's profile Send private message Visit poster's website Reply with quote
prana



Joined: 28 Aug 2003
Posts: 51
prana 03 Oct 2003, 16:46
It's just great Very Happy
Can hardly wait for the next part Very Happy
I'm compiling all work of yours in this thread Smile
Post 03 Oct 2003, 16:46
View user's profile Send private message Reply with quote
LiuGuoHua(Chinese)



Joined: 26 Sep 2003
Posts: 25
LiuGuoHua(Chinese) 27 Oct 2003, 06:19
Really nice work!
I'm attemping to translate it into Chinese.
Keep on, waitting!
Post 27 Oct 2003, 06:19
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.