flat assembler
Message board for the users of flat assembler.

Index > Main > [fasmg] Split struc macro with postpone in an if / end if

Author
Thread Post new topic Reply to topic
VMo



Joined: 06 Sep 2024
Posts: 5
Location: Brest FRANCE
VMo 08 Jul 2026, 17:22
I have a problem I cannot get through involving the simultaneous use of postpone, struc, esc and if. I do not understand sufficiently precisely the fasmg machinery to find the solution.

The context : I use fasmg as binary generating backend for the Ada 83/TLALOC compiler.
I have two macros for a split struc when generating postponed a constant bloc of enum images strings :

Code:
;                       --------------
macro                   BEGIN_BLOC_DEF                          ; Debut de definition d'un bloc octets utilisable       comme STRING Ada
;                       --------------
;
  esc struc BYTES_BLOC                                          ; Structure du bloc     type STRING avec saut de fin de macro par "esc" pour coupure en deux parties
    postpone                                                    ; ATTENTION : différé terminé par la macro BYTE_BLK_END
    local       data
    local       info
    local       str_bit_size
    align_q                                                     ; aligner       le doublet descripteur sur un   quadword (taille adresses)
  .data_ptr = $                                                 ; adresse       de l'adresse de data
    dq  data                                                    ; offset 0 : adresse des octets
  .info_ptr = $                                                 ;
    dq  info                                                    ; offset 8 : adresse des infos d'usage associées       TOT_SIZ, COMP_SIZ, FST_1, LST_1
  info = $                                                      ; info d'usage mises ici
    dd  str_bit_size, 8, 1, str_bit_size/8                              ; offset 16 : TOT_SIZ=str_bit_size ; offset 20 :        COMP_SIZ=8bits ; offset 24 : FST=1 ; offset     28 : LST=str_bit_size/8
    virtual at 0                                                        ; definition des offsets sur le useinfo
    SIZ =       $
    rd 1
    COMP_SIZ = $
    rd 1
    FST_1       = $
    rd 1
    LST_1       = $
    end virtual
  data = $                                                      ; pour une constante les caracteres suivent (pour       une chaine variable     ce n'est pas le cas, les octets sont dans la co-pile)
                                                                ; les octets deront     places ici
end macro

;                       -------------
macro                   END_BLOC_DEF!                           ; Fin de definition     d'une constante chaine (Attention inconditionnelle "!")
;                       -------------
      str_bit_size = 8*($ - data)                                       ; Calculer la taille effective en bits
    end postpone
  esc end       struc                                                   ; Fin de la structure du bloc   arrêt de       la coupure par "esc"
end macro
    


Until now it worked, but when those macros are used in a conditional assembly section which is not assembled (P_L28_ not defined) END_BLOC_DEF creates an error :

flat assembler version g.kd3c
optim push_pop_rax_count (8 octets/unité) = 372

A83009A.fas [14] A83009A.FINC [425]:
END_BLOC_DEF
macro END_BLOC_DEF [4]:
end postpone
Processed: end postpone
Error: unexpected instruction.

This is the conditional bloc ( a procedure which is assembled only if used somewhere) which uses the split macro:

Code:
if defined P_L28_
PRO     P_L28                                   ;---------- PRO P
ELB 3                                   ;    BODY ELAB

                                        ; _CHILD4 ENUMERATION TYPE INFO
_CHILD4 = '_CHILD4'
namespace _CHILD4
VAR use__info, q
BEGIN_BLOC_DEF
db 0, 2, "E1"
db 1, 2, "E2"
db 2, 2, "E3"
END_BLOC_DEF
IMAGES  BYTES_BLOC
CST LST, d, 2
CST FST, d, 0
CST SIZ, d, 8   ; SIZ en bits !
postpone
  align_q
end postpone
        LCA     SIZ
        Sa      3, use__info
end namespace
                                        ;    end elab
begin:                                  ;---------- BDY INSTRUCTIONS
ret_lbl:
        UNLINK 3
        RTD
excep:
endPRO                                  ;---------- end PRO P
end if

    


if P_L28_ is not defined, the END_BLOC_DEF stays alone (it is unconditional in a conditional section). The use of the BLOC_DEF_ACTIF flag could seem to solve the problem but creates another difficulty that prevent fasmg to assemble. Is there a viable form for this construction ?.
Post 08 Jul 2026, 17:22
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8543
Location: Kraków, Poland
Tomasz Grysztar 09 Jul 2026, 09:35
If you end up with mismatched nesting of control directives when your macros are put inside a conditional section, you may need to take special steps to ensure that what is unrolled unconditionally has them all paired properly.

To better understand what is happening, let's start with what the manual has to say about control directives, as POSTPONE is one of them:
fasmg manual wrote:
They are the instructions that control the flow of assembly. Each of them defines its own block of subordinate instructions, closed with corresponding "end" command, and if these blocks are nested within each other, it always must be a proper nesting - the inner block must always be closed before the outer one. All control directives are therefore unconditional instructions - they are recognized even when they are inside an otherwise skipped block.
So when we are in a conditional section, like an IF block, the assembler still records all the control directives it sees, to see that they are properly nested and that the final END IF really is paired with the IF that started the block and not another one that happens to be embedded somewhere inside.

When passing through a skipped block this way, the assembler also unrolls are the macros that are unconditional. If you have a regular, "conditional" macro though, the assembler passes over it, and this way you can hide a control directive. Therefore to ensure that the assembler sees proper pairs of openings and closings of control blocks, your macros should either hide both ends or expose them both.

Let's prepare a simple test case:
Code:
macro defer?
        postpone
end macro


macro end?.defer?
        end postpone
end macro

if 0
        defer
                content
        end defer
end if    
This works well as is, and keeps working if we make both the macros unconditional. The problem shows up when we make only one of them unconditional:
Code:
macro defer?
        postpone
end macro


macro end?.defer?!
        end postpone
end macro

if 0
        defer
                content
        end defer
end if    
This is, I believe, the issue you're encountering.

Of course in practice ensuring that both ends are equally hidden or exposed may be tricky. See for example one of my old variants of IRPS macro. There my main IRPS_AS_IRPV macro is conditional, but END.IRPS needs to be unconditional (to ensure that the assembler sees the END.IRPV even when there is nothing to interate over and the block is skipped). To make sure that the assembler sees the opening IRPV in all cases, I added a dummy IRPV and a macro override. When the block is skipped, the assembler does not process the macro definition and notices the dummy IRPV. When the block is not skipped, the macro gets defined, dummy IRPV is sees as this macro and not a control directive, but then the actual IRPS_AS_IRPV implementation generates the proper IRPV.

As you can see, once you starting messing around with control blocks like that, you need to carefully consider all the scenarios.

The use of CALM may help a lot, as it gives a better control over entire process. See the current implementation of IRPS in fasm2 package for example.
Post 09 Jul 2026, 09:35
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.