flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > [fasmg] C style fastcall macro toolkit - version 1

Author
Thread Post new topic Reply to topic
Jessé



Joined: 03 May 2025
Posts: 135
Location: Brazil
Jessé 08 Jun 2025, 12:56
This is the final stable (at least to my tests Wink) version of my fastcall toolkit macro set.
Changes from BETA2:

- irpv demon is now gone!
- overall performance has become quite good now!
- removed internal TRUE, FALSE and NULL definitions. Internal types for this still exist.
- default size statement for unsizable parameters is now permanent (see this post);
- upgrade 'testtype' internal macro following Tomasz recomendations about register identification;
- 32 bit computed address with 32 registers now is recognized as 32-bit size;
- added support to pass MMX registers for integer type parameters (dword, qword);
- enhance tword parameter decision taking on FPU parameters (including FPU registers);
- added PI number (TT or π represented) as a tword parameter;
- added support for ("CHARDATA") format to pass up to qword characters parameter (not string);
- added 'alias' macro inside proto macro, which defines only the alias not the function name as macro;
- internal aliased functions now call function 'name' instead of '_name';
- added _bss macro for uninitialized data section (alpha stage, due to limitations on how 'virtual' directive handles uninitialized data);
- added '_code rwx' for declaring a self modifying code section (read, write and execute);
- made _data, _rdata and _code reusable, outputting sections contents to the topmost _data, _rdata or _code macro;
- label x number thing is removed, completely unreliable. But it is not a problem, because it still has *label or the classical [label] to do its stuff.

I included the updated user guide version, please read it. There's some points to consider when using the new stuff. Also helper texts are alongside macro code to complement what's in the user guide.
The 'irpv' problem is due to me keeping using my first premature version of 'testtype', which has wrong define/equ/= usage for some global variables. 100% fixed now!
The one here is much more refined, stable, and has a much much better performance than the BETA2 approach. And extra features, too.
This also makes it extremely bounded to fasm2 environment, which is never an issue, because it is made for fasm2 assembler/x86-64/Linux O.S./System V ABI Fastcall calling convention. So, backup that copy of BETA2 if you have it. One might need to reuse my text-based register detect melhod if doing anything customized.

Have fun! ✌️


Description: Clean and nifty now, without any "possession" =D
Packed with examples, adapted to the new stuff, also.

Download
Filename: fastcall_v1 demo.zip
Filesize: 52.49 KB
Downloaded: 387 Time(s)


_________________
jesse6
Post 08 Jun 2025, 12:56
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 135
Location: Brazil
Jessé 13 Jun 2025, 05:44
From now on, one can get any updates on this macro toolkit under my GitHub repo for it (finally).
I know I'm changing the wheel while the car is moving, but, I can't wait... Rolling Eyes
Post 13 Jun 2025, 05:44
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 135
Location: Brazil
Jessé 10 Jun 2026, 15:19
After some time enjoying this very powerfull creation, I've decided to make (also) version 2, which will be available soon.
This new version will support position independent executables! Working in tandem with version 1, with automatic ELF executable type detection.
It's already working flawlessly, I just need to write some few lines of documentation to spot the small differences between those 2 types of executables, and their characteristics.
Post 10 Jun 2026, 15:19
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 135
Location: Brazil
Jessé 11 Jun 2026, 07:37
Done!

One interested in using it must sync its local repo.

Have fun! ✌🏼
Post 11 Jun 2026, 07:37
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 135
Location: Brazil
Jessé 25 Jul 2026, 08:21
I dive deep to make an upgraded version of it, and thanks to the prompt help of Tomasz Grysztar and bitRAKE, alongside with many others that help me figured out several things with fasmg (again, thank you guys for your patience and good explanations and suggestions), it's now possible (at my current not published yet development stage: version 3) to achieve this beautiful syntax:

Code:
format ELF64 executable 3

include 'fastcall3.inc'
include 'stdio.inc'

struct DUMMY1
    .a              dq ?
    .b              dq ?
    .c              dq ?
end struct

struct SUB_FIELD
    .sub_a          dq ?
    .sub_b          dq ?
    .sub_c:         dq ?
    .sub_d:         dq ?
    .sub_e          DUMMY2
end struct

struct TEST_FIELDS
    .data.first     dq ?
    .data.second    dq ?
    .ptr.first:     dq ?
    .ptr.second:    dq ?
    .what.third     SUB_FIELD
    .data.fourth    dq ?
    .data.fifth:    dq ?
end struct

struct DUMMY2
    .d:             dq ?
    .e:             dq ?
    .f:             dq ?
    .g              dq ?
end struct

_bss    dmys            DUMMY2
        var             TEST_FIELDS
        dmye            DUMMY1

