flat assembler
Message board for the users of flat assembler.
Index
> Macroinstructions > How to pass a point to structure to a proc? |
| Author |
|
|
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 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 |
|||
|
|
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 |
|||
|
|
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] ;... |
|||
|
|
AsmGuru62 18 Apr 2026, 15:19
Just use struct/ends, no virtual needed and you also get sizeof.<your-struct-name> for free.
|
|||
|
|
Byte 18 Apr 2026, 15:36
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? |
|||
|
|
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? |
|||
|
|
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' |
|||
|
|
Byte 18 Apr 2026, 20:25
AsmGuru62 wrote: My apologies, I was, most likely, not very helpful. 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. |
|||
|
|
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. |
|||
|
|
revolution 18 Apr 2026, 23:30
Byte wrote:
Code: _font _font 0,0 |
|||
|
|
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". 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. |
|||
|
|
Byte 19 Apr 2026, 15:25
revolution wrote: It needs two dummy values to satisfy the macro. Thank you, it helped. |
|||
|
|
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] |
|||
|
|
macomics 19 Apr 2026, 16:05
Byte wrote:
Code: struc assume base*, type { if ~ type eq |
|||
|
|
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++. 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. |
|||
|
|
Byte 19 Apr 2026, 16:51
revolution wrote:
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 |
|||
|
|
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 Code: mov AL, byte [[_system_font.font]+ESI] |
|||
|
|
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] |
|||
|
|
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. |
|||
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.