Tratteremo in questo tutorial un argomento tra i più interessanti nella programmazione. Non riuscirò certo a coprire l'intero argomento, mi propongo solo di dare una infarinatura generale lasciando poi a voi il compito di approfondire l'argomento, in rete si trovano molte informazioni sullaprogrammazione della scheda video.. Il modo grafico che considererò qui è il 13h, quello della VGA "Standard" che lavora a 320x200 con 256 colori. La prima cosa che un programma assembly (ma anche in ogni altro linguaggio) deve fare è impostare la modalità; bene, questo può essere fatto utilizzando l'int 10h tramite la funzione 00h. Quindi: Set_VGA PROC mov ax,0013h ;ah=00 al=13h (modalità 320x200x256) int 10h RET Set_VGA ENDP Una volta terminato il programma si deve reimpostare la modalità testo, anche questo può essere fatto tramite l'int 10h: Set_TXT PROC mov ax,0003h ;ah=00 al=03h (modalita testo 80x25) int 10h RET Set_TXT ENDP Ora che siamo riusciti ad impostare la modalità grafica voluta vediamo come si può mettere un Pixel sullo schermo. Anche per questa operazione si può ricorrere all'int 10h (funzione 0Ch) Put_Pixel PROC mov ah,0Ch mov al,Color ;colore del pixel mov cx,X ;coordinata X mov dx,Y ;coordinata Y mov bx,1 ;numero di pagina (per le modalità con più pagine) int 10h RET Put_Pixel ENDP Un problema di questo modo di posizionare un pixel sul video è dato dalla lentezza veramente insopportabile in alcune applicazioni, perciò invece di usare la funzione del BIOS (int 10h) possiamo accedere direttamente alla memoria video. Il segmento in cui questa risiede è all'indirizzo A000, quindi il punto di coordinate 0,0 sarà allindirizzo A000:0000 quello di coordinate 319,199 a A000:FFFF. E il punto di coordinate 145,76?? Bene per trovare l'indirizzo di un generico punto x,y in memoria si può usare la formula:
ind = x + ( Y * 320)
Chiaro? OK ma cosa ci mettiamo all'indirizzo calcolato?? Bene a quell'indirizzo ci va l'indice del colore del pixel. Per capire bene questo dobbiamo fare una parentesi sulla palette. LA PALETTE La palette è la tavolozza dei colori da usare per realizzre il nostro disegno. Si tratta di un array bidimensionale di 256 elementi ognuno dei quali contiene 3 valori che corrispono al livello di Rosso, Verde, Blue (R G B).
Palette ------- | r|g|b | 0|__|_|__| | r|g|b | 1|__|_|__| |r |g|b | 2|__|_|__| | | | | Come voi saprete mescolando in modo opporutuno il Rosso, Verde e Blue possiamo ottnere tutti i colori che vogliamo. Le gradazioni di R G e B vanno da 0 a 63. Per leggere il valore di R G e B di un colore dalla palette procedo nel modo seguente: get_pal PROC mov dx,3c7h ;porta in cui va indicato l'indice del colore mov al,col ;col è l'indice del colore da leggere (0..255) out dx,al add dx,2 ;3c9h è la porta da cui si leggono i 3 valori in al,dx mov R,al in al,dx mov G,al in al,dx mov B,al ; in R, G e B ho i valori RET get_pal ENDP La procedura inversa, quella per impostare i valori di R G e B nella palette è la seguente: set_pal PROC mov dx,3c8h ;porta incui va indicato l'indice del colore ;da scrivere (NB è diverso dal precedente!!) mov al,col out dx,al ;scrivo sulla porta il colore inc dx ;3c9 è la porta su cui scrivere i 3 valori R G B mov al,R out dx,al mov al,G out dx,al mov al,B out dx,al ;ora nella palette c'è il nuovo colore RET set_pal ENDP Spero di aver chiarito cosìè e come funziona la palette. Tornando al discorso della put_pixel che agisce direttamente in memoria si diceva che all'indirizzo calcolato dalla formula si doveva scrivere l'indice del colore, beh ora è chiaro no? Metto l'indice che il colore ha nella palette. Per concludere il discorso vi lascio un esempio che utilizza un po' tutte le funzioni viste. Si tratta di un pgmche simula l'effetto neve che si vede sui televisori rotti o non sintonizzati. ;SNOW.ASM - By b0nu$, 1997 .286 SEG_A SEGMENT ASSUME CS:SEG_A, DS:SEG_A ORG 100H SNOW PROC FAR INIT: JMP START rgb db 3 dup(?) ; Array che contiene i valori di R G B del colore num_rnd_val dw 12345 ; A caso num_rnd_mul dw 9421 ; A caso START: mov ax,0013h int 10h ;imposto modalità 320x200 xor ax,ax loop_pal: mov rgb[0],al mov rgb[1],al mov rgb[2],al CALL Set_Pal ; imposto la palette con tutte le tonalità di ; grigio nel quale si ha R=G=B. inc al cmp al,0FFh jne loop_pal xor bx,bx ;x=0 Ciclo_x: xor dx,dx ;y=0 ;parto da 0,0 Ciclo_y: push dx ;questo ciclo posiziona a caso pixel sullo schermo push dx CALL Random pop dx CALL Put_Pixel pop dx inc dx cmp dx,0C7h ;199 jne Ciclo_y inc bx cmp bx,013Fh ;319 jne Ciclo_x mov ax,0003h int 10h ;imposto modalità txt RETN SNOW ENDP Put_Pixel PROC ;dx=y bx=x ah=col push ax ;usa l'accesso diretto in memoria video mov ax,0A000h mov es,ax push bx mov dh,dl xor dl,dl shl bx,6 add dx,bx pop bx add bx,dx mov di,bx xor al,al pop ax ;prelevo il colore mov es:[di],ah RET Put_Pixel ENDP Set_Pal PROC ;al=colore mov dx,3c8h ;mov al,[col] out dx,al inc dx mov al,rgb[0] ;red out dx,al mov al,rgb[1] ;green out dx,al mov al,rgb[2] ;blue out dx,al RET Set_Pal ENDP Random PROC ;Genera un numero casuale con l'algoritmo ; di D.Lehmer mov ax,num_rnd_val mul num_rnd_mul inc ax mov num_rnd_val,ax RET Random ENDP SEG_A ENDS END INIT Naturalmente non pretendo certo di aver coperto l'intero l'argomento, prendetelo solo come un introduzione, un punto di partenza da cui spiccare il salto verso la grafica avanzata. Qui spero solo di avervi fatto capire alcuni meccanismi che stanno alla base della programmazione della scheda video VGA.