_code   Start entry:    libc.StartMain(Main);

        Main:           push        0

                        mov         rax, [stdout]
                        mov         rdx, [stderr]
                        push        [rax]
                        push        [rdx]
                        pop         [stderr]
                        pop         [stdout]

                        fputs("Loading structure...", stdout);
                        fflush(stdout);

                        mov         [var.data.first], +1000
                        mov         [var.data.second], +2000
                        mov         [var.what.third.sub_e.g], -3000

                        fputs(" done."\n, stdout);
                        fflush(stdout);

                        fprintf(stderr, "Dumping fields:"\n \
                            " Data: %d, %d, %d   Address: 0x%lX, 0x%lX, 0x%lX"\n, \
                            var.data.first, var.data.second, var.what.third.sub_e.g, \
                            var.ptr.first, var.ptr.second, var.what.third.sub_e.f);

                        pop         rax
                        ret

            .testpost:  db 'This message pointer must be seen as address type!', 10, 0

    


When compiling (the verbosity is on because of its current 'development' phase) it results in:

Quote:

artix-avlt:[jesse6]:~/ASM64/fasm2_latest/tests$ fasm2 test_struct.asm
flat assembler version g.l8vn
Using 'fastcall' macro package version 3.0+
Switch label namespace to: proto.fflush
Switch label namespace to: proto.fprintf
Switch label namespace to: proto.fputs
Switch label namespace to: proto.__libc_start_main
Importing: stdout
Importing: stderr
Importing: fflush
Importing: fprintf
Importing: fputs
Importing: __libc_start_main
Switch label namespace to: symtab
Switch label namespace to: rela
Switch label namespace to: hash
Switch label namespace to: strtab
Switch label namespace to: strtab.stdout
Switch label namespace to: strtab.stderr
Switch label namespace to: strtab.fflush
Switch label namespace to: strtab.fprintf
Switch label namespace to: strtab.fputs
Switch label namespace to: strtab.__libc_start_main
Switch label namespace to: strtab.needed#1
Switch label namespace to: ptrtab
Switch label namespace to: stdout
Switch label namespace to: stderr
Switch label namespace to: fflush
Switch label namespace to: fprintf
Switch label namespace to: fputs
Switch label namespace to: __libc_start_main
Switch label namespace to: dmys
Struct start at: dmys
--> Mount: .d : dq ?
-> Create property address to: .d at: dmys
--> Mount: .e : dq ?
-> Create property address to: .e at: dmys
--> Mount: .f : dq ?
-> Create property address to: .f at: dmys
--> Mount: .g dq ?
Struct end: dmys
Switch label namespace to: var
Struct start at: var
--> Mount: .data.first dq ?
--> Mount: .data.second dq ?
--> Mount: .ptr.first : dq ?
-> Create property address to: .ptr.first at: var
--> Mount: .ptr.second : dq ?
-> Create property address to: .ptr.second at: var
--> Mount: .what.third SUB_FIELD
-> Create property address to: .what.third at: var
Struct start at: var.what.third
--> Mount: .sub_a dq ?
--> Mount: .sub_b dq ?
--> Mount: .sub_c : dq ?
-> Create property address to: .sub_c at: var.what.third
--> Mount: .sub_d : dq ?
-> Create property address to: .sub_d at: var.what.third
--> Mount: .sub_e DUMMY2
-> Create property address to: .sub_e at: var.what.third
Struct start at: var.what.third.sub_e
--> Mount: .d : dq ?
-> Create property address to: .d at: var.what.third.sub_e
--> Mount: .e : dq ?
-> Create property address to: .e at: var.what.third.sub_e
--> Mount: .f : dq ?
-> Create property address to: .f at: var.what.third.sub_e
--> Mount: .g dq ?
Struct end: var.what.third.sub_e
Struct end: var.what.third
--> Mount: .data.fourth dq ?
--> Mount: .data.fifth : dq ?
-> Create property address to: .data.fifth at: var
Struct end: var
Switch label namespace to: dmye
Struct start at: dmye
--> Mount: .a dq ?
--> Mount: .b dq ?
--> Mount: .c dq ?
Struct end: dmye
Switch label namespace to: Start
Probing: rsp... parameter: 'rsp' size: 8 type: 24
Probing: rdx... parameter: 'rdx' size: 8 type: 24
Probing: 0... parameter: '0' size: 4 type: 18
Probing: 0... parameter: '0' size: 4 type: 18
Probing: rsp+16... parameter: 'rsp+16' size: 8 type: 3
Probing: [rsp+8]... parameter: 'rsp+8' size: 0 type: 1
Probing: Main... parameter: 'Main' size: 8 type: 3
Switch label namespace to: Main
Probing: __imp.stdout... parameter: '__imp.stdout' size: 8 type: 1
Probing: 'Loading structure...'... parameter: ''Loading structure...'' size: 8 type: 17
Probing: __imp.stdout... parameter: '__imp.stdout' size: 8 type: 1
Probing: __imp.stdout... parameter: '__imp.stdout' size: 8 type: 1
Probing: ' done.'\n... parameter: '' done.'\n' size: 8 type: 37
Probing: __imp.stdout... parameter: '__imp.stdout' size: 8 type: 1
Probing: 'Dumping fields:'\n ' Data: %d, %d, %d Address: 0x%lX, 0x%lX, 0x%lX'\n... parameter: ''Dumping fields:'\n ' Data: %d, %d, %d Address: 0x%lX, 0x%lX, 0x%lX'\n' size: 8 type: 37
Probing: var.data.first... parameter: 'var.data.first' size: 8 type: 1
Probing: var.data.second... parameter: 'var.data.second' size: 8 type: 1
Probing: var.what.third.sub_e.g... parameter: 'var.what.third.sub_e.g' size: 8 type: 1
Probing: var.ptr.first... parameter: 'var.ptr.first' size: 8 type: 3
Probing: var.ptr.second... parameter: 'var.ptr.second' size: 8 type: 3
Probing: var.what.third.sub_e.f... parameter: 'var.what.third.sub_e.f' size: 8 type: 3
Probing: __imp.stderr... parameter: '__imp.stderr' size: 8 type: 1

