flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > advanced struct for fasmg

Thread Post new topic Reply to topic

Joined: 12 Apr 2005
Posts: 501
Location: Belarus
zhak 10 Apr 2017, 23:52
Long story short, I finally created advanced struct macro for fasm g, based on and inspired by Tomasz's example, which can do some cool things. Would be glad if you could test it away and point to any bugs or suggest optimizations.

Before I start describing the macro, I'd like to say my thanks to Tomasz for this wonderful engine. When I first tried it when it first appeared I was like yeah, okay, its interesting. But it took some time and learning effort to realize how extremely cool it is.

In its current implementation the macro may not work correctly with pe.inc from examples if relocations are present in output .exe. This is because I redefine standard data types like dd or dword and align macro. I myself don't use pe.inc from examples and at the moment didn't have enough time to test against it. Sorry. I'll tune this later, when come back from vacation (having a flight in the morning).

macro datatypes types&
  irp <size, type>, types
    @datatype.type equ ::type::
    sizeof.type = size
    macro type args:?&
      match [value], args
        local count
        count = +value
        emit size: count dup ?
        emit size: args
      end match
    end macro
    struc (__name__) type args:?&
      label .: size
      type args
      __name__.__size = size
      __name__.__length = $ - .
    end struc
  end irp
end macro

datatypes \
  1,db?, 2,dw?, 4,dd?, 6,dp?, 8,dq?, 10,dt?, 16,ddq?, 32,dqq?, 64,ddqq?
datatypes \
  1,byte?, 2,word?, 4,dword?, 6,fword?, 8,qword?, 10,tbyte?,\
  16,dqword?, 16,oword?, 32,qqword?, 32,yword?, 64,dqqword?, 64,zword?

macro datatypes_reservable types&
  irp <size, type>, types
    @datatype.type equ ::type::
    sizeof.type = size
    macro type value*
      local count
      count = +value
      emit size: count dup ?
    end macro
    struc (__name__) type value*
      label .: size
      type value
      __name__.__size = size
      __name__.__length = $ - .
    end struc
  end irp
end macro

datatypes_reservable \
  1,rb?, 2,rw?, 4,rd?, 6,rp?, 8,rq?, 10,rt?, 16,rdq?, 32,rqq?, 64,rdqq?

The above macros add some fields to standard data types, so that it's possible to use sizeof.db to get data type size (in bytes). For named variables it adds inner properties:

    __size - data size
    __length - length of initialized data

lipsum db 'Lorem ipsum'
lipsum.__size = 1
lipsum.__length = 11

It also adds the possibility to reserve data using the following syntax:
db [3]; the same as rb 3 or db 3 dup ?

The latter has been added just to introduce consistent look and feel for definition of structures and primitive data types

simple structure

struct POINT
  x dd ?
  y rd 1
end struct

point POINT x:1, y:2

structure in structure
struct LINE
  StartPoint POINT
  EndPoint POINT
end struct

line LINE StartPoint.x:1, StartPoint.y:2, EndPoint.x:5, EndPoint.y:6

arrays of primitives
struct LIST
  letters rb 4
end struct

; it's possible to fill the array with values
list1 LIST letters:<1,2,3,4>

; or it's possible to override data types to fill more array elements at once
list2 LIST letters:<word 0x1111, word 0x2222>
list3 LIST letters:<dword 0x44444444>

; it's also possible to use smaller datatypes to initialize the variable
; but in this case the value will be padded with zeroes to data type size
point2 POINT x:<word 0x5555>

; point2 POINT x:<word 0x5555, word 0x6666> is not allowed

; it's possible to address any item in the array separately
list4 LIST letters[0]: 'a', letters[1]: 'b', letters[2]: 'c'

; data type can be overriden, too
list5 LIST letters[2]: <word 0x7777>

arrays of structures
The same rules apply to variables which define structures
struct TWO_LINES
  lines LINE [2]
end struct

my_lines TWO_LINES lines[1].StartPoint.x: 1, lines[1].EndPoint.y: 5

Length of array can be obtained with __length property:

It is also possible to initialize array of structures.
In this case index of the structure should be added as .[index]
other_points POINT [2] .[0].x: 1, .[1].y:2

Finally, it's possible to initialize zero-length arrays. This could be useful when the last parameter in the structure has variable length. In this case only parameter name is created.
struct POINTS
  points_count db ?
  points POINT [0]
end struct

If zero-length parameter is a structure, then it won't be possible to address that structure's params directly. In this case parameters can be addressed in way like
mypoints POINTS
mov eax, [mypoints.points + POINT.y + sizeof.POINT * INDEX]

Seems like that's most of it. Hope I didn't forget anything. Anyway, if forgot, then will add later.

Filename: test.asm
Filesize: 9.22 KB
Downloaded: 539 Time(s)

Post 10 Apr 2017, 23:52
View user's profile Send private message Reply with quote
Tomasz Grysztar

Joined: 16 Jun 2003
Posts: 8344
Location: Kraków, Poland
Tomasz Grysztar 11 Apr 2017, 18:18
This is very interesting. I did not expect development of "struct" in this direction.
Post 11 Apr 2017, 18:18
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.