plik


Asembler: DOS: Tryb graficzny Tryb graficzny w języku asembler Na początek uprzedzam: jeśli myślicie o wysokich rozdzielczościach, to się zawiedziecie, gdyż ten kurs nie będzie takich omawiał. Jeśli naprawdę wolicie wysokie rozdzielczości, to poszukajcie w Internecie opisu standardu VESA lub DirectX API. A my, zamiast bawić się w te wszystkie skomplikowane sprawy, zajmiemy się trybem 13h. Ten tryb oferuje rozdzielczość 320x200 w 256 kolorach (co widać też w Liście Przerwań Ralfa Brown'a - RBIL). Ale najważniejszą jego cechą jest to, że 320x200 = 64000 < 64kB, więc cały ekran mieści się w jednym segmencie, co znacznie ułatwia pracę. Ekran w trybie graficznym mieści się w segmencie 0A000h oraz: 0A000:0000 - pierwszy piksel (bajt, 256 możliwości) 0A000:0001 - drugi piksel 0A000:0002 - trzeci piksel ... Do zmiany trybu graficznego używa się przerwania 10h, funkcji 0 (opis wyjęty z Listy przerwań 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 widać, zmiana trybu graficznego na omawiany tryb 13h nie jest trudniejsza niż: mov ax, 13h int 10h Powrót do tradycyjnego trybu tekstowego 80x25 wygląda tak: mov ax, 3 int 10h Pytanie brzmi: jak cokolwiek narysować? Nic prostszego! Po prostu pod adres: wiersz*320 + kolumna zapisujemy odpowiedni bajt, np. tak (składnia 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 mało na nasze ambicje, prawda? Spróbujmy narysować poziomą linię (NASM): przeskocz program rysujący linię poziomą ; 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 ; przenieś 10 bajtów wartości 15 pod ; es:di = 0a000:0000 xor ah, ah int 16h mov ax, 3 int 10h ; powrót do trybu tekstowego mov ax, 4c00h int 21h To chyba nie było zbyt trudne, prawda? No to spróbujmy coś trudniejszego: linia pionowa. Cała filozofia w tym przypadku polega na tym, aby po narysowaniu piksela przejść o 1 wiersz niżej (czyli o 320 bajtów dalej). Piszmy więc (NASM): przeskocz program rysujący linię pionową ; 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 było łatwo: rysować zaczynaliśmy w lewym górny rogu, więc DI był równy 0. A co, jeśli chcemy wyświetlać piksele gdzieś indziej? Cóż, są dwie możliwości: W czasie pisania programu (czyli przed kompilacją) znasz dokładną pozycję, gdzie będziesz rysować. W takim przypadku kompilator policzy DI za ciebie, wystarczy wpisać coś takiego: mov di, wiersz*320 + kolumna wstawiając w miejsce słów wiersz i kolumna znane przez siebie wartości. Pozycja, gdzie będziesz rysować jest zmienna i zależy np. od tego, co wpisze użytkownik. Tutaj jest gorzej. Trzeba wpisać do programu instrukcje, które przemnożą wiersz przez 320 i dodadzą kolumnę. Należy raczej unikać powolnej instrukcji (I)MUL. Ten problem rozwiążemy tak (wiersz i kolumna to 2 zmienne po 16 bitów): 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 przykład: rysowanie okręgu (no, w każdym razie czegoś co miało być okręgiem a ma kształt bardziej przypominający elipsę...). Program ten wykorzystuje koprocesor do policzenia sinusów i kosinusów dla kątów od 0 do 360 stopni, przerobionych na radiany. Komentarze obok instrukcji FPU oznaczają stan stosu, od st(0) z lewej. przeskocz program rysujący koło ; 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 fld1 fild word [r] ; r, 1, pi/180 fldz ; kąt=0, r, 1, pi/180 mov al, 15 rysuj: fld st0 ; kąt, kąt, r, 1, pi/180 fmul st4 ; kąt w radianach mov di, 100*320 + 160 ; środek ekranu fsin ; sin(kąt), kąt, r, 1, pi/180 fmul st2 ; sin(kąt)*r, kąt, r, 1, pi/180 fistp word [wys] ; kąt, r, 1, pi/180 fld st0 ; kąt, kąt, r, 1, pi/180 fmul st4 ; kąt w radianach fcos ; cos(kąt), kąt, r, 1, pi/180 fmul st2 ; r*cos(kąt), kąt, r, 1, pi/180 fistp word [szer] ; kąt, r, 1, pi/180 add di, [szer] ; dodajemy odległość poziomą mov dx, [wys] mov bx, dx shl dx, 8 shl bx, 6 add dx, bx ; dx = wys*320 sub di, dx ; odejmujemy odległość pionową mov [es:di], al ; wyświetlamy 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, używając FSIN i FCOS, można rysować np. linie ukośne, które pominąłem w tym kursie. Mam nadzieję, że po lekturze tego odcinka każdy bez problemów będzie rysował w tym dość prostym (zwłaszcza do nauki) trybie graficznym. Miłego eksperymentowania! Spis treści off-line (Alt+1) Spis treści on-line (Alt+2) Ułatwienia dla niepełnosprawnych (Alt+0)

Wyszukiwarka

Podobne podstrony:
DOS GRAF TUT
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