4 passes, 0.2 seconds, 1460 bytes.



For reference:
Type 1: data at memory
Type 3: effective address
Type 17: simple string (which will be rendered null terminated)
Type 18: absolute literal number
Type 37: escaped string type (also null terminated)

And, when running it:
Quote:

artix-avlt:[jesse6]:~/ASM64/fasm2_latest/tests$ ./test_struct
Loading structure... done.
Dumping fields:
Data: 1000, 2000, -3000 Address: 0x402470, 0x402478, 0x4024B0


Another example, with comments to ease understanding (now, dynamic address ELF):
Code:
format ELF64

include 'fastcall3.inc'     ; The almighty header behind this stuff
include 'stdio.inc'         ; Reusable header related to libc.so.6

CONSTANT1 := 585585h        ; Numeric literal data labels
CONSTANT2 = 100001h         ;

_rdata
        DATA            dd 800008h                              ; By value [data] label
        POINTER:        db 'this is a pointer-type label', 0    ; By reference pointer label

_code   Start entry:    libc.StartMain(Main);       ; This is a macro at 'stdio.inc' header

        Main:           push        0

                @1      fprintf(stdout, "Values of 'CONSTANT's are: 0x%X 0x%X."\n, CONSTANT1, CONSTANT2);
                @2      fprintf(stdout, "Data at 'DATA' variable is: 0x%X."\n, DATA);
                @3      fprintf(stdout, "String at pointer 'POINTER' label is: '%s'."\n, POINTER);

                        pop         rax
                        ret

        ; For reference, about the last parameters of each line:
        ;
        ; Data at '@1' label resolves to: mov reg, CONSTANTx
        ; Data at '@2' label resolves to: mov reg, [DATA]
        ; Data at '@3' label resolves to: lea reg, [POINTER]
        ;

    


Compiling:
Quote:

artix-avlt:[jesse6]:~/ASM64/fasm2_latest/tests$ build label_pnp
Using 'fastcall' macro package version 3.0+
Importing: stdout
Importing: fprintf
Importing: __libc_start_main
Switch label namespace to: DATA
Switch label namespace to: POINTER
Switch label namespace to: Start
Probing: rsp... parameter: 'rsp' size: 8 type: 24
Probing: rdx... parameter: 'rdx' size: 8 type: 24
Probing: 0... parameter: '0' size: 4 type: 18
Probing: 0... parameter: '0' size: 4 type: 18
Probing: rsp+16... parameter: 'rsp+16' size: 8 type: 3
Probing: [rsp+8]... parameter: 'rsp+8' size: 0 type: 1
Probing: Main... parameter: 'Main' size: 8 type: 3
Switch label namespace to: Main
Probing: 'Values of ''CONSTANT''s are: 0x%X 0x%X.'\n... parameter: ''Values of ''CONSTANT''s are: 0x%X 0x%X.'\n' size: 8 type: 37
Probing: CONSTANT1... parameter: 'CONSTANT1' size: 4 type: 18
Probing: CONSTANT2... parameter: 'CONSTANT2' size: 4 type: 18
Probing: stdout... parameter: 'stdout' size: 8 type: 1
Probing: 'Data at ''DATA'' variable is: 0x%X.'\n... parameter: ''Data at ''DATA'' variable is: 0x%X.'\n' size: 8 type: 37
Probing: DATA... parameter: 'DATA' size: 4 type: 1
Probing: stdout... parameter: 'stdout' size: 8 type: 1
Probing: 'String at pointer ''POINTER'' label is: ''%s''.'\n... parameter: ''String at pointer ''POINTER'' label is: ''%s''.'\n' size: 8 type: 37
Probing: POINTER... parameter: 'POINTER' size: 8 type: 3
Probing: stdout... parameter: 'stdout' size: 8 type: 1



And running:
Quote:

artix-avlt:[jesse6]:~/ASM64/fasm2_latest/tests$ ./label_pnp
Values of 'CONSTANT's are: 0x585585 0x100001.
Data at 'DATA' variable is: 0x800008.
String at pointer 'POINTER' label is: 'this is a pointer-type label'.



At its current development, all of those previous problems I've faced are now solved, and all of them were because of my lack of experience with fasmg at that moment, which is making me realize how limitless fasmg really appears to be.
As soon as I can, I'll publish it here, as always, and let you know.

Cheers!
Post 25 Jul 2026, 08:21
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-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.