flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > [FULL SUCCESS]assembly time control on struct fields offsets

Author
Thread Post new topic Reply to topic
ProMiNick



Joined: 24 Mar 2012
Posts: 802
Location: Russian Federation, Sochi
ProMiNick 04 Jul 2022, 19:45
Code:
; Macroinstructions for defining data structures

def.rb equ db
def.rw equ dw
def.rd equ dd
def.rp equ dp
def.rq equ dq
def.rt equ dt

local@offbase = 0
local@eaxIndex = 0
local@ebxIndex = 0
local@ecxIndex = 0
local@edxIndex = 0
local@ediIndex = 0
local@esiIndex = 0
local@espIndex = 0
local@ebpIndex = 0
varbase equ eax*local@eaxIndex+ebx*local@ebxIndex+ecx*local@ecxIndex+edx*local@edxIndex+edi*local@ediIndex+esi*local@esiIndex+esp*local@espIndex+ebp*local@ebpIndex+local@offbase

macro disphex pretext,posttext,number*,digits:8 {
        display pretext
        repeat digits
                digit = ((number) shr ((digits-%) shl 2)) and 0Fh
                if digit < 10
                        display '0'+digit
                else
                        display 'A'+digit-10
                end if
        end repeat
        display posttext
}

struc reequ value { local tmp
        tmp equ value
        restore .
        . equ tmp }

macro redefine statement { local tmp,tmp2
        tmp equ
        tmp2 equ
        irps n,statement \{
                match any,tmp \\{ tmp2 equ tmp2 \n \\}
                match ,tmp \\{ define tmp n\\} \}
        match tmp3,tmp \{
                match tmp4,tmp2 \\{
                        restore tmp3
                        define tmp3 tmp4 \\} \} }


macro definefield@struct name,field,type,def {
        local ..fielddef
        if ~ fielddef eq .
                ..fielddef: name#field type def
                sizeof.#name#field = $ - ..fielddef
        else
                label name#.#type
                rb sizeof.#type
        end if }

macro applyfield@struct name,field,type,def,value {
        match    , value \{ field type def \}
        match any, value \{ \local ..field
                ..field: field type value
                if ~ field eq .
                        rb sizeof.#name#field - ($-..field)
                end if \} }

