flat assembler
Message board for the users of flat assembler.

Index > Main > How to make union for local variables?

Author
Thread Post new topic Reply to topic
CoolCmd



Joined: 27 Dec 2023
Posts: 11
CoolCmd 27 Dec 2023, 10:16
to reduce stack consumption i need something like this:
Code:
proc p1
  locals
  union ; <-- error: illegal instruction
    s1 LARGESTRUCT ?
    buf1 rb 100
  ends
  endl
endp
    


how???
Post 27 Dec 2023, 10:16
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1051
Location: Russia
macomics 27 Dec 2023, 10:47
Code:
struc LARGESTRUCT name { label .
  .name db name
  .res db 99 dup (0)
  label .Length at $ - .
}

struc assume base*, type& { if ~ type eq
    virtual at base
      . type
      if ~ definite .Length
        label .Length at $ - $$
      end if
    end virtual
  else
    label . at base
    label .Length at 0
  end if }

sl LARGESTRUCT ?
bufl assume sl, db sl.Length dup (?)    
Post 27 Dec 2023, 10:47
View user's profile Send private message Reply with quote
CoolCmd



Joined: 27 Dec 2023
Posts: 11
CoolCmd 27 Dec 2023, 12:04
macomics, your code does not do what i need.

i need universal way for any data types, including already defined standard Windows structures. members of the union must have different sizes.
Post 27 Dec 2023, 12:04
View user's profile Send private message Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1051
Location: Russia
macomics 27 Dec 2023, 13:06
CoolCmd wrote:
i need universal way for any data types, including already defined standard Windows structures. members of the union must have different sizes.

That 's why it was declared .Length. Find the maximum value and reserve the remaining bytes in the remaining structures.
This works with any structures, including those announced in advance.
Code:
include 'WIN32A.INC'
struc assume base*, type& { if ~ type eq
    virtual at base
      . type
      if ~ definite .Length
        label .Length at $ - $$
      end if
    end virtual
  else
    label . at base
    label .Length at 0
  end if }

point1 POINT
label point1.Length at $ - point1
msg assume point1, MSG
a = msg.Length / 10
b = msg.Length - a * 10
display 'sizeof MSG = ', '0' + a, '0' + b, 13, 10
display 'sizeof POINT = ', point1.Length + '0', 13, 10
if point1.Length - msg.Length > 0
  reserved rb point1.Length - msg.Length
else if point1.Length - msg.Length < 0
  reserved rb msg.Length - point1.Length
end if
db $7b    
Code:
$ fasm -m 102400 testStruct.asm
flat assembler  version 1.73.32  (102400 kilobytes memory, x64)
sizeof MSG = 28
sizeof POINT = 8
2 passes, 29 bytes.

