Visualizzazione post con etichetta Dosbox. Mostra tutti i post
Visualizzazione post con etichetta Dosbox. Mostra tutti i post

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

giovedì 28 aprile 2016

Mandelbrot Mode 13h

Ed ora qualcosa di completamente inutile...Mandelbrot in modo 13h della VGA. Il codice di base e' quello del precedente post riadattato per la visualizzazione grafica a 320x200x256 colori




Visto che per questa visualizzazione si usa l'accesso diretto alla memoria video ed un formato di eseguibile sotto DOS si deve usare DosBox oppure FreeDos in macchina virtuale (non si puo' invece usare DosEmu perche' di fatto questo programma non emula il processore ma si appoggia sul sistema sottostante per cui ogni gestione diretta della memoria crea conflitto con il sottostante sistema operativo)

-------------------------------------------------------------------------
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
    cicli:    dd    255     ; numero di cicli di iterazione per ogni punto

section .text

global _start                   ;serve a 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

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

    push     ecx        ; salva il registro ecx
    mov     ecx,[cicli]    ; in ecx 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

    cmp ecx,0        ; controlla se si e' raggiunto il limite dei cicli di iterazione
    je putpixel           ; se e' zero stampa uno spazio

    pop ecx


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

putpixel:        ; scrive un pixel direttamente sulla memoria VGA
    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    dl,7
    mov    [es:di],dl
    pop     dx
    pop    bx
    pop    di
    jmp    ritorna


-------------------------------------------------------------------------
il programma compilato con nasm (disponibile sia per Linux che per Dos) e' lungo 240 bytes



Per correggere gli errori non si puo' fare debug sotto Linux perche' ddd (ovviamente) non riconosce il formato .COM. Per questo motivo mi sono ricostruito un ambiente di sviluppo in Freedos in macchina virtuale sotto VMWare


Turbo Debugger in FreeDos


Visto che non e' banalissimo usare Freedos un po' di appunti su come installarlo su VMWare. Per prima cosa di monta la .iso del Cd di Freedos e si formatta il disco C:. Al termine l'installer richiede il riavvio del sistema ma ci si trova di fronte alla schermata sottostante perche' VMWare e' ripartito dal disco fisso dove non e' ancora stato installato il sistema


Si deve entrare nel Bios di VMware ed impostare l'ordine di avvio dei dispositivi...peccato che la schermata e' velocissima ed e' praticamente impossibile trovare l'attimo giusto per premere ESC all'avvio. La soluzione piu' semplice e' quella di editare il file in Documenti/My Virtual Machines/MS-DOS/MS_DOS.vmx ed aggiungere la riga 

bios.bootDelay = "5000"

per ritardare il boot di 5 secondi ed avere il tempo di premere ESC


Da qui in poi l'installazione e' banale...rimane il problema di installare il software in un sistema come il DOS che ha pochissima confidenza con le chiavette USB ed il TCP/IP.La soluzione che ho trovato piu' semplice e' stata quella di inserire tutto il software DOS che mi serviva (Volkov Commander, Nasm e Turbo Debugger) in una cartella, convertire la cartella in un file .iso con AnyToIso ed  inserire il file .iso del CD virtuale di VMWare.
Fatta partire la macchina virtuale, dal prompt di Dos, si digita (vedi questo link)

devload uide.sys /N3 /D:CDROM01
shsucdx /D:CDROM01

il Cdrom sara' su D: e si possono copiare il file su C:. I file copiati saranno tutti read-only per cui si deve usare il programma ATTRIB per togliere il flag


venerdì 22 aprile 2016

Assemby x86 e dissemblare in Linux

Un po' di appunti per compilare e decompilare in Assembler sotto Linux

La sintassi di nasm e' simile a quella di TASM ma ci sono alcuni dettagli per cui non e' sempre possibile compilare codice vecchio senza modifiche

Prima di tutto GEdit non ha preimpostata la colorazione della sintassi dei file .asm ma si puo' rimediare con i comandi
wget http://www.carminebenedetto.net/_downloads/asm-intel.lang 
sudo cp asm-intel.lang /usr/share/gtksourceview-3.0/language-specs/

per compilare il codice (compreso della tabella dei simboli per il debug)
nasm -f elf -F dwarf mand_linux.asm
ld mand_linux.o -o mand_linux


per rimuovere i codici di debug (ed ottenere un eseguibile nettamente piu' snello) si puo' aggiungere in fase di link lo switch --strip-all come segue
ld mand_linux.o -o mand_linux --strip-all

per compilare codice a 32 bit su un sistema operativo a 64 bit
nasm -f elf -F dwarf mand_linux.asm
ld -m elf_i386 mand_linux.o -o mand_linux


con nasm si possono compilare anche eseguibili DOS (i vecchi file .COM)
nasm -f bin -o mand_dos.com mand_dos.asm
dosbox mand_dos.com -exit


per compilare codice DOS in formato COM si deve aggiungere in testa al codice la linea

org 100h

il programma DOS puo' essere verificato con DOSBOX
dosbox programma.com -exit

Per decompilare o fare debugging, al posto del complicato gdb, puo' essere molto comodo usare ddd, una IDE di gdb in cui si puo' fare debug step-by-step con breakpoint (tasto destro sulla riga di codice), watch delle variabili e dei valori dei registri del processore


E' anche possibile editare direttamente il codice e ricompilare senza uscire da ddd (questa funzione mi ha creato qualche problema a dire il vero perche' la finestra di debug non sempre e' aggiornata con gli aggiornamenti del codice)

Nel caso di core dump del codice si puo' eseguire
gdb file_eseguibile file_core

seguito dal comando backtrace per capire dove si e' generato il segmentation fault. All'interno di ddd si puo' lanciare l'esecuzione (senza breakpoint), attendere il core dump e poi fare il backtrace direttamente dalla IDE

domenica 26 maggio 2013

Borland Turbo C++ in DosBox

In vena di ricordare il passato ho provato ad installare il compilatore Borland Turbo C++ sulla mia Debian Box.
Il primo tentativo e' stato utilizzando DosEmu ma per motivi non meglio chiariti (non vengono emessi segnali di errore) il programma tc non viene messo in esecuzione
Sono quindi passato a DosBox

Una volta scaricato il pacchetto di Turbo C++ da qualche sito internet (ne ve sono a bizzeffe) e spacchettato all'interno della propria  home si puo' digitare


keyb it
mount c: /home/luca
c: 
cd \tc\bin
tc


l'Ide si apre e si puo' iniziare a scrivere il programma. Il problema si pone quando si vuole mettere in esecuzione con la combinazione CTRL+F9 perche' la medesima combinazione chiude l'applicazione DosBox.
Si deve quindi premere CTRL+F1, selezionare ShutDown e cancellare questa combinazione di tasti


In conclusione comunque e' abbastanza inutile usare Turbo C++ quando si ha disposizione GCC perche' nel 1991, anno di uscita del compilatore Borland, non era stato ancora formalizzato lo standard ANSI. Inoltre al momento attuale il compilatore e' totalmente privo di supporto anche a causa della scomparsa di Borland

Geologi

  E so anche espatriare senza praticamente toccare strada asfaltata