flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > How to pass a point to structure to a proc?

Author
Thread Post new topic Reply to topic
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 17 Apr 2026, 17:05
How to implement the following:

Code:
struc _font name, width
{
  .name    DD   name        ; point to font table
  .width    DW   width        ; width in pixels
}

font8x8   DB  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
          DB  000h, 0CAh, 048h, 0DC, 0DBh, 0CAh, 000h, 000h
              .....................

font8  _font  font8x8, 8

stdcall SetFont, font8

proc SetFont, fnt:_font
  mov   EAX, [fnt.name]
  mov   [system_font.name], EAX
  mov   EAX, [fnt.width]
  mov   [system_font.width], EAX

  ret
endp
    

?
fasm does not allow to write such code.
Post 17 Apr 2026, 17:05
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1211
Location: Russia
macomics 17 Apr 2026, 20:11
I usually use this approach.
Code:
struc assume base&, type { if ~ type eq
    virtual at base
      . type
      if ~ definite .Bytes
        label .Bytes at $ - $$
      end if
    end virtual
  else
    label . at base
    label .Bytes at 0
  end if
}


struc _font name, width
{
  .name    DD   name        ; point to font table
  .width    DW   width        ; width in pixels
}

font8x8   DB  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
          DB  000h, 0CAh, 048h, 0DC, 0DBh, 0CAh, 000h, 000h
              .....................

font8  _font  font8x8, 8

stdcall SetFont, font8

proc SetFont, lp_font:DWORD
  fnt assume _font, EDX

  mov   EDX, [lp_font]
  mov   EAX, [fnt.name]
  mov   [system_font.name], EAX
  mov   EAX, [fnt.width]
  mov   [system_font.width], EAX

  ret
endp    
Or, for this particular case (the length of the structure is 6 bytes), you can use this approach
Code:
struc assume base&, type { if ~ type eq
    virtual at base
      . type
      if ~ definite .Bytes
        label .Bytes at $ - $$
      end if
    end virtual
  else
    label . at base
    label .Bytes at 0
  end if
}


struc _font name, width
{
  .name    DD   name        ; point to font table
  .width    DW   width        ; width in pixels
}

font8x8   DB  000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h
          DB  000h, 0CAh, 048h, 0DC, 0DBh, 0CAh, 000h, 000h
              .....................

font8  _font  font8x8, 8

stdcall SetFont, font8

proc SetFont, a_fnt:QWORD
  fnt assume _font, a_fnt

  mov   EAX, [fnt.name]
  mov   [system_font.name], EAX
  mov   EAX, [fnt.width]
  mov   [system_font.width], EAX

  ret
