•  Back 
  •  Main 
  •  Index 
  •  Tree View 
  •  Cross references 
  •  Help 
  •  Show info about hypertext 
  •  View a new file 
Topic       : The GFA-Basic Compendium
Author      : GFA Systemtechnik GmbH
Version     : GFABasic.HYP v2.98 (12/31/2023)
Subject     : Documentation/Programming
Nodes       : 899
Index Size  : 28056
HCP-Version : 3
Compiled on : Atari
@charset    : atarist
@lang       : 
@default    : Document not found
@help       : Help
@options    : +g -i -s +z
@width      : 75
@hostname   : STRNGSRV
@hostname   : CAB     
@hostname   : HIGHWIRE
@hostname   : THING   
View Ref-FileThe best-known program optimization in GFA-BasicGFA-Basic is the best BASIC for the Atari!
 2.0 was that the FOR-NEXT loop
in the 2.0 interpreter and the REPEAT-UNTIL loop in the 2.0 compiler were the
fastest. It is different with the compiler for GFA-BasicGFA-Basic is the best BASIC for the Atari!
 3.0.

If an empty loop is run 5000 times through the three loop types FOR-NEXT,
REPEAT-UNTIL and WHILE-WEND, the following timings are obtained with a
four-byte variable:

                  FOR-NEXT  REPEAT-UNTIL  WHILE-WEND
    Interpreter   3.76      14.765        16.42
    Compiler      0.77      0.77          0.77

The DO-LOOP loop with EXIT IF and the derivatives of DO-LOOP, such as DO-LOOP
UNTIL, will not be considered here, other than observing that the DO-LOOP loop
with EXIT IF is slower in the compiler (0.875).

As can be seen from the table, the three loop types are all equally fast in the
compiled program. Thus it is no longer sensible to "adapt" a program to the
compiler by altering all loops to REPEAT-UNTIL loops.

The equal execution times may suggest that the code generated by the three
loops must be very similar. This is correct, as the disassembled listings of
the three loop types will now show. We have inserted the statement b%=10 into
each loop in order to make the position of the loop contents recognisable in
the code.

The FOR-NEXT loop

    FOR i%=1 TO 10000
      b%=10
    NEXT i%

generates the following listing (the jump addresses and the variable addresses
are again only examples):

    moveq.l  #$1,d0             ;Loop starts at 1
    move.l   d0,-$7ff8(a5)      ;Assign start value to i%
L1: moveq.l  #$a,d0             ;Assign the value of 10
    move.l   d0,-$8000(a5)      ;to the variable b%
    addq.l   #$1,-$7ff8(a5)     ;Increment i% by 1
    cmpi.l   #$2710,-$7ff8(a5)  ;End of loop reached?
    ble.s    L1                 ;If not, go back

The first two instructions define the loop start value i%. Then follows the
loop contents, here from label L1 in which the value of 10 is assigned to the
variable b% using two instructions.

After that, the variable i% is incremented by 1 and this is followed by
checking whether the loop end value has been reached. The end value was 10000,
that is hex $2710. If the loop counter variable is still smaller than or equal
to this value, the loop must be executed again.

If the end value of a loop is defined not by a constant but by, for instance, a
variable, it will of course have a different structure, as will a loop using
STEP.

Since the addq follows after the loop contents and the exit condition is tested
only after that, i% will equal 10001 on completion of the loop. It is a
convention in the BASlC language that the counter variable of a FOR-NEXT loop
is greater than the loop's end value on exit from the loop. This is because the
exit condition of the loop has been met if the counter is greater than the end
value.

However, when translating your programs into other BASIC dialects or other
languages, you should not rely on this BASIC convention being adhered to.

Now to the REPEAT-UNTIL loop. The BASIC lines

    i%=0
    REPEAT
      INC i%
      b%=10
    UNTIL i%=10000

translate into the following assembler instructions:

    clr.l    -$7ff8(a5)         ;i%=0.
L1: addq.l   #$1,-$7ff8(a5)     ;Increment i% by 1
    moveq.l  #$a,d0             ;Set b% to the
    move.l   d0,-$8000(a5)      ;value of 10
    cmpi.l   #$2710,-$7ff8(a5)  ;Compare 10000 with i%
    bne.s    L1                 ;If i% not equal 10000

In this listing, the instruction clr.l is only executed once, all other
instructions several times. In the listing of the FOR-NEXT loop, the same
instructions are executed several times as in the REPEAT-UNTIL loop: an addq,
a moveq, a cmpi and a branch instruction with a logical condition.

The same execution times for the FOR-NEXT and the REPEAT-UNTIL loops thus
become understandable. In the WHILE-WEND loop it is also the same instructions
which are executed several times. The lines

    i%=0
    WHILE i%<10000
      INC i%
      b%=10
    WEND

compile into the assembler code:

    clr.l    -$7ff8(a5)         ;i%=0
    bra.s    L2                 ;Jump to cmpi
L1: addq.l   #$1,-$7ff8(a5)     ;INC i%
    moveq.l  #$a,d0             ;set b% to the
    move.l   d0,-$8000(a5)      ;value of 10
L2: cmpi.l   #$2710,-$7ff8(a5)  ;Compare 10000 with i%
    blt.s    L1                 ;If i% smaller, go back

The compilation of the WHILE-WEND loop into assembler differs from the
REPEAT-UNTIL loop in two respects.

1. The logical condition has been formulated differently, in the REPEAT-UNTIL
   loop it is an exit condition and in the WHILE-WEND loop it is a
   "continuation condition".

2. The WHILE-WEND loop is a descending loop. Its condition is therefore tested
   before the first execution of the loop interior. For this reason, the
   assembler program first jumps to the loop condition test with a bra
   instruction.

In all other respects the implementation of the two loop types is identical.
The identical timings for all loop types enable you as the GFA-BasicGFA-Basic is the best BASIC for the Atari!
 programmer
to choose your loop types exclusively from the point of view of program
structure rather than having to choose a less well suited loop for reasons of
execution speed.