flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > Macros with end

Author
Thread Post new topic Reply to topic
Cgtk



Joined: 10 May 2020
Posts: 19
Cgtk
Hello, I need to write a macro that will be similar in syntax to virtual, I would like its use to look something like this:
Code:
myMacro
.
.
.
end myMacro
    


How do I do something like this? Does the fasm macro engine allow each line inside this definition to be a group of variables? For example, the line testvar dq ? it was broken down by gaps
Post 22 Jun 2022, 12:33
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1081
Location: Belarus
DimonSoft
Seems like you need something very similar to what struct/ends macros do. Just with end instead of ends which is easily doable as well.
Post 23 Jun 2022, 13:15
View user's profile Send private message Visit poster's website Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 576
Location: Ukraine
Overclick
Did you read the manual? There is one example. You need to use fix
To divide ENDM to separate words you have to redefine end macro with macro extension
Post 23 Jun 2022, 18:12
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 652
Location: Russia
macomics
Such an announcement is basically impossible
Code:
myMacro ; <- You call a macro or start declaring it.
.
.
.
end myMacro    
How to distinguish then a label/command/directive/macro from the beginning of a new macro.
Post 23 Jun 2022, 20:35
View user's profile Send private message Reply with quote
Cgtk



Joined: 10 May 2020
Posts: 19
Cgtk
macomics wrote:
Such an announcement is basically impossible
Code:
myMacro ; <- You call a macro or start declaring it.
.
.
.
end myMacro    
How to distinguish then a label/command/directive/macro from the beginning of a new macro.


I thought it was possible to define your own service words in fasm. In the manner described above, the macro should only be called.

I imagined it somehow like this: "The preprocessor sees the word, checks it with the service words known to it. Finds my macro and searches for myMacro end. After that, it processes what is written. "


Last edited by Cgtk on 23 Jun 2022, 23:59; edited 1 time in total
Post 23 Jun 2022, 23:27
View user's profile Send private message Reply with quote
Cgtk



Joined: 10 May 2020
Posts: 19
Cgtk
I would be very happy if you could give some simple examples, it would save me a lot of time because I'm new to macros.
Post 23 Jun 2022, 23:33
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 652
Location: Russia
macomics
In the example you gave, the beginning of a macro declaration is indistinguishable from its use. In order to understand which of the actions (definition, redefinition or application) you want to do, you need to use at least some reserved word. Examples:
Code:
struc RECT {
 .left   dd ?
 .top    dd ?
 .right  dd ?
 .bottom dd ?
}
myMacro RECT ; defining a macro with the RECT parameter or defining a structure under the myMacro label

end myMacro
;------------------------------------------------------
macro normalMac def& { local name
name def }
normalMac RECT ; Unambiguous application of the macro that defines the RECT structure    
Code:
myMacro movd eax, mm0 ; application of the myMacro macro with 2 parameters or the beginning of the definition of the same macro?

end myMacro
;------------------------------------------------------
macro normalMac cmd& {}
normalMac movd eax, mm0 ; = nothing    
Code:
myMacro
 xor eax, eax
end myMacro
myMacro ; applying myMacro or overriding the same macro?
 xor ecx, ecx
end myMacro
;------------------------------------------------------
macro normalMac { xor eax, eax }
macro normalMac { xor ecx, ecx }
normalMac ; = xor ecx, ecx
    
How to distinguish all the above cases without knowing that there is a string "end myMacro". And you need to know this at the moment when a specific text is being processed. Otherwise, checking each word at the beginning of the macro will turn into an endless abyss and compilation will take 1`000`000 times longer.
Post 24 Jun 2022, 01:27
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1081
Location: Belarus
DimonSoft
macomics, it might just be a case of something like
Code:
if
.
.
.
end if    
Just replace if with anyMacroName. It might have a lot of valid use cases, Cgtk will just have to choose which behaviour is desired.
1) Actual conditional inclusion/exclusion of definitions but with custom if-like syntax (actually, match itself looks quite ugly for choosing between multiple alternatives).
2) Gathering series of code blocks into one place. Then the macro gives blocks unique names and adds them to a list of blocks.
3) Some struct-like behaviour. Who said one can’t tell the name of the struct at ends?
4) Redefinition of what has been declared before. Not of much use since it would just duplicate macro behaviour but some people might hate curly braces, why not? Except that replacing end myMacro with } might be a bit tricky due to the existencs of end if, end while and stuff, and they probably should not be broken by the fix.
5) …
Post 24 Jun 2022, 07:17
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 652
Location: Russia
macomics
DimonSoft wrote:
macomics, it might just be a case of something like
Code:
if
.
.
.
end if    
Just replace if with anyMacroName. It might have a lot of valid use cases, Cgtk will just have to choose which behaviour is desired.
1) Actual conditional inclusion/exclusion of definitions but with custom if-like syntax (actually, match itself looks quite ugly for choosing between multiple alternatives).
2) Gathering series of code blocks into one place. Then the macro gives blocks unique names and adds them to a list of blocks.
3) Some struct-like behaviour. Who said one can’t tell the name of the struct at ends?
Then you will have to make your own preprocessor that will understand if and reorganize the program. Overclick, for example, did the same in its .multisection macro. But at least he only worked with the assembler text, not the preprocessor.

Another problem. This is the implementation of the macro application. Before you understand what is happening, you will have to find the ending "end macroName" or "macroName" (redefine or apply).

DimonSoft wrote:
4) Redefinition of what has been declared before. Not of much use since it would just duplicate macro behaviour but some people might hate curly braces, why not? Except that replacing end myMacro with } might be a bit tricky due to the existencs of end if, end while and stuff, and they probably should not be broken by the fix.
Redifinition
Code:
macro define@proc name,statement
...
   macro locals
   \{ virtual at localbase@proc+current
      macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,<type \\\} \\}
      struc db [val] \\{ \common deflocal@proc .,db,val \\}
      struc du [val] \\{ \common deflocal@proc .,du,val \\}
      struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
      struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
      struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
      struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
      struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
      struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
      struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
      struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
      struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
      struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
      struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
   macro endl
   \{ purge label
      restruc db,du,dw,dp,dd,dt,dq
      restruc rb,rw,rp,rd,rt,rq
      current = $-(localbase@proc)
      end virtual \}
   macro ret operand
   \{ match any, operand \\{ retn operand \\}
      match , operand \\{ match epilogue:reglist, epilogue@proc:<regs> \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
   macro finish@proc
   \{ localbytes = current
      match close:reglist, close@proc:<regs> \\{ close name,flag,parmbytes,localbytes,reglist \\}
      end if \}
...
macro endp
 { purge ret,locals,endl
   finish@proc
   purge finish@proc
   restore regs@proc
   match all,args@proc \{ restore all \}
   restore args@proc
   match all,all@vars \{ restore all \} }    
Post 24 Jun 2022, 08:32
View user's profile Send private message Reply with quote
Cgtk



Joined: 10 May 2020
Posts: 19
Cgtk
The task I want to solve with this macro is a convenient reference to variables in the stack. The plan is for the necessary variables to be described in this block as something like this:
Code:
myMacro
var1 dq ?
var2 dq ?
var4 dq 0xFF
end myMacro
    

Then my macro would split them into lines, lines into spaces and get {[var1], [dq], [?]}, etc.
After that, in the program, the labels var1,var2, var3 would be replaced by [rsp+0xNN]. The latter, as I understand it, can be implemented using equ.
Post 24 Jun 2022, 09:48
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 18844
Location: In your JS exploiting you and your system
revolution
Look at the post by macomics immediately above yours.

Replace "myMacro" with locals, and replace "end myMacro" with endl.
Post 24 Jun 2022, 09:52
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 652
Location: Russia
macomics
Cgtk wrote:
The task I want to solve with this macro is a convenient reference to variables in the stack. The plan is for the necessary variables to be described in this block as something like this:
Code:
myMacro
var1 dq ?
var2 dq ?
var4 dq 0xFF
end myMacro
    

Then my macro would split them into lines, lines into spaces and get {[var1], [dq], [?]}, etc.
After that, in the program, the labels var1,var2, var3 would be replaced by [rsp+0xNN]. The latter, as I understand it, can be implemented using equ.
This is already implemented in the proc macro (labels/endl, see revolution above). But why duplicate virtual?
Code:
procname_esp:
virtual at esp
  label .locstart
  .varN   RECT
  ...
  .var1   dd ?
  .var0   db ?
  label .locals at (-4 and ($ - .locstart + 3))
  rb $ - .locals
  .lastret dd ?
  .arg0   dd ?
  .arg1   dd ?
  ...
  .argN   dd ?
  label .procarg at (-4 and ($ - .lastret - 1))
end virtual
  if .locals > 0
    lea esp, [esp - .locals]
  end if
  ...
  if .procarg > 0
    retn .procarg
  else
    retn
  end if

procname_ebp:
virtual at ebp - .locals
  label .locstart
  .varN   RECT
  ...
  .var1   dd ?
  .var0   db ?
  label .locals at (-4 and ($ - .locstart + 3))
  rb $ - .locals
  .lastebp dd ?
  .lastret dd ?
  .arg0   dd ?
  .arg1   dd ?
  ...
  .argN   dd ?
  label .procarg at (-4 and ($ - .lastret - 1))
end virtual
  push ebp
  mov ebp, esp
  if .locals > 0
    lea ebp, [esp - .locals]
  end if
  ...
  leave
  if .procarg > 0
    retn .procarg
  else
    retn
  end if    
Post 24 Jun 2022, 10:19
View user's profile Send private message Reply with quote
Cgtk



Joined: 10 May 2020
Posts: 19
Cgtk
Thanks a lot to everyone, I think that local variables are suitable for solving my problem. Somehow I didn't think in their direction.
Post 24 Jun 2022, 12:17
View user's profile Send private message 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-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.