endp    
Post 17 Apr 2026, 20:11
View user's profile Send private message Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 18 Apr 2026, 09:10
Code:
flat assembler   version  1.73.35 (140224 kilobytes memory)
font.asm [34]
struc assume base&, type { if ~ type eq
error:  invalid macro arguments
    
Post 18 Apr 2026, 09:10
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20951
Location: In your JS exploiting you and your system
revolution 18 Apr 2026, 11:37
Try
Code:
struc _font name, width
{
  .name    DD   name        ; point to font table
  .width    DW   width        ; width in pixels
}
virtual at 0
  _font _font
end virtual

;...

proc SetFont, fnt
  mov   EDX, [fnt]
  mov   EAX, [EDX + _font.name]
;...    
Post 18 Apr 2026, 11:37
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1793
Location: Toronto, Canada
AsmGuru62 18 Apr 2026, 15:19
Just use struct/ends, no virtual needed and you also get sizeof.<your-struct-name> for free.
Post 18 Apr 2026, 15:19
View user's profile Send private message Send e-mail Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 18 Apr 2026, 15:36
Sad
Code:
flat assembler   version  1.73.35 (140224 kilobytes memory)
font.asm [56]
  _font  _font
font.asm [50]
   .name   DD  name     ; point to font table
processed:  _font.name  DD
error: invalid argument
    


Isn't there a simple way to use structure members in a subroutine?
Post 18 Apr 2026, 15:36
View user's profile Send private message Visit poster's website Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 18 Apr 2026, 15:38
AsmGuru62 wrote:
Just use struct/ends, no virtual needed and you also get sizeof.<your-struct-name> for free.

Unfortunately, I don't understand how to put this in code.
----
Let me ask the question another way.
Maybe there is another, simpler way to pass the value of one structure to another?
Post 18 Apr 2026, 15:38
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1793
Location: Toronto, Canada
AsmGuru62 18 Apr 2026, 19:12
My apologies, I was, most likely, not very helpful.
Below is a working program for Windows, which demonstrates the principle.
You may be coding for other OS (which one?), then, again, not sure if I can help.
The program below compiles by FASM and in debugger I can see how it copies values from one structure to another:
Code:
; ---------------------------------------------------------------------------
; FILE: x32-help-struct.Asm
; DATE: April 18, 2026
; ---------------------------------------------------------------------------

format  PE GUI 4.0
entry   start
stack   4000h, 4000h

include 'Win32A.Inc'

; ---------------------------------------------------------------------------
struct Font1
    PointsToFontTable   dd ?
    WidthInPixels       dw ?
ends

; ---------------------------------------------------------------------------
section '.data' data readable writeable

    FontBits        rb 256  ; 256 bytes for the font, same as lines of DB 0CAh, ... etc

    system_font     Font1   ; Font to be set by the 'SetFont' function

    my_font         Font1 FontBits, 8   ; These are copied into 'system_font' by 'SetFont'

; ---------------------------------------------------------------------------
section '.code' code readable executable

proc SetFont pFont:DWORD
    mov     ecx, [pFont]

    mov     eax, [ecx + Font1.PointsToFontTable]
    mov     [system_font.PointsToFontTable], eax

    mov     ax, [ecx + Font1.WidthInPixels]
    mov     [system_font.WidthInPixels], ax     ; can't use EAX with DW
    ret
endp

; ---------------------------------------------------------------------------
; PROGRAM ENTRY POINT
; ---------------------------------------------------------------------------
start:
    stdcall   SetFont, my_font
    invoke    ExitProcess, 0

; ---------------------------------------------------------------------------
section '.idata' import data readable writeable

    library kernel32,'KERNEL32.DLL',user32,'USER32.DLL',gdi32,'GDI32.DLL'

    include 'API\Kernel32.Inc'
    include 'API\User32.Inc'
    include 'API\Gdi32.Inc'
    
Post 18 Apr 2026, 19:12
View user's profile Send private message Send e-mail Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 18 Apr 2026, 20:25
AsmGuru62 wrote:
My apologies, I was, most likely, not very helpful.
Below is a working program for Windows, which demonstrates the principle.
You may be coding for other OS (which one?), then, again, not sure if I can help.
The program below compiles by FASM and in debugger I can see how it copies values from one structure to another:

Thanks for the answer. I'm currently writing code that is OS independent and called from my own bootloader. I'll try to adapt your code for my needs.
Post 18 Apr 2026, 20:25
View user's profile Send private message Visit poster's website Reply with quote
AsmGuru62



Joined: 28 Jan 2004
Posts: 1793
Location: Toronto, Canada
AsmGuru62 18 Apr 2026, 22:20
I see. The struct/ends construct is a macro found in a header file for Windows "Struct.Inc".
You can try to include that file and you should get struct/ends in OS independent code.
For OS independent code you should try to create your structures based on a 'virtual' keyword in FASM.
I started coding with FASM when MS-DOS was not yet dead, so I used the following approach:
Code:
virtual at 0
Font1:
    .PointsToFontTable   dd ?
    .WidthInPixels       dw ?
    .size = $
end virtual
    

Now, you got a structure-like thing called "Font1".
You can allocate memory for it using "Font1.size". It holds the # of bytes for a structure.
However, you cannot declare it in data section as before:
Code:
MyFont   Font1
    

But you can declare it using RB directive, like so:
Code:
MyFont   rb Font1.size
    

You would be just reserving bytes.
To set a field into such thing, you need to load a register:
Code:
mov   ecx, MyFont
mov   [ecx + Font1.WidthInPixels], 8
    

Yes, I did all that for MS-DOS code. It was working fine.
Try to include the file "Struct.Inc" and see if it works for you.
For me this file is located here:
Code:
C:\Tools\fasmw17332\INCLUDE\MACRO\STRUCT.INC
    

This is ^^^ FASM for Windows.
Try to find the same file in your FASM package.
With "virtual at 0" thing your code and data sections will change:
Code:
; ---------------------------------------------------------------------------
section '.data' data readable writeable

    FontBits        rb 256  ; 256 bytes for the font, same as lines of DB 0CAh, ... etc

    system_font     rb Font1.size   ; Font to be set by the 'SetFont' function

    my_font         dd FontBits
                    dw 8   ; These are copied into 'system_font' by 'SetFont'

; ---------------------------------------------------------------------------
section '.code' code readable executable

proc SetFont pFont:DWORD
    mov     ecx, [pFont]
    mov     edx, system_font

    mov     eax, [ecx + Font1.PointsToFontTable]
    mov     [edx + Font1.PointsToFontTable], eax

    mov     ax, [ecx + Font1.WidthInPixels]
    mov     [edx + Font1.WidthInPixels], ax     ; can't use EAX with DW
    ret
endp

; ---------------------------------------------------------------------------
; PROGRAM ENTRY POINT
; ---------------------------------------------------------------------------
start:
    stdcall   SetFont, my_font
    

One more thing: proc/endp/stdcall also from Windows headers,
so I am not sure how it is going to work in your OS independent code.

Of course, you can just use labels as procedures and [EBP+xxx] to get the pushed parameters,
for MS-DOS I had to do all that work.
I used [BP+xxx], but it is just details.
Post 18 Apr 2026, 22:20
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: 20951
Location: In your JS exploiting you and your system
revolution 18 Apr 2026, 23:30
Byte wrote:
Sad
Code:
flat assembler   version  1.73.35 (140224 kilobytes memory)
font.asm [56]
  _font  _font
font.asm [50]
   .name   DD  name     ; point to font table
processed:  _font.name  DD
error: invalid argument
    


Isn't there a simple way to use structure members in a subroutine?
It needs two dummy values to satisfy the macro.
Code:
 _font  _font 0,0    
Post 18 Apr 2026, 23:30
View user's profile Send private message Visit poster's website Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 19 Apr 2026, 13:07
AsmGuru62 wrote:
I see. The struct/ends construct is a macro found in a header file for Windows "Struct.Inc".
You can try to include that file and you should get struct/ends in OS independent code.
For OS independent code you should try to create your structures based on a 'virtual' keyword in FASM.
I started coding with FASM when MS-DOS was not yet dead, so I used the following approach:


Thank you for a meaningful answer!
So, of course, I tried to include the file "Struct.Inc" in my project. At the moment, I use fasm for DOS and I get errors when compiling. For me, using a fasm for DOS is faster, I just don't know simple way to mount a floppy image under Windows to write compiled code to it. Then the virtual machine is loaded from this image.
Your advice is useful, but if i use
Code:
MyFont rb Font1.size    

i will lose all the benefits of using the structure.
I need declare structure like in MASM code:
Code:
_font  STRUC
     name    DD  0
     width    DW 0
     height  DW 0
_font ENDS
    

I need to not just reserve memory for the structure, I need to then conveniently use it with maximum help from the compiler, as the same MASM does. Unfortunately, I haven't found a way to compile 32-bit code from MASM without headers. Therefore, I switched to FASM.
After that, i need to add a different number of structures that describe certain fonts. (For MASM example:)
Code:
font_1   _font   <_font8x8, 8, 8>
font_2   _font   <_font8x14, 8, 14>
font_2   _font   <_font8x16, 8, 16>
    

Then I just need a pointer to one of the structures at any time.
Code:
lea   EAX, font_1
mov  _system_font, EAX
mov  EBX, _system_font.height
...
    

In my opinion, a modern ASM compiler should distinguish between a pointer to a structure, like it does in C++.
Code:
_font *_system_font;    

Then you could use code like:
Code:
lea     EAX, font_1
mov   _system_font, EAX
mov   EBX, _system_font->width
    

and so on.
I'll try to implement your advice into code a little later.
Post 19 Apr 2026, 13:07
View user's profile Send private message Visit poster's website Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 19 Apr 2026, 15:25
revolution wrote:
It needs two dummy values to satisfy the macro.
Code:
 _font  _font 0,0    

Thank you, it helped.
Post 19 Apr 2026, 15:25
View user's profile Send private message Visit poster's website Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 19 Apr 2026, 15:55
Thanks for the replies. I finally managed to compile a working version of the code with the help of your community. The code currently looks like this.
Code:
format binary

use32

INCLUDE '../inc/proc32.inc'
INCLUDE '../inc/masm.inc'
INCLUDE '../inc/const.inc'

; structure for describing a font
  struc _font font, font_width, font_height
  {
    .font         DD   font         ; point to font in memory
    .width        DW   font_width
    .height       DW   font_height
  }
  virtual at 0
    _font _font 0, 0, 0
  end virtual

ORG 0A000h           ; loaded on 0000A000 address

use32

Main:

; out to screen
   call  _ClrScreen                      ; clear screen

   stdcall _SetSystemFont, _font8x8bm

   stdcall _OutChar, 'A', 000A000Ah

   stdcall _SetSystemFont, _font8x14bm

   stdcall _OutChar, 'A', 000B000Ah   
   ..........

; set font for out
proc  _SetSystemFont, newfont:DWORD
   push  EAX  EDX  ESI
   mov   ESI, [newfont]
   mov   EDX, _system_font
   mov   EAX, [ESI + _font.font]     ; point to font table
   mov   [EDX + _font.font], EAX

   mov   AX, [ESI + _font.width]
   mov   [EDX + _font.width], AX     ; font width

   mov   AX, [ESI + _font.height]
   mov   [EDX + _font.height], AX     ; font height
   pop   ESI  EDX  EAX
   ret
endp
........

  LABEL   _font8x8  BYTE
  INCLUDE '../font/font8x8u.fon'
  LABEL   _font8x14  BYTE
  INCLUDE '../font/font8x14.fon'
  _font8x8bm       _font  _font8x8, 08h, 08h
  _font8x14bm      _font  _font8x14, 08h, 0Eh
  _system_font     _font  0h, 0h, 0h               ; default font for out
    

Still, it would be nice if FASM learned to support pointers, for example, as implemented in C++.
And for some reason the instruction like:
Code:
mov  AL, byte [_system_font.font+ESI]    

stopped working.
I had to replace it with:
Code:
mov   EAX, [_system_font.font]
mov  AL, byte [EAX+ESI]
    
Post 19 Apr 2026, 15:55
View user's profile Send private message Visit poster's website Reply with quote
macomics



Joined: 26 Jan 2021
Posts: 1211
Location: Russia
macomics 19 Apr 2026, 16:05
Byte wrote:
Code:
flat assembler   version  1.73.35 (140224 kilobytes memory)
font.asm [34]
struc assume base&, type { if ~ type eq
error:  invalid macro arguments
    
Code:
struc assume base*, type { if ~ type eq    
Post 19 Apr 2026, 16:05
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20951
Location: In your JS exploiting you and your system
revolution 19 Apr 2026, 16:06
Byte wrote:
Still, it would be nice if FASM learned to support pointers, for example, as implemented in C++.
And for some reason the instruction like:
Code:
mov  AL, byte [_system_font.font+ESI]    

stopped working.
I had to replace it with:
Code:
mov   EAX, [_system_font.font]
mov  AL, byte [EAX+ESI]
    
It depends upon the definition of _system_font. The x86 encoding rules combined with PE relocations can make some things impossible to encode. And fasm will just say is can't do it. The failing is that fasm won't describe the exact reason, so people unfamiliar with the terse responses might not understand.

Since _system_font is a fixed address I don't see how ESI is needed. Using a plain "mov AL, byte [_system_font.font]" should be all that is needed. The only way it works is if ESI = 0, which makes it redundant. Plus the byte override is weird for a a dword address pointer.
Post 19 Apr 2026, 16:06
View user's profile Send private message Visit poster's website Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 19 Apr 2026, 16:51
revolution wrote:


Since _system_font is a fixed address I don't see how ESI is needed. Using a plain "mov AL, byte [_system_font.font]" should be all that is needed. The only way it works is if ESI = 0, which makes it redundant. Plus the byte override is weird for a a dword address pointer.


This is because the ESI points to the specific byte that needs to be displayed on the screen. This is an offset in the font table. The full code is:
Code:
; out one byte char to xy coordinate
; input: 'char' - char to draw; low 'yx' 16 bit - x coordinate
; high 'yx' 16 bit - y coordinate
proc    _OutCharXYIn12h, char:DWORD, yx:DWORD
        push    EAX EBX ECX EDX ESI EDI EBP

        mov     EAX, [yx]
        mov     ESI, [char]

        imul    SI, [_system_font.height]   ; offset to char in bytes

        mov     CX, AX
        shr     EAX, 16
        mov     BX, AX
        mov     DI, 80                 ; screen width in bytes
        mul     DI
        mov     DI, CX
        and     CL, 00000111b          ; bit mask
        shr     DI, 3                  ; devide by 8
        add     DI, AX                 ; add x coordinate

        add     EDI, _video_ram

        mov     DX, 3CEh
        mov     AL, 3
        mov     AH, CL
        out     DX, AX

        mov     BX, 0FFFFh
        shr     BH, CL
        neg     CL
        add     CL, 8
        shl     BL, CL

       mov     BP, [_system_font.height]
       mov     DX, 3CEh
        mov     CX, 80      ;screen width in bytes
        dec     CX
        dec     CX      ; -2 because do two bytes for each char
char_loopxy:
        mov     AL, 8
        mov     AH, BL
        out     DX, AX

        mov     EAX, [_system_font.font]
        ;mov     AL, byte [_system_font.font+ESI]   
        mov     AL, byte [EAX+ESI]            ;get character byte
        inc     ESI
        mov     AH, byte [EDI]                ;load latches
        stosb                                 ;write character byte

        add     EDI, ECX
        dec     BP
        jnz     char_loopxy

        pop     EBP EDI ESI EDX ECX EBX EAX
        
        ret
endp
    
Post 19 Apr 2026, 16:51
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20951
Location: In your JS exploiting you and your system
revolution 19 Apr 2026, 23:25
Code:
        mov     EAX, [_system_font.font]
        ;mov     AL, byte [_system_font.font+ESI]   
        mov     AL, byte [EAX+ESI]            ;get character byte    
To do that in one instruction it would look like this:
Code:
mov     AL, byte [[_system_font.font]+ESI]    
x86 encoding does not support double indirection. "it would be nice if FASM learned to support pointers" can't be support by the CPU, fasm cant rewire the CPU instruction encoding.
Post 19 Apr 2026, 23:25
View user's profile Send private message Visit poster's website Reply with quote
Byte



Joined: 21 Mar 2026
Posts: 18
Byte 20 Apr 2026, 09:51
revolution wrote:
To do that in one instruction it would look like this:

Thanks for the tip.

revolution wrote:
"it would be nice if FASM learned to support pointers" can't be support by the CPU, fasm cant rewire the CPU instruction encoding.

This is not a CPU issue, it's a compiler issue. If I declare a variable as a pointer to a structure, the compiler can learn to understand it as a reference to a structure and do all the necessary calculations with the offsets and sizes of the arguments.
Something like this:
Code:
struc st1
{
    .size    DD  ?
    .width   DW  ?
}

myVar1 st1 000C00A0h, 000Dh
ptrVar1 *st1;

mov   EAX, [myVar1.size]
lea   EBX, myVar1
mov   ptrVar1, EBX
mov   DX, [ptrVar1->width]
    
Post 20 Apr 2026, 09:51
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20951
Location: In your JS exploiting you and your system
revolution 20 Apr 2026, 10:15
fasm works with a single instruction per line. Hence the name assembler. To make it into a compiler then the macro engine can be used.

People here have made many macro sets of varying complexity. One of them might do something like that. Although usually they are made to solve a particular purpose, so I think that some amount of customisation or extension will be needed to make it more generic, or more featured, to support HLL syntaxes as proposed above.

Note that the particular line "mov DX, [ptrVar1->width]" will need to allocate a temporary register to hold the intermediate address before loading DX, so some extra information will need to be provided to tell the engine which register is okay to be used.
Post 20 Apr 2026, 10:15
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.