$ hexdump -C testStruct.bin
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 7b           |............{|
0000001d    
Of course, these calculations can be expressed in the form of a macro or other struc. Because only you know which fields should be combined

ADD: The second option. Automatically reserves space, but now assume will not work as intended. It should be applied immediately after the field that is being combined.
Code:
include 'WIN32A.INC'
struc union base*, type& { label .BaseLength at $ - base
  if ~ type eq
    virtual at base
      . type
      if ~ definite .Length
        label .Length at $ - $$
      end if
    end virtual
  else
    label . at base
    label .Length at 0
  end if
  if .Length - .BaseLength > 0
    rb .Length - .BaseLength
  end if }

struc MyStructure {
  .name db 60 dup ?
  .point1 POINT
  .msg union .point1, MSG
  .break db $2d
}

point1 POINT
label point1.Length at $ - point1
msg union point1, MSG
a = msg.Length / 10
b = msg.Length - a * 10
display 'sizeof MSG = ', '0' + a, '0' + b, 13, 10
display 'sizeof POINT = ', point1.Length + '0', 13, 10
db $7b
abc MyStructure
a = abc.name - abc
display 'Offset abc.name = ', '0' + a, 13, 10
a = (abc.point1 - abc) / 10
b = abc.point1 - abc - a * 10
display 'Offset abc.point1 = ', '0' + a, '0' + b, 13, 10
a = (abc.msg - abc) / 10
b = abc.msg - abc - a * 10
display 'Offset abc.msg = ', '0' + a, '0' + b, 13, 10
a = (abc.break - abc) / 10
b = abc.break - abc - a * 10
display 'Offset abc.break = ', '0' + a, '0' + b, 13, 10    
Code:
$ fasm -m 102400 testStruct.asm
flat assembler  version 1.73.32  (102400 kilobytes memory, x64)
sizeof MSG = 28
sizeof POINT = 8
Offset abc.name = 0
Offset abc.point1 = 60
Offset abc.msg = 60
Offset abc.break = 88
2 passes, 118 bytes.

$ hexdump -C testStruct.bin
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 7b 00 00 00  |............{...|
00000020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000070  00 00 00 00 00 2d                                 |.....-|
00000076    
Post 27 Dec 2023, 13:06
View user's profile Send private message Reply with quote
vityacv



Joined: 27 Oct 2012
Posts: 7
vityacv 28 Dec 2023, 21:39
Code:
DllMain:
struct DllMainStack
union
Test1 rd 100
Test2 rw 500
Test3 rw 1000
ends
ends
virtual at 0
rq 4
.union DllMainStack
align 16
rq 1
.locals = $-$$
rq 1
.hInstDLL rq 1
.Reason rq 1
.Reserved rq 1
end virtual
sub rsp,.locals
mov [rsp+.hInstDLL],rcx

lea rcx,[rsp+.union.Test1]
lea rcx,[rsp+.union.Test2]
lea rcx,[rsp+.union.Test3]

add rsp,.locals
ret    

or simple:
Code:
DllMain:
virtual at 0
rq 4
.Test1 rd 0
.Test2 rw 0
.Test3 rw 1000
align 16
rq 1
.locals = $-$$
rq 1
.hInstDLL rq 1
.Reason rq 1
.Reserved rq 1
end virtual
sub rsp,.locals
mov [rsp+.hInstDLL],rcx
lea rcx,[rsp+.Test1]
lea rcx,[rsp+.Test2]
lea rcx,[rsp+.Test3]
add rsp,.locals
ret
    
Post 28 Dec 2023, 21:39
View user's profile Send private message Reply with quote
Overclick



Joined: 11 Jul 2020
Posts: 670
Location: Ukraine
Overclick 29 Dec 2023, 08:00
Did you search in the macros thread?
I've already created such a macro
Code:
macro union autounion=0
{
        currentunion = $
        sizeofunion = autounion
        purge clone,endunion
        macro clone
        \{
                purge clone
                macro clone
                \\{
                        if $-currentunion > sizeofunion
                                sizeofunion = $-currentunion
                        end if
                        end virtual
                        virtual at currentunion
                \\}
                virtual at currentunion
        \}
        macro endunion
        \{
                if $-currentunion > sizeofunion
                        sizeofunion = $-currentunion
                end if
                end virtual
                if $-currentunion > sizeofunion
                        sizeofunion = $-currentunion
                end if
                if autounion > 0 & autounion < sizeofunion
                        display "Overflow fixed size of union.",13,10
                end if
                times sizeofunion-($-currentunion) db ?
        \}
}
    


example:
Code:
struc SomeStruc Lab=0,Param=0,Matrix=0
{       
        .adr                    dq Lab
        .param                  dd Param
                                        dd ?
                union 32
        .matrix                 dd Matrix
                clone
        .point1.X               dd ?
        .point1.Y               dd ?
        .point2.X               dd ?
        .point2.Y               dd ?
                clone
        .mesh                   db 24 dup(?)
                endunion
}    

Union can have any fixed size or auto size with different parts, types, etc.
Post 29 Dec 2023, 08:00
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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.