
 Ecco il codice prodotto dal SAS/C per MandToPi.c. Ho cercato di commentarlo
in modo da rendere piu' o meno chiaro quello che fa. Per chi non conosce
l'assembler del 68K, vi diro' che:

  MOVE   A,L   copia il contenuto di A in B
  PEA    A     pusha A sullo stack
  BSR          salta ad una subroutine (come la CALL dell'x86)
  BRA          salta incondizionatamente
  LEA    A,B   carica l'indirizzo effettivo di A in B
  MOVEQ  N,B   variante di MOVE che sposta N (8bit) in B estendendolo a 32bit
  Fxxx         istruzione per il coprocessore matematico


  .B           parametro BYTE     ( 8bit)
  .W           parametro WORD     (16bit)
  .L           parametro LONG     (32bit)
  .D           parametro DOUBLE   (64bit)
  .X           parametro EXTENDED (80bit)

 --------------------------------------------------------------------------------

 _main:

     SUBQ.W    #8,A7              ; Riserva 8 bytes sullo stack
     FMOVEM.X  FP7-FP3,-(SP)      ; Salva sullo stack i registri FPU che usa
     MOVEM.L   D6-D7,-(SP)        ; Salva i registri dati che usa

     PEA       0130(PC)           ; fa le 4 printf() iniziali
     BSR.W     __builtin_printf   ; notare come venga pushato sullo stack
     PEA       0156(PC)           ; l'argomento della funzione, cioe' il, 
     BSR.W     __builtin_printf   ; puntatore alla stringa costante, ma 
     PEA       0198(PC)           ; non viene riaggiustato lo stack dopo
     BSR.W     __builtin_printf   ; ogni chiamata.  Il compilatore lo
     PEA       01D8(PC)           ; aggiusta una sola volta alla fine.
     BSR.W     __builtin_printf

     BSR.W     _clock             ; chiama la clock(). Il risultato va in D0
                                  ; ed il compilatore lo lascia stare li'...


     FMOVE.D   #1.000000e+00,FP7  ; carica 1.0 in FP7 (starti = 1.0)
     LEA       0010(SP),SP        ; riaggiusta lo stack caricando 16+SP in SP
     MOVE.L    D0,D7              ; sposta il risultato di clock() in D7
     MOVEQ     #00,D6             ; pass = 0
     BRA.W     test               ; salta al test del primo for()

for_esterno:
     FMOVE.D   #0.000000e+00,FP6  ; azzera zr, zi e altre tre cose...
     FMOVE.D   #0.000000e+00,FP5  ; non capisco perche' lo faccia in questo
     FMOVE.D   #0.000000e+00,FP7  ; modo che e' assurdamente inefficiente.
     FMOVE.D   #0.000000e+00,FP4
     FMOVE.D   #0.000000e+00,FP3  ; counter = 0

for_interno:
     FMUL.X    FP5,FP6            ; zr * zi
     FMUL.W    #0002,FP6          ; (zr * zi) * 2
     FADD.D    0044(A7),FP6       ; zi += ci
     FMOVE.X   FP6,FP5            ; sposta questa roba in FP5
     FMOVE.X   FP7,FP6            ; mette rsquared (FP7) in FP6
     FSUB.X    FP4,FP6            ; zr = rsquared - isquared
     FADD.D    #-7.500000e-01,FP6 ; zr += cr (-.75)
     FMOVE.X   FP6,FP7            ; copia zr in FP7
     FMUL.X    FP6,FP7            ; rsquared = zr * zr
     FMOVE.X   FP5,FP4            ; copia zi in FP4
     FMUL.X    FP5,FP4            ; isquared = zi * zi
     FADD.W    #0001,FP3          ; counter++
     FMOVE.X   FP7,FP0            ; copia starti in FP0
     FADD.X    FP4,FP0            ; zi += ci (starti)
     FCMP.W    #0004,FP0          ; rsquared + isquared <= 4.0 ?
     FBULE.W   for_interno        ;  si', vai a for_interno

     FMOVE.D   0044(SP),FP7       ; ricarica starti
     FMOVE.X   FP3,FP0            ; copia counter in FP0
     FMUL.X    FP7,FP0            ; starti * counter
     FMOVE.D   FP0,-(SP)          ; mette starti * counter sullo stack
     FMOVE.D   FP3,-(SP)          ; mette counter sullo stack
     FMOVE.D   FP7,-(SP)          ; mette starti sullo stack
     PEA       0110(PC)           ; mette la stringa sullo stack
     BSR.W     __builtin_printf   ; printf()

     FMUL.D    #1.000000e-01,FP7  ; starti *= 0.1
     ADDQ.L    #1,D6              ; pass++
     LEA       001C(SP),SP        ; rimette a posto lo stack

; test del primo for() notare che viene furbescamente messo in
; coda al blocco di codice.

test:
     FMOVE.D   FP7,0044(SP)      ; salva starti sullo stack
     MOVEQ     #08,D0            ; mette MAXPASSES in D0
     CMP.L     D0,D6             ; pass < MAXPASSES ?
     BLT.W     for_esterno       ; si', salta


fine:
     BSR.W     _clock            ; end = clock()

     SUB.L     D7,D0             ; end - start
     DIVU.L    #000003E8,D0      ; divide per CLOCKS_PER_SEC (senza segno)
     MOVE.L    D0,-(SP)          ; mette l'argomento sullo stack
     PEA       010C(PC)          ; mette la stringa sullo stack
     BSR.W     __builtin_printf  ; printf()
     ADDQ.W    #8,SP             ; riaggiusta lo stack

     MOVEQ     #00,D0            ; return 0
     MOVEM.L   (SP)+,D6-D7       ; ripristina i registri infangati
     FMOVEM.X  (SP)+,FP3-FP7     ; anche quelli della FPU
     ADDQ.W    #8,SP             ; toglie le variabili dallo stack
     RTS                         ; bye bye

 -------------------------------------------------------------------------
 
 Miei commenti al codice: sicuramente un essere umano avrebbe saputo far
di meglio. Il compilatore non ha neanche tentato di srollare il for piu'
interno, sebbene francamente non avrebbe portato ad un grande incremento
delle prestazioni.