macro struct definition {
        match name tail, definition: \{
                virtual
                        db \`name
                        load initial@struct byte from $$
                        if initial@struct = '.'
                                display 'Error: name of structure should not begin with a dot.',0Dh,0Ah
                                err
                        end if
                end virtual

                macro ends \\{
                        match , sub@struct \\\{
                                if $
                                        display 'Error: definition of ',\`name,' contains illegal instructions.',0Dh,0Ah
                                        err
                                end if

                                restruc db,dw,du,dd,dp,dq,dt
                                restruc rb,rw,rd,rp,rq,rt
                                purge db,dw,du,dd,dp,dq,dt
                                purge rb,rw,rd,rp,rq,rt
                                purge union,struct,ends


                                irpv fields,field@struct \\\\{
                                        restore field@struct
                                 \\\\common
                                        restore @struct
                                        make@struct name,fields
                                        define fields@\#name fields \\\\}
                                end virtual \\\}
                        match any, sub@struct \\\{ field@struct reequ field@struct> \\\}
                        restore sub@struct \\}
                match parent:,tail \\{ field@struct equ fields@\\#parent \\} \}
        irp d@,db,dw,du,dd,dp,dq,dt \{
                struc d@ [val] \\{ \\common define field@struct .,d@,<val> \\}
                macro d@ [val] \\{ \\common \\local anonymous
                                            define field@struct anonymous,d@,<val> \\} \}

        irp r@,rb,rw,rd,rp,rq,rt \{
                match d@,def.#r@ \\{
                        struc r@ count \\\{ \\\local offset,size
                                             define field@struct .,d@,count dup (?) \\\}
                        macro r@ count \\\{ \\\local anonymous
                                             define field@struct anonymous,d@,count dup (?) \\\} \\} \}

        irp sub@,union,struct \{
                macro sub@ \\{
                        field@struct equ ,sub\#sub@,<
                        sub@struct equ sub\#sub@ \\} \}

        define @struct
        sub@struct equ
        virtual at 0 }

macro make@struct name,[field,type,def]
 { common local define
        define equ name
   forward local sub
        match , field \{
                make@substruct type,name,sub def
                         define equ define,.,sub, \}
        match any, field \{ define equ define,.#field,type,<def> \}
   common
        match fields, define \{ define@struct fields \} }

macro define@struct name,[field,type,def]
 { common local list
        list equ
   forward local value
        ;definefield@struct name,field,type,def      ;wanted to be simplified
        if ~ field eq .                              ;instead of that
                local ..fielddef                     ;
                ..fielddef: name#field type def      ;
                sizeof.#name#field = $ - ..fielddef  ;
        else                                         ;
                label name#.#type                    ;
                rb sizeof.#type                      ;
        end if                                       ;
        match any, list \{ list equ list, \}
        list equ list <value>
   common
        sizeof.#name = $
        restruc name
        match values, list \{
        macro name value \\{
        match , @struct \\\{ \\\local anonymous
                                  define field@struct anonymous,name,<values> \\\}
        match no, @struct \\\{
   forward
                                ;applyfield@struct name,,type,def,value             ;wanted to be simplified
                                match , value \\\\{ type def \\\\}                  ;instead of that
                                match any, value \\\\{ \\\\local ..field            ;
                                        ..field: type value                         ;
                                        if ~ field eq .                             ;
                                                rb sizeof.#name#field - ($-..field) ;
                                        end if \\\\}                                ;
   common \\\} \\}
                struc name value \\{ \\local \\..base
                        match , @struct \\\{ define field@struct .,name,<values> \\\}
                        match no, @struct \\\{
                                ..base: virtual
   forward
                                        field type def                               ;
   common
                                end virtual
                                name value
                        label . at \\..base \\\} \\} \} }

macro enable@substruct
 {      macro make@substruct substruct,parent,name,[field,type,def]\{
         \common \local define
        define equ parent,name
         \forward \local sub
                match , field \\{
                        match any, type \\\{
                                enable@substruct
                                               make@substruct type,parent,sub def
                                               purge make@substruct
                                               define equ define,.,sub, \\\} \\}
        match any, field \\{ define equ define,.\#field,type,<def> \\}
       \common
        match fields, define \\{ define@\#substruct fields \\} \} }

enable@substruct

macro define@subunion parent,name,[field,type,def]
 { common local field@end
        virtual at parent#.#name
                field@end = $
   forward local value
                ;definefield@struct parent,field,type,def         ;wanted to be simplified
                if ~ field eq .                                   ;instead of that
                        local ..fielddef                          ;
                        ..fielddef: parent#field type def         ;
                        sizeof.#parent#field = $ - ..fielddef     ;
                else                                              ;
                        label parent#.#type                       ;
                        type def ; why not rb sizeof.#type????    ;
                end if                                            ;
                if field@end <$
                        field@end = $
                end if
        end virtual
        virtual at parent#.#name
   common
                sizeof.#name = field@end - $$
        end virtual

        macro name [value] \{ \common local ..union
                first@union equ
   forward
                match , first@union \\{
                        match , value \\\{ first@union equ type def \\\}
                        match any, value \\\{ first@union equ type value \\\} \\}
   common
                        ..union: first@union
                        rb sizeof.#name - ($ - ..union) \}
        struc name [value] \{ \common label .\#name
   forward
                virtual
                               field type def
                end virtual
   common
                name value \} }

macro define@substruct parent,name,[field,type,def]
 { common
    virtual at parent#.#name
   forward local value
                ;definefield@struct parent,field,type,def        ;wanted to be simplified
                if ~ field eq .                                  ;instead of that
                        local ..fielddef                         ;
                        ..fielddef: parent#field type def        ;
                        sizeof.#parent#field = $ - ..fielddef    ;
                else                                             ;
                        label parent#.#type                      ;
                        rb sizeof.#type                          ;
                end if                                           ;
   common
                sizeof.#name = $ - parent#.#name
    end virtual
        macro name value \{ \local ..anonymous
   forward
                ;applyfield@struct parent,,type,def,value               ;wanted to be simplified
                match , value \\{  type def \\}                         ;instead of that
                match any, value \\{ \\local ..field                    ;
                        ..field: type value                                      ;
                        if ~ field eq .                                 ;
                                rb sizeof.#parent#field - ($-..field)   ;
                        end if \\}                                      ;
   common \}
        struc name value \{ label .\#name
                virtual
   forward
                        field type def
   common
                end virtual
                name value \} }

struct SYSTEM_INFO
  union
    dwOemId                   dd ?
    struct
      wProcessorArchitecture  dw ?
      wReserved               dw ?
    ends
  ends
  dwPageSize                  dd ?
  lpMinimumApplicationAddress dd ?
  lpMaximumApplicationAddress dd ?
  dwActiveProcessorMask       dd ?
  dwNumberOfProcessors        dd ?
  dwProcessorType             dd ?
  dwAllocationGranularity     dd ?
  wProcessorLevel             dw ?
  wProcessorRevision          dw ?
ends

;struct SYSTEM_INFO2 SYSTEM_INFO
;  union
;    dwAOemId                   dd ?
;    struct
;      wAProcessorArchitecture  dw ?
;      wAReserved               dw ?
;    ends
;  ends
;  dwAPageSize                  dd ?
;  lpAMinimumApplicationAddress dd ?
;  lpAMaximumApplicationAddress dd ?
;  dwAActiveProcessorMask       dd ?
;  dwANumberOfProcessors        dd ?
;  dwAProcessorType             dd ?
;  dwAAllocationGranularity     dd ?
;  wAProcessorLevel             dw ?
;  wAProcessorRevision          dw ?
;ends

;A SYSTEM_INFO
;B SYSTEM_INFO2
;db SYSTEM_INFO2.wAProcessorRevision,SYSTEM_INFO2.wAReserved,SYSTEM_INFO2.wReserved,SYSTEM_INFO2.dwAOemId,SYSTEM_INFO2.dwOemId

;macro dispsymbol [symbol] {
;        local proxy
;        define proxy symbol
;        match name, proxy \{ display \`name,':' \}
;        match content, symbol \{
;                irps token,content \\{ display \\`token,' '
;                \\}
;                display ';'
;                match content2, content \\{
;                        irps token,\\content2 \\\{ display \\\`token,' ' \\\} \\}
;                \}
;      display ';',13,10 }

;macro dumpstructfields [name] { forward dispsymbol fields@#name }

;dumpstructfields SYSTEM_INFO2 ;fields@SYSTEM_INFO2:,subunion ,<,dwOemId ,dd,<?>,,substruct ,<,wProcessorArchitecture ,dw,<?>,wReserved ,dw,<?>>>,dwPageSize ,dd,<?>,lpMinimumApplicationAddress ,dd,<?>,lpMaximumApplicationAddress ,dd,<?>,dwActiveProcessorMask ,dd,<?>,dwNumberOfProcessors ,dd,<?>,dwProcessorType ,dd,<?>,dwAllocationGranularity ,dd,<?>,wProcessorLevel ,dw,<?>,wProcessorRevision ,dw,<?>,,subunion ,<,dwAOemId ,dd,<?>,,substruct ,<,wAProcessorArchitecture ,dw,<?>,wAReserved ,dw,<?>>>,dwAPageSize ,dd,<?>,lpAMinimumApplicationAddress ,dd,<?>,lpAMaximumApplicationAddress ,dd,<?>,dwAActiveProcessorMask ,dd,<?>,dwANumberOfProcessors ,dd,<?>,dwAProcessorType ,dd,<?>,dwAAllocationGranularity ,dd,<?>,wAProcessorLevel ,dw,<?>,wAProcessorRevision ,dw,<?>;

macro locals {
        macro label def \{ match . type,def> \\{ deflocal@proc .,label,<type \\} \}
        irp d@,db,dw,du,dd,dp,dq,dt \{
                struc d@ [val] \\{ \\common deflocal@proc .,d@,val \\} \}
        irp r@,rb,rw,rd,rp,rq,rt \{
                struc r@ count \\{ \\common deflocal@proc .,r@,count \\} \} }

macro deflocal@proc name,def,[val] { name def val }

macro deflocal@proc name,def,[val]
 { common
    match vars, all@vars \{ all@vars equ all@vars, \}
    all@vars equ all@vars name
   forward
    local ..var,..tmp
    ..var def val
    match =?, val \{ ..tmp equ \}
    match any =?, val \{ ..tmp equ \}
    match any (=?), val \{ ..tmp equ \}
    match =label, def \{ ..tmp equ \}
    match tmp : value, ..tmp : val
     \{ display 'initlocals deprecated',13,10,'due to nature of stack',13,10
        err stack can`t be initialized, only directly modified in realtime \}
   common
    local proxy
    match first rest, ..var, \{
    name equ first +varbase
    ;disphex '',<' ',`name,13,10>,first
    \} }

struc label type { label . type }

locals

d SYSTEM_INFO

use32
align $10
local@offbase = 0
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize] where d.dwPageSize=4
align $10
local@offbase = 6
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize+6] where d.dwPageSize=4
align $10
local@espIndex = 1
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize+esp+6] where d.dwPageSize=4
align $10
local@ebpIndex = 4
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize+esp+ebp*4+6] where d.dwPageSize=4
align $10
local@espIndex = 0
local@offbase = local@offbase+$50
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize+ebp*4+$56] where d.dwPageSize=4
align $10
db 0    

_________________
I don`t like to refer by "you" to one person.
My soul requires acronim "thou" instead.
Post 04 Jul 2022, 19:45
View user's profile Send private message Send e-mail Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 802
Location: Russian Federation, Sochi
ProMiNick 06 Jul 2022, 22:00
I`m glad to inform that state of combining struct mechanism with variable base is changed and finished.
Content of initial topic is replaced with final successfull state.
(in initial post struct was defined relative $, but here only test part of rebasing struct that related via register):
Code:
...
virtual at esp
d SYSTEM_INFO
end virtual
use32
align $10
local@offbase = 0
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize] where d.dwPageSize=esp+4
align $10
local@offbase = 6
assert d.dwPageSize relativeto esp
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize+6] where d.dwPageSize=esp+4
align $10
local@espIndex = -1
assert d.dwPageSize relativeto $
assert d.dwPageSize relativeto 0
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize-esp+6] where d.dwPageSize=esp+4
align $10
local@ebpIndex = 4
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize-esp+ebp*4+6] where d.dwPageSize=esp+4
align $10
local@espIndex = 0
local@offbase = local@offbase+$50
assert d.dwPageSize relativeto ebp*4+esp
mov eax,[d.dwPageSize];compiled as mov eax,[d.dwPageSize+ebp*4+$56] where d.dwPageSize=esp+4
align $10
db 0     
Post 06 Jul 2022, 22:00
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20421
Location: In your JS exploiting you and your system
revolution 07 Jul 2022, 04:08
Congrats.

Where can this be used?
Post 07 Jul 2022, 04:08
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 802
Location: Russian Federation, Sochi
ProMiNick 07 Jul 2022, 05:45
mainly for win32:
Code:
ShellExtInit@AddRef: procedure(Self)
        sub     [Self], current_COMobject.SEI ; we cant create ebp frame here it will break logic
ShellPropSheetExt@AddRef: ;procedure(Self)
        mov     eax, [Self]                      ; just a luck that continuing esp frame here is shorter 1 byte due to only 1 use of args or locals
        add     eax, current_COMobject.RefCount
        invoke  InterlockedIncrement, eax
        ret
endp

ShellExtInit@Release: procedure(Self)
        sub     [Self], current_COMobject.SEI  ; again we cant create ebp frame here it will break logic
ShellPropSheetExt@Release: procedure(Self)
        mov     eax, [Self]                    ; just a luck that continuing esp frame here is same as ebp frame due to only 2 uses of args or locals
        add     eax, current_COMobject.RefCount
        invoke  InterlockedDecrement, eax
        test    eax, eax
        jnz     .locret
        push    ebx
        mov     eax, [Self]
        push    eax
        push    [eax+current_COMobject.lpFileName]
        call    PDClassFactory@CreateInstance.free
        call    PDClassFactory@CreateInstance.free
        pop     ebx
        invoke  InterlockedDecrement, ServerLockCount
      .locret:
        ret
endp

; here combining together with "sub     [Self], current_COMobject.SEI" economy for us
; mov    eax, [Self]
; sub    eax, current_COMobject.SEI
; invoke ShellPropSheetExt@AddRef,eax
; ret
; and economy
; mov    eax, [Self]
; sub    eax, current_COMobject.SEI
; invoke ShellPropSheetExt@Release,eax
; ret    

it was just 1 example.
we could use procedure chunks (use parts of procs for another procs) and we not limited to use chunks without ebp only or with ebp only, we could combine them together & increase code readability in own trickery form.
yes for good realization of chunks we will needed modification of proc macroset but it mostly trivial after gaining ability of controling struct field members offsets.
And my fasmpack project at current state partialy unworked (because sintax used features that was not realized) - it is bad to be package targeted to newbies and contain bugs inside.
I plan to reuse this feature in kolibri, wince & in linux examples (and I still don`t added GUI linux ones because of switching my attention to rebase structures on fly)
Post 07 Jul 2022, 05:45
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20421
Location: In your JS exploiting you and your system
revolution 07 Jul 2022, 05:51
I don't follow.

What is "procedure(Self)"? Where are you using the macros in the first post?
Post 07 Jul 2022, 05:51
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 802
Location: Russian Federation, Sochi
ProMiNick 07 Jul 2022, 06:56
nature of procedure is labeled code.
so for cases when we don`t suppose variant where procedure budy could be skipped
we use form:
Code:
procname: procedure() ; looks same as just "procname:" with comment that this is procedure    
but in case
Code:
procname: procedure(args) ; we could define args relative to esp or/and ebp    
for case where procedure body could be never used - next form:
Code:
procname procedure(args) ; : - skipped, now procedure is struc not macro, args defined same    

what macro/struc procedure itself?
Code:
macro procedure definition& {
        match (args),definition \{ proc@parameters args \}
        match (),definition \{ proc@parameters \} }

struc procedure definition& {
        close@@ equ end if ; later used as match first rest,close@@ { close@@ }, in undefined state nothing for rest. than release close@@
        if used .
        .:
        procedure definition }    

"macro proc@parameters statement" is mostly clone of classical "macro define@proc name,statement"
that is was syntax I used but not realized completely (as thou guess there is esp frame based and it required struct rebasing, because every change of esp affect whole locals & args offsets)
Quote:
Where are you using the macros in the first post?

I will share everything when I finish.
Post 07 Jul 2022, 06:56
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20421
Location: In your JS exploiting you and your system
revolution 07 Jul 2022, 07:12
Okay. I am keen to see how these macros make things easier.

But brackets and colons are harder to type than commas.
Code:
proc name,arg1,arg2 ; easier to type    
Post 07 Jul 2022, 07:12
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.