flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > CALM implementation of STRUCT - new tricks Goto page Previous 1, 2, 3 Next |
Author |
|
Tomasz Grysztar 31 Mar 2023, 17:17
bitRAKE wrote:
As for why you might want to use the new implementation, apart from compatibility with fasm 1, is that by passing all the values directly to the instructions that define the data (instead of fixing them with STORE later) makes it work seamlessly with relocatable values as long as basic macros like DD are implemented to work with them. |
|||
31 Mar 2023, 17:17 |
|
fabbel 03 Apr 2023, 00:45
... above def works using "naive" / "basic" implementation though (in utility/struct.inc) ...
|
|||
03 Apr 2023, 00:45 |
|
Tomasz Grysztar 03 Apr 2023, 06:45
You could not use anything outside of the specific set of data definitions in the fasm's macro, so from the compatibility point of view this would be normal. However, fasmg's version is much less limited and in general allows any kinds of commands. The problem you encountered is related to defining the default value for a named field inside the structure body (which can be replaces by a value taken from the arguments). The IF is not evaluated while defining structure as a macro, only when it is instantiated, therefore definition sees two definitions for "xVal", generating conflict that is implied by the error message you get when you try it.
This demonstrates that with this implementation it's still impossible to use the same data label twice within the same structure - you can either move IF completely outside to define different variants, or use some other methods of avoiding a duplicate name, for example: Code: WIN64 = 1 struc DA? values& if WIN64 = 0 . dd values else . dq values end if end struc struct T_DUMMY dwVal1 dd ? dwVal2 dd ? xVal da ? ends Code: struct T_DUMMY dwVal1 dd ? dwVal2 dd ? if WIN64 = 0 label xVal : dword dd ? else label xVal : qword dq ? end if ends Code: struct T_DUMMY dwVal1 dd ? dwVal2 dd ? label xVal : SIZE_xVal if WIN64 = 0 dd ? else dq ? end if SIZE_xVal = $ - xVal ends fabbel wrote: ... above def works using "naive" / "basic" implementation though (in utility/struct.inc) ... |
|||
03 Apr 2023, 06:45 |
|
fabbel 12 Apr 2023, 15:24
Hi Tomasz
Kept thinkin / workin on this... and finally managed a workaround - even if a bit convoluted i must admit ... => basically, it's reading/pushing the struct def as a string into a virtual bloc using a macro ?, which is executed afterwards using eval ... I have done some testing with basic as well as fasm1-compatibility struct implementations, and seem to work pretty well... ... maybe it's just me, but I find it more intutitive like this - hence posting back here ... happy to get feedback / expert comments (note that i extended a bit the syntax, allowing struct def. closing with 'end struct' / and [sub-]union closing with 'end union' [alt. endu] - which, to me again, looked more fasmg-ish) XStruct.inc Code: @XStruct?:: macro @XStruct?.Init? local __xstruct, __symlinks __xstruct.Mode = 0 ; assume struct impl = basic impl. by default ... irpv any, struct ; ... or assume (extended) fasm1 compatibility impl. if symbol 'struct' is definite __xstruct.Mode = 1 ; ... i.e. to adjust union closing marker accordingly => 'endu' or 'ends' break end irpv define __symlinks macro:end:define match _macro:_end:define, __symlinks namespace __xstruct ShowDef = 0 ExecDef = 1 define Settings ShowDef define Settings ExecDef SDef = 0 SDef.Nst = 0 ; 0=close def, 1=struct, 2=union _macro end! arg* END arg _end macro _end namespace end match macro __xstruct.show_settings display '> XStruct settings:',13,10 irpv _setting, __xstruct.Settings display '* ', `_setting,': ' if _setting display 'on' else display 'off' end if display 13,10 end irpv end macro macro __xstruct.settings args*& local _xsetting_def iterate _arg, args redefine _xsetting_def irpv _setting, __xstruct.Settings rawmatch =+=_setting, _arg _xsetting_def equ _setting = 1 break else rawmatch =_setting, _arg _xsetting_def equ _setting = 1 break else rawmatch =-=_setting, _arg _xsetting_def equ _setting = 0 break end rawmatch end irpv match _xdef, _xsetting_def _xdef else err 'Unexpected XStruct setting: ', `_arg end match end iterate end macro macro @XStruct?.Settings? args& match , args __xstruct.show_settings else __xstruct.settings args end match end macro macro __xstruct.struct? sdecl*& virtual at 0 match _sdecl, sdecl db 'struct ',`_sdecl,13,10 end match __xstruct.SDef = 0 __xstruct.SDef.Nst =: 1 mvmacro ends?, __xstruct.ends mvmacro endu?, __xstruct.endu mvmacro ?, __xstruct.collect_def end macro macro __xstruct.collect_def? line& rawmatch =END _arg, line if _arg = __xstruct.SDef.Nst if __xstruct.Mode = 1 | _arg = 1 db 'ends',13,10 else db 'endu',13,10 end if restore __xstruct.SDef.Nst if __xstruct.SDef.Nst = 0 load __xstruct.SDef:$ from 0 end virtual mvmacro __xstruct.collect_def, ? mvmacro __xstruct.ends, ends? mvmacro __xstruct.endu, endu? if __xstruct.ShowDef __xstruct.show_def end if if __xstruct.ExecDef __xstruct.exec_def end if end if else if _arg = 1 err 'Unexpected <end struct>' else if _arg = 2 err 'Unexpected <end union / endu>' else err 'Unexpected <',`line,'>' end if else db `line, 13,10 rawmatch =struct?, line __xstruct.SDef.Nst =: 1 else rawmatch =union?, line __xstruct.SDef.Nst =: 2 end rawmatch end rawmatch end macro macro __xstruct.ends?! repeat 1 _nst:__xstruct.SDef.Nst __xstruct.end _nst end repeat end macro macro end?.struct?! __xstruct.end 1 end macro macro end?.union?! __xstruct.end 2 end macro macro __xstruct.endu?! __xstruct.end 2 end macro macro __xstruct.show_def repeat 1, _len:lengthof __xstruct.SDef display '> struct def (',`_len,' bytes):',13,10,__xstruct.SDef, 13,10 end repeat end macro macro __xstruct.exec_def mvmacro __xstruct.struct, struct eval __xstruct.SDef mvmacro struct, __xstruct.struct end macro mvmacro struct, __xstruct.struct purge @XStruct?.Init? end macro @XStruct.Init test.asm Code: ;include 'utility/struct.inc' include 'x86/include/macro/struct.inc' include 'XStruct.inc' ;@XStruct.Settings +ShowDef @XStruct.Settings ; basic struct T_POINT x dd ? y dd ? ends ; mixing ends/endu/end struct/end union - just for the sake of validation... ; - this one only to test with (extended) fasm1-compatibility impl. ; - comment-out for basic impl. struct T_LINE union tStart T_POINT struct x1 dd ? y1 dd ? ends endu union tEND T_POINT struct x2 dd ? y2 dd ? end struct end union end struct tLine T_LINE tStart:<0,0>, y2:0 ; testing with if WIN64 = 1 struct T_DUMMY dwVal1 dd ? dwVal2 dd ? if WIN64 = 0 xVal dd ? else xVal dq ? end if ends tDummy T_DUMMY dwVal1:0,xVal:0 ; testing with iterate struct T_TESTiter a dd ? b dd ? iterate sec, DATA,CODE,UDATA sec.BinSize dd ? sec.VMSize dd ? end iterate c dd ? end struct tTest T_TESTiter a:32, DATA.BinSize:255, DATA.BinSize:1024, c:-1 ; testing with repeat struct T_TESTrept a dd ? b dd ? repeat 4 dwVal#% dd ? end repeat c dd ? end struct tTest2 T_TESTrept a:1,dwVal4:55, c:258 |
|||
12 Apr 2023, 15:24 |
|
Tomasz Grysztar 12 Apr 2023, 20:16
Funny how I made it harder for myself by making assumptions that from you point of view are (understandably!) not natural. I wanted it to behave similar to STRUC, a macro unrolled every time at instantiation, so I used elaborate tricks to ensure that control directives would not be evaluated at definition time, only during instantiation. But if you consider STRUCT to be just a static definition of rigid data structure, then obviously it makes much more sense to have control directives like IF operate during the definition, not later.
I believe that this - likely wiser - set of assumptions allows for a simpler implementation (maybe something similar to the one in the very first post in this thread). Yours might be a good direction, too, but I'm not sure why you'd need EVAL there. I consider it kind of "last resort" tool. |
|||
12 Apr 2023, 20:16 |
|
Tomasz Grysztar 13 Apr 2023, 10:02
I prepared an example of how I would begin implementing STRUCT under the alternate assumptions. To keep it simple, just the basic fasm-compatible syntax and no substructures/unions. But even with all the compatibility features added it should not become very complex, it is really much less tricky with this approach:
Code: include 'xcalm.inc' define struct? struct? macro struct? name* define struct?.NAME name struct?.new namespace name virtual at 0 mvstruc ?, struct?.field mvmacro ?, struct?.collect end macro macro ends? mvmacro struct?.collect, ? mvstruc struct?.field, ? match name, struct?.NAME sizeof.name := $ end match end virtual end namespace struct?.declare end macro namespace struct? define NAME define BODY define DECL define LINE PARAM = 0 calminstruction new? arrange DECL, =struc NAME compute PARAM, 0 take , BODY end calminstruction calminstruction collect? line& arrange LINE, line assemble line take BODY, LINE end calminstruction ; Name pool for macro parameters: repeat 26, i:0 eval 'define ?',`i,' __','a'+i end repeat calminstruction (name) field definition& local type, default, param arrange param, struct.PARAM compute PARAM, PARAM+1 transform param match type default?, definition arrange DECL, DECL param:<default>, arrange LINE, .name type param arrange definition, name definition assemble definition end calminstruction calminstruction declare local buffer, line reverse: take buffer, BODY jyes reverse match DECL=,, DECL assemble DECL ; Just for debugging: stringify DECL display DECL display 10 arrange line, =label . : =sizeof.NAME assemble line definition: take line, buffer jno finish assemble line ; Just for debugging: stringify line display 9 display line display 10 jump definition finish: asm end struc end calminstruction end namespace BITS = 64 struct POINT if BITS = 64 x dq ? else x dd ? end if if BITS = 64 y dq ? else y dd ? end if ends struct OCTAGON repeat 8 vertex#% POINT end repeat ends example OCTAGON <10,11>,<20,21>,<30,31>,<40,41>,<50,51>,<60,61>,<70,71>,<80,81> Last edited by Tomasz Grysztar on 13 Apr 2023, 12:31; edited 2 times in total |
|||
13 Apr 2023, 10:02 |
|
fabbel 13 Apr 2023, 11:08
Hi
More than happy to get your feedback ! Will try your new example. Answering to your prev msg, just couple of (humble) remarks, to maybe clarify my earlier perspective - about the code I submitted previously : * Indeed, as you mentionned, I view STRUCT as "just a static definition of rigid data structure", which shud work 'naturally' with control directives (greatly appreciate you saw some legitimate use there - esp since considering myself as a newbie ! ;-P) * I didn't want to re-invent the wheel: your struct impls. - either basic or extended fasm1 compatible - were working perfectly * I do not have enough expertise (yet?) to fully understand your struct impls. and how to tweak it to my needs - esp. reg. CALM... which I am still struggling with * Then, I figured out that maybe I did not even need to spend all the time and effort to do this : maybe I could simply try to somehow 'override' your base impl. - i.e. just adding a layer on top of it with some extra functionalitites, while being able to call that base impl. to do the core of the job * This is how EVAL solution came to mind : even if kinda 'brute force' and not the most efficient, as I fully reckon, it allows to build a curated 'raw script' that can then be fed to the 'base' impl. * Plus, I cud make this as agnostic as poss reg. 'base' impl., ideally looking for it to work 'transparently' with both impls (by just a matter of changing the included strcut.inc version) * Pbly i/o of building it as a string in a virtual block + giving that to EVAL, i cud store it in a stacked variable that would then be executed via IRPV, but this proved not so straightforward as per my early attempts - still trying to figure out how to do it... (think issues with getting unconditional macros expanded/overriden correctly + seeing if/where ESC may be needed ...) * ultimatey, the new sketch you just sent kinda support my above assessement: reimplementing it is currently beyond me .... Many thanx for considering anyhow ! |
|||
13 Apr 2023, 11:08 |
|
Overclick 13 Apr 2023, 11:09
Too difficult, too unreadable to do simple things that can be implemented by simple solutions.
About If: Code: if WIN64 = 0 xVal dd ? else xVal dq ? end if Code: cpumode equ 64 match =64, cpumode { xVal dq ? } match =32, cpumode { xVal dd ? } |
|||
13 Apr 2023, 11:09 |
|
fabbel 13 Apr 2023, 11:20
.... point is to have this working inside STRUCT def..... sorry if I fail to see how the above helps....
|
|||
13 Apr 2023, 11:20 |
|
Tomasz Grysztar 13 Apr 2023, 11:31
fabbel wrote: * ultimatey, the new sketch you just sent kinda support my above assessement: reimplementing it is currently beyond me .... Also, the debugging DISPLAY commands help by showing the important lines of the produced definition. The example I included earlier: Code: BITS = 64 struct POINT if BITS = 64 x dq ? else x dd ? end if if BITS = 64 y dq ? else y dd ? end if ends struct OCTAGON repeat 8 vertex#% POINT end repeat ends Code: flat assembler version g.jz27 struc POINT __a:?, __b:? .x dq __a .y dq __b struc OCTAGON __a:, __b:, __c:, __d:, __e:, __f:, __g:, __h: .vertex#1 POINT __a .vertex#2 POINT __b .vertex#3 POINT __c .vertex#4 POINT __d .vertex#5 POINT __e .vertex#6 POINT __f .vertex#7 POINT __g .vertex#8 POINT __h |
|||
13 Apr 2023, 11:31 |
|
ProMiNick 13 Apr 2023, 11:48
(only my opinion)
that Code: struc DA? values& if WIN64 = 0 . dd values else . dq values end if end struc because conditions inside of struct definitions looks ugly in case of octagon such syntax would be look cleaner (repeats not so ugly as conditions, but unwanted) Code: struct OCTAGON vertex[8] POINT ; under fasm I realize that array extension of structs ends |
|||
13 Apr 2023, 11:48 |
|
Roman 13 Apr 2023, 11:52
vertex POINTArray 8
Or this: vertex dim 8 Or: Vertices 8 ;in vertices hidden 8 POINT My idea in calm must implemented user rules for behavior in macro ! User write own determinants. |
|||
13 Apr 2023, 11:52 |
|
Tomasz Grysztar 13 Apr 2023, 12:26
ProMiNick wrote: in case of octagon such syntax would be look cleaner (repeats not so ugly as conditions, but unwanted) Code: macro struct? name struct name calminstruction ?! definition& local size, item, i match name [size] item, definition jno pass compute i, 0 repeat: arrange definition, name#i item assemble definition compute i, i + 1 check i = size jno repeat exit pass: assemble definition end calminstruction end macro macro ends? purge ? ends end macro struct OCTAGON vertex[8] POINT ends |
|||
13 Apr 2023, 12:26 |
|
Tomasz Grysztar 13 Apr 2023, 16:50
fabbel wrote: * Then, I figured out that maybe I did not even need to spend all the time and effort to do this : maybe I could simply try to somehow 'override' your base impl. - i.e. just adding a layer on top of it with some extra functionalitites, while being able to call that base impl. to do the core of the job Code: include 'macro/struct.inc' DEBUG = 1 calminstruction calminstruction?.DEBUG? command& check DEBUG = 0 jyes skip assemble command skip: end calminstruction struct?.XSTRUCT = 0 calminstruction struct? declaration* arrange declaration, =struct declaration check struct?.XSTRUCT = 0 jyes override assemble declaration exit override: compute struct?.XSTRUCT, 1 take struct?.BODY, declaration asm mvmacro ?, struct?.xstruct end calminstruction macro ends?! end struct end macro calminstruction struct?.xstruct line& match =end? =struct?, line jyes ends match =struct?, line jno collect compute struct?.XSTRUCT, struct?.XSTRUCT + 1 take struct?.BODY, line exit collect: arrange line, #line take struct?.BODY, line exit ends: arrange line, =ends take struct?.BODY, line check struct?.XSTRUCT = 1 jyes ready compute struct?.XSTRUCT, struct?.XSTRUCT - 1 exit ready: asm mvmacro struct?.xstruct, ? local buffer reverse: take buffer, struct?.BODY jyes reverse commit: take line, buffer jno finish assemble line DEBUG stringify line DEBUG display line DEBUG display 10 jump commit finish: compute struct?.XSTRUCT, 0 end calminstruction BITS = 64 struct POINT if BITS = 64 x dq ? else x dd ? end if if BITS = 64 y dq ? else y dd ? end if ends struct OCTAGON repeat 8 vertex#% POINT end repeat ends example OCTAGON <10,11>,<20,21>,<30,31>,<40,41>,<50,51>,<60,61>,<70,71>,<80,81> another OCTAGON vertex3:<4,8> |
|||
13 Apr 2023, 16:50 |
|
fabbel 14 Apr 2023, 12:36
Very useful indeed !
Tx ! |
|||
14 Apr 2023, 12:36 |
|
Tomasz Grysztar 14 Dec 2023, 14:22
The newly added feature allows to clean up the issues with the above wrapper. It's enough to add the "&" prefix in
Code: calminstruction struct?.xstruct line& Code: calminstruction struct?.xstruct &line& Code: arrange line, #line |
|||
14 Dec 2023, 14:22 |
|
fabbel 14 Dec 2023, 15:01
.. was thinkin about that indeed ! ;-P
|
|||
14 Dec 2023, 15:01 |
|
Tomasz Grysztar 01 Feb 2024, 21:25
In the fasm2 package I'm now including a modified variant of STRUCT macro, cleaned up thanks to the new features of fasmg, which allows structure definitions to be affected by control directives while they are defined.
|
|||
01 Feb 2024, 21:25 |
|
ProMiNick 02 Feb 2024, 17:28
struct redefinition - could it be solved. struct define labels, not symbolic vars. redefinition of labels cause error.
|
|||
02 Feb 2024, 17:28 |
|
Goto page Previous 1, 2, 3 Next < Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2024, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.