GRAF TUT



#Start Contents

Tryb graficzny w jezyku asembler

Na poczatek uprzedzam: jesli myslicie o wysokich rozdzielczosciach,
to sie zawiedziecie, gdyz ten kurs nie bedzie takich omawial. Jesli
naprawde wolicie wysokie rozdzielczosci, to poszukajcie w Internecie
opisu standardu VESA lub DirectX API.
A my, zamiast bawic sie w te wszystkie skomplikowane sprawy, zajmiemy
sie trybem 13h. Ten tryb oferuje rozdzielczosc 320x200 w 256 kolorach
(co widac tez w Liscie Przerwan Ralfa Brown'a - RBIL).
Ale najwazniejsza jego cecha jest to, ze 320x200 = 64000 < 64kB, wiec
caly ekran miesci sie w jednym segmencie, co znacznie ulatwia prace.
Ekran w trybie graficznym miesci sie w segmencie 0A000h oraz:
0A000:0000 - pierwszy piksel (bajt, 256 mozliwosci)
0A000:0001 - drugi piksel
0A000:0002 - trzeci piksel
...
Do zmiany trybu graficznego uzywa sie przerwania 10h, funkcji 0 (opis
wyjety z Listy przerwan Ralfa Brown'a):
przeskocz opis int 10h, ah=0
INT 10 - VIDEO - SET VIDEO MODE
AH = 00h
AL = desired video mode (see #00010)
Return: AL = video mode flag (Phoenix, AMI BIOS)
20h mode > 7
30h modes 0-5 and 7
3Fh mode 6
AL = CRT controller mode byte (Phoenix 386 BIOS v1.10)
Desc: specify the display mode for the currently active display
adapter

Jak widac, zmiana trybu graficznego na omawiany tryb 13h nie jest
trudniejsza niz:
mov ax, 13h
int 10h

Powrot do tradycyjnego trybu tekstowego 80x25 wyglada tak:
mov ax, 3
int 10h

Pytanie brzmi: jak cokolwiek narysowac?
Nic prostszego! Po prostu pod adres:
wiersz*320 + kolumna
zapisujemy odpowiedni bajt, np. tak (skladnia TASM):
mov ax, 0a000h
mov es, ax
xor di,di
mov byte ptr es:[di],15 ; NASM/FASM: mov byte [es:di],15

No ale 1 piksel to za malo na nasze ambicje, prawda?
Sprobujmy narysowac pozioma linie (NASM):
przeskocz program rysujacy linie pozioma
; nasm -O999 -o liniapoz.com -f bin liniapoz.asm

org 100h

mov ax, 13h
int 10h ; uruchom tryb graficzny 13h

mov ax, 0a000h
mov es, ax
xor di, di

mov al, 15
mov cx, 10

rep stosb ; przenies 10 bajtow wartosci 15 pod
; es:di = 0a000:0000

xor ah, ah
int 16h

mov ax, 3
int 10h ; powrot do trybu tekstowego

mov ax, 4c00h
int 21h

To chyba nie bylo zbyt trudne, prawda? No to sprobujmy cos
trudniejszego: linia pionowa.
Cala "filozofia" w tym przypadku polega na tym, aby po narysowaniu
piksela przejsc o 1 wiersz nizej (czyli o 320 bajtow dalej). Piszmy
wiec (NASM):
przeskocz program rysujacy linie pionowa
; nasm -O999 -o liniapio.com -f bin liniapio.asm

org 100h

mov ax, 13h
int 10h

mov ax, 0a000h
mov es, ax
xor di, di

mov al, 15
mov cx, 100

rysuj:
mov [es:di], al
add di, 320
loop rysuj

xor ah, ah
int 16h

mov ax, 3
int 10h

mov ax, 4c00h
int 21h

Na razie bylo latwo: rysowac zaczynalismy w lewym gorny rogu, wiec DI
byl rowny 0. A co, jesli chcemy wyswietlac piksele gdzies indziej?
Coz, sa dwie mozliwosci:
1. W czasie pisania programu (czyli przed kompilacja) znasz dokladna
pozycje, gdzie bedziesz rysowac.
W takim przypadku kompilator policzy DI za ciebie, wystarczy
wpisac cos takiego:
mov di, wiersz*320 + kolumna
wstawiajac w miejsce slow "wiersz" i "kolumna" znane przez siebie
wartosci.
2. Pozycja, gdzie bedziesz rysowac jest zmienna i zalezy np. od
tego, co wpisze uzytkownik.
Tutaj jest gorzej. Trzeba wpisac do programu instrukcje, ktore
przemnoza wiersz przez 320 i dodadza kolumne. Nalezy raczej
unikac powolnej instrukcji (I)MUL. Ten problem rozwiazemy tak
(wiersz i kolumna to 2 zmienne po 16 bitow):
mov ax, [wiersz]
mov bx, [wiersz] ; BX = AX
shl ax, 8 ; AX = AX*256
shl bx, 6 ; BX = BX*64 = AX*64
add ax, bx ; AX = AX*256 + AX*64 = AX*320 =
; = wiersz*320
add ax, [kolumna] ; AX = wiersz*320 + kolumna

mov di,ax

Ostatni przyklad: rysowanie okregu (no, w kazdym razie czegos co
mialo byc okregiem a ma ksztalt bardziej przypominajacy elipse...).
Program ten wykorzystuje koprocesor do policzenia sinusow i kosinusow
dla katow od 0 do 360 stopni, przerobionych na radiany. Komentarze
obok instrukcji FPU oznaczaja stan stosu, od st(0) z lewej.
przeskocz program rysujacy kolo
; nasm -O999 -o kolo.com -f bin kolo.asm

org 100h

mov ax, 13h
int 10h

mov ax, 0a000h
mov es, ax

mov cx, 360

finit
fldpi
fild word [sto80]

fdivp st1, st0 ; pi/180

finit
fld1
fild word [r] ; r, 1, pi/180
fldz ; kat=0, r, 1, pi/180

mov al, 15

rysuj:
fld st0 ; kat, kat, r, 1, pi/180

fmul st3 ; kat w radianach
mov di, 100*320 + 160 ; srodek ekranu

fsin ; sin(kat), kat, r, 1, pi/180
fmul st2 ; sin(kat)*r, kat, r, 1, pi/180

fistp word [wys] ; kat, r, 1, pi/180

fld st0 ; kat, kat, r, 1, pi/180
fcos ; cos(kat), kat, r, 1, pi/180
fmul st2 ; r*cos(kat), kat, r, 1, pi/180

fistp word [szer] ; kat, r, 1, pi/180

add di, [szer] ; dodajemy odleglosc pozioma

mov dx, [wys]
mov bx, dx
shl dx, 8
shl bx, 6
add dx, bx ; dx = wys*320

sub di, dx ; odejmujemy odleglosc pionowa

mov [es:di], al ; wyswietlamy piksel

fadd st0, st2 ; kat += 1

dec cx
jnz rysuj

finit

xor ah, ah
int 16h

mov ax, 3
int 10h

mov ax, 4c00h
int 21h

r dw 50
szer dw 0
wys dw 0
sto80 dw 180

Podobnie, uzywajac FSIN i FCOS, mozna rysowac np. linie ukosne, ktore
pominalem w tym kursie.
Mam nadzieje, ze po lekturze tego odcinka kazdy bez problemow bedzie
rysowal w tym dosc prostym (zwlaszcza do nauki) trybie graficznym.
Milego eksperymentowania!

Spis tresci off-line (Alt+1)
Spis tresci on-line (Alt+2)
Ulatwienia dla niepelnosprawnych (Alt+0)


Wyszukiwarka

Podobne podstrony:
GRAF TUT
DOS GRAF TUT
GRAF TUT
ART121 tut 2
phys tut 08
phys tut 12
DOS DIOD TUT
KOMP Rachunek wyników graf
SYS TUT
ART121 tut 3
graf
MYSZ TUT

więcej podobnych podstron