venerdì 29 aprile 2016

Mandelbrot 13h (2)

Un po' di effetto dimagrante (da 240 a 224 bytes) del post precedente mettendoci anche un po' di colore (certo..la palette non e' bellissima)
Ho tolto anche la dipendenza dai registri a 32 bit che non era necessaria




----------------------------------------------------------------------
org 100h            ; serve solo per DOS per fare i file .COM
section .data
    a:    dq    -2.0     ; minimo reale della finestra
    b:    dq    -1.5     ; minimo immaginario della finestra
    bb:    dq    -1.5    ; asdasd
    da:    dq    0.0078125     ; incremento parte reale ((1.2-(-2))/320px delta_a
    db:    dq    0.015    ; incremento parte immaginaria ((1.5-1.5))/200px delta_b
    limite:    dq    4.0    ; condizione di fuga

section .text

global _start                   ;must be declared for using gcc

_start:


    ; inizializza il modo 13h 320x200x8bpp (256 colori) SOLO PER DOS CON VGA
    mov     al, 13h
    int     10h
    ; fa puntare direttamente alla memoria video SOLO PER DOS
    mov     ax, 0a000h   
    mov     es, ax

    mov     di,319 ; dimensione dell'asse reale in pixel sullo schermo

loop_reale:

    mov    dx,199  ; dimensione dell'asse immaginario in pixel sullo schermo

    ; calcola a = a + delta_a
    fstp    st0
    fld    qword     [a]    ; mette a in st0
    fld    qword    [da]    ; mette l'incremento di a in st1
    fadd    st0,st1        ; a+da
    fstp    qword    [a]    ; mette il risultato in a

loop_immaginario:
    ; calcola b = b + delta_b
    ;fstp    st0        ; resetta lo stack della FPU
    fld    qword     [b]    ; mette b in st0
    fld    qword    [db]    ; mette l'incremento di b in st1
    fadd    st0,st1        ; b+db
    fstp    qword     [b]    ; mette il risultato in b

    ; pulisce tutto lo stack del 387 (8 registri portati a zero)


    ;inizia la fase di calcolo
    fstp    st0
    fld    qword    [a]     ; mette a nello stack
    fld    qword    [b]     ; mette b nello stack

    push     cx        ; salva il registro cx
    mov     cx,255    ; in cx ci sara' il contatore dei cicli di iterazioni di calcolo. Si parte da 256

    fldZ            ; mette stack st3 = 0. Sara' utilizzato come parte reale z.r = 0
    fldZ            ; mette stack st2 = 0. Sara' utilizzato come parte immaginaria z.i = 0
    fldZ              ; mette stack st1 = 0. Sara' utilizzato come parte reale quadrata z.r^2 = 0
    fldZ            ; mette stack st0 = 0. Sara' utilizzato come parte immaginaria quadrata z.i^2 = 0

l1:                ; inizia il loop di calcolo piu' interno
    fsubp    st1,st0        ; sottrae z.i^2- e lo mette nello stack come st0.
    fadd    qword     [a]    ; aggiunge a ad st0
    fstp    st3        ; prende il valore di st3 con pop
    fmulp    st1,st0        ; moltiplica st0 ed st1 z.r*z.i
    fadd    st0,st0        ; moltiplica 2*st0 facendolo come una somma st0+st0
    fadd    qword    [b]    ; aggiunge ad st0 b ovvero 2*z.r+z.i+b

    fld    st1        ; mette st1 in st0 ovvero z.r
    fmul    st0,st0        ; quadrato di z.r
    fld    st1        ; mette st1 in st0 ovvero z.i
    fmul     st0,st0        ; quadrato di z.i
    fld    st1
    fadd    st0,st1        ; somma i due quadrati z.r^2+z.i^2
    fcomp    qword     [limite]; compara st0 con il limite di calcolo 4
    fstsw    ax        ; passa il valore di st0 al registro ax
    sahf            ; mette AH nelle flags
    jae    fine        ; se ax e' sopra il valore di 4 allora esci dal ciclo di calcolo
    dec    ecx        ; decrementa il contatore della iterazioni di calcolo
    jnz    l1        ; se ecx non e' zero continua il calcolo saltando alla label l1

fine:
    ffree    st5
    ffree    st4
    ffree    st3
    ffree    st2
    ffree    st1
    ffree     st0

    ; stampa il colore a seconda del valore di cx
    push    di
    push     bx
    push     dx
    mov     bx,dx     ; in dx c'e' la coordinata schermo immaginaria
    imul    bx,320     ; viene moltiplicata per 320
    add    bx,di    ; in cx c'e' la coordinata schermo reale
    mov    di,bx    ; ha calcolato la posizione in memoria
    mov    [es:di],cl
    pop     dx
    pop    bx
    pop    di

    pop cx


ritorna:
    ;controlla se siamo alla fine di un loop immaginario
    dec     dx
    cmp    dx,0
    jnz    loop_immaginario

    ; resetta la variabile immaginaria
    fld     qword    [bb]
    fstp    qword    [b]


    ;controlla se siamo alla fine di un loop reale
    dec    di
    cmp    di,0
    jnz    loop_reale


    ;esce dal programma
    ; aspetta la pressione di un tasto (SOLO DOS)
    xor     ah, ah
    int     16h

    ; Rimette in modalita' testuale (SOLO DOS)
    mov     ax, 0003h
    int     10h
    ret