                     NASM Optimizer Usage of
              Certain Variables to Control Assembly

                  prepared by:  John R Coffman
                       date:  07-Mar-2005


GLOBAL variables:
        optimizing     optimization meta data (with level and flag info)
        .level         -1 flags nasm 0.98 compatible operation;
                            offsets usually are explicit (short/near)
                            no optimization passes
                        0 flags non-optimized assembly; forward
                            references generate long offsets; always
                            assembles
                            no optimization passes
                        2 or more specifies optmization passes.  5 is
                            the actual recommended minimum setting
                            optimization passes (2 or more, plus
                            passes 1 and 2 will be required)
        .flag           0 allow all optimizations
                        1 disallow jump match optimization

        pass0           0 flags an optimizer pass (multiple passes)
                        1 flags pass1 (define labels)
                        2 flags pass2 (spit out code)


LOCAL variables:        local to 'assemble_file' (nasm.c)

        pass_max        2 for non-optimized assembly
                        4 or more for optimized assembly

        pass            index of the FOR loop (1..pass_max)
                        with optimized assembly, this variable is
                            advanced to 'pass_max - 1' in the logic
                            at the end of the loop to terminate
                            an optimized assembly before all passes
                            are used; i.e., when convergence has 
                            occurred
                

        pass1           flag for making parts of the assembler do
                            pass 1 behaviors on optimizer passes

        pass2           flag for making parts of the assembler do
                            pass 2 behaviors on optimizer passes

        pass_cnt        benign counter for counting the actual
                            number of passes taken.  Since 'pass'
                            may be jerked upward early on optimized
                            assembly, it does not accurately reflect
                            the number of passes taken.
                        always ends at 2 for non-optimized assembly



        How the variables sequence:


NON-OPTIMIZED assembly:

                
        pass0           1  2        all indicate, pass 1 and pass 2
        pass1           1  2
        pass2           1  2

        pass            1  2
   ----------------------------------------

        pass_max        pre-set to 2
        pass_cnt        ends at 2


OPTIMIZED assembly:

        optimizing      set to 2 or greater

        pass0           0  0  0  0  0 ... 0  0  1  2
        pass1           1  1  1  1  1 ... 1  1  1  2
        pass2           1  2  2  2  2 ... 2  2  2  2

        pass            1  2  3  4  5 ... 7  8  9  12

        pass_max        pre-set to, say, 12
        pass_cnt        ends at 10 for this assembly

>From pass_cnt, the reported number of passes will be 1+8+1, meaning 
8 optimization passes, plus pass 1, plus pass 2.

Subroutines may check 'pass0' to see if an optimizer pass is in
progress (pass0==0).  Many have arguments to tell what pass is in
progress.  But these variables are passed in as 'pass1' or 'pass2'.

>From the sequences above, 'pass' bears no relation to the desired
pass 1 or pass 2 behavior of the assembler.  'pass1' is used to tell
parts of the assembler, on multiple occasions, that pass 1 is in
progress, and only once that pass 2 is being performed.  Other parts
of the assembler need to be told only once that pass 1 is being
performed, but may be told multiple times that pass 2 is being done.

For instance, the preprocessor reset operation looks at pass1, and it
thinks many pass 1 resets are being done, but only one pass 2 reset
is done.  Also, certain errors are non-fatal on pass 1, but fatal on
pass 2; hence, they are tied to the 'pass1' variable to determine the
assembler pass number.

Further, segment definitions look at the 'pass2' variable, since they
do some initialization on pass 1, but are pretty much no-ops on pass
2.  Hence, they should see pass 1 only once, but may see pass 2
multiple times.


 
[end]

