flat assembler
Message board for the users of flat assembler.

Index > Tutorials and Examples > Forward referencing overflows or other unexpected conditions

Thread Post new topic Reply to topic
Tomasz Grysztar

Joined: 16 Jun 2003
Posts: 7862
Location: Kraków, Poland
Tomasz Grysztar
Note: this post applies the same to fasm 1 as well to fasmg.

Sometimes when constructing a file with fasm it may be needed to reserve an area for a data structures without knowing in advance how much space is going to be needed. For example when manually generating a PE file, it might be initially not known how many sections is it going to contain, but the area for section table needs to be reserved in the header of a file (to be later filled with STORE directive). Fortunately this part of PE file needs to be aligned up to 512 bytes boundary, so even if just a minimum amount is reserved, it is still going to suffice for a few section headers. But if later many sections are defined and it runs out of space, this approach is going to fail.

Forward-referencing allows to easily deal with this kind of problems. It is only needed to count the sections and at the end of source define a constant like:
NUMBER_OF_SECTIONS = SECTION_COUNTER  ; with fasmg := may be used to indicate that it is a constant    
(this can be put into a POSTPONEd block). And the headers may forward-reference this value to reserve the right amount of space.

This has a small side-effect: it required more passes to be assembled. It is often not noticeable, because other code may require multiple passes as well. But if the forward-referenced value is actually something more fragile that the number of sections, like a value that may keep changing when other parts of file are moving, such reference may end up adding even a several passes. Also, if everything else in the source could assemble just in a one pass, this single forward reference is going to add another.

There is a way to combine the two approaches described above into one. A code may be written in such way that in the first (and sometimes the only one) pass it reserves the "usual" amount that is suspected to be the most often right, and then only if it fails proceed with more passes to resolve the problem. This may look like:
if defined OVERFLOW_SIZE
    ; reserve as much space as indicated by OVERFLOW_SIZE
    ; reserve the basic size
end if    
; at the end of source (or in the POSTPONE):
end if    
Thanks to the way in which fasm detects its own mispredictions, this is not going to require a second pass if OVERFLOW_SIZE does not end up getting defined.

The same trick can be used to detect other "unusual" conditions and avoids some special processing early in the source unless something later in the source really ends up requiring it.

This trick is also a demonstration of the intended function of fasm's DEFINED operator. Often it is expected by newcomers that would be akin to #IFDEF of languages like C, but in the case of fasm it serves other important purposes.

A side note: if anyone is wondering - fasm's DEFINED can still be used like #IFDEF, but the symbol needs to be variable and therefore not forward-referable. And fasm only starts treating symbol as a variable when it is defined at least twice:
if ~ defined foo
        foo = 1
        foo = 1 ; enforce variable status
end if

if ~ defined foo
        foo = 2
        foo = 2 ; enforce variable status
end if    
Post 13 Oct 2017, 13:39
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-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.