flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > Lists of comma-separated items.

Author
Thread Post new topic Reply to topic
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 11 Jun 2005, 20:12
Here are the few notes on how the "match" directive can help in working with such lists (I plan to put those notes also in the updated manual for the next release).

Imagine you've got defined the list of items as a value of symbolic constant, like:
Code:
list equ 1,2,3    

And you'd like to pass those values to some macro, which would process each of items separately. The macro would be for example:
Code:
macro disp [value]
{ display `value,13,10 }    

Unfortunately it won't work this way:
Code:
disp list ; this will actually display the 'list'    

because the symbolic constants are replaced with their values after macroinstruction has been processed, and this time the name of constant has already became the quoted string (on the other hand it would work if constant was defined with "fix" directive, but this one is not as flexible as "equ"). The "match" directive can help, because it replaces the symbolic constants in the matched value before it checks it for the match. So the solution looks like:
Code:
match items,list { disp items }    

The "match" directive first replaces the "list" with its value and then it performs the match - the whole list is matched to the "items" name and then passed to the macro (the "match" directive is processed like macroinstruction, what means that the matched names are processed like macro arguments, so the line "disp items" becomes "disp 1,2,3" before any actual preprocessing). Also, if the list is empty, there won't be match (since every name in the match expression needs to match at least one symbol), and the block won't be processed at all.

The other place where "match" can help with operating on such list is adding the items to them. Let's start with an empty list:
Code:
list equ    

The following macroinstruction can be used to add items to it:
Code:
macro add_to_list value
{
  match any, list \{ list equ list,value \}
  match , list \{ list equ value \}
}    

First match occurs only when the list is not empty, in such case the new item is attached after the comma. The second match is processed for the case of empty list, then just the value of item is assigned to the list.
This would also attach the value to list:
Code:
match any, list { list equ any,value }    

but there is some difference: the "any" becomes the value of "list" symbolic constant, and then inside this value (all the items from the list) the symbolic constants are replaced again, as "equ" does usually. Look at the sample:
Code:
list equ 1,2
1 equ 7 ; a small definition to cause mess
match any, list { list equ list,3 }
match any, list { list equ any,3 }    

The first match becomes just:
Code:
list equ list,3 ; defines list with value 1,2,3    

while the second match becomes:
Code:
list equ 1,2,3,3 ; defines list with value 7,2,3,3    
Post 11 Jun 2005, 20:12
View user's profile Send private message Visit poster's website Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard 12 Jun 2005, 13:39
Thanks for the description - it helped me a lot.
I was trying to write a helper macros for importing functions from DLLs. You can specify just a name of a dll file (like kernel32 or user32), and macro will include INC file with equates, and list of import functions. Only files with needed equates would be included.
Here are the macros:
Code:
macro use_dll [dll] {
common
  __dll_list equ
forward
  match any , __dll_list \{ __dll_list equ __dll_list,dll  \}
  match , __dll_list \{ __dll_list equ dll \}
  include '%fasminc%\equates\'#`dll#'.inc'
}

macro __import_lib [lib]
 { forward
    local _label
    if ~ lib#.redundant
    dd RVA lib#.lookup,0,0,RVA _label,RVA lib#.address
    end if
   common
    dd 0,0,0,0,0
   forward
    if ~ lib#.redundant
    _label db `lib#'.dll',0
    end if
   forward
    include '%fasminc%\apia\'#`lib#'.inc'
 }

macro .idata {
common
  section '.idata' import data readable
  match list,__dll_list \{ __import_lib list \}
}    


Sample program with my macro should look like this:
Code:
format PE GUI
include '%fasminc%\win32a.inc'
include 'imports.inc'
use_dll kernel32,user32
entry start

section '.code' code readable executable

  start:
        invoke  MessageBox, 0, _caption,_message,0
        invoke  ExitProcess,0

section '.data' data readable writeable

  _caption db 'Win32 assembly program',0
  _message db 'Hello World!',0

.idata    

It is almost working... only there's a problem with equate files - when I try to compile source, FASM reaports "incomplete macro" error, pointing on first STRUCT definition in source file. What's wrong?
Post 12 Jun 2005, 13:39
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 12 Jun 2005, 13:59
Great thanks, you have found the bug in include processing that went unnoticed through all the earlier versions of fasm. Wink
Please download the new release, it has it fixed. However your sample still won't work, since you are including the equates twice (and the "struct" cannot define the same structure twice, since it defines some global labels), but I guess you will fix this yourself.


Last edited by Tomasz Grysztar on 12 Jun 2005, 14:11; edited 2 times in total
Post 12 Jun 2005, 13:59
View user's profile Send private message Visit poster's website Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard 12 Jun 2005, 14:07
Thanks Wink
I forgot to write that win32a.inc has to be changed, I wasn't trying to include equates twice of course.
Post 12 Jun 2005, 14:07
View user's profile Send private message Visit poster's website Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard 12 Jun 2005, 14:54
Something is wrong again with my first macro, if I try to use relative path FASM can't find the file...
Code:
macro use_dll [dll] {
common
  __dll_list equ
forward
  match any , __dll_list \{ __dll_list equ __dll_list,dll  \}
  match , __dll_list \{ __dll_list equ dll \}
  include '..\equates\'#`dll#'.inc'        ; <- here
}    
Post 12 Jun 2005, 14:54
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 12 Jun 2005, 15:05
The include happens when macro is invoked, that is when you are in the main file - so the path is relative to the path of main file. The similar problem I had to solve in WIN32AXP, you might take a look at it.

Probably the best is just to require the INCLUDE variable etc.
Post 12 Jun 2005, 15:05
View user's profile Send private message Visit poster's website Reply with quote
decard



Joined: 11 Sep 2003
Posts: 1092
Location: Poland
decard 12 Jun 2005, 15:17
I tried this:
Code:
incdir fix '%myinc%'   ; somewhere in the beginning of main file    


Code:
macro use_dll [dll] {
 (...)
  include incdir#'\equates\'#`dll#'.inc'
}    


Unfortunatelly FASM doesn't allow to use # operator anywhere but inside macroinstructions, which makes this solution not fully useful.
Post 12 Jun 2005, 15:17
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 12 Jun 2005, 15:30
Why not fully useful? You can just define the macros for including the files with given prefix.

And you can also do it with standard symbolic constant:
Code:
incdir equ '%myinc%'

match dir,incdir { include dir#'\somefile.inc' }    
Post 12 Jun 2005, 15:30
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< 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.