Kurs programowania w asemblerze


Tryb 13H

Wstęp

Zacznę od wyjaśnienia, co to jest to tajemnicze 13H. Otóż tryb 13H jest to pewien tryb graficzny, który można uzyskać na chyba każdej karcie graficznej bez żadnych dodatkowych sterowników. Daje on nam rozdzielczość 320x200 i 256 kolorów. Dzięki temu można tworzyć programy wykorzystujące więcej kolorów, np. ogień w bardzo prosty sposób. Ogień jest świetnym przykładem efektu graficznego, którego nie da się uzyskać w zwykłym (standardowym) trybie graficznym dostępnym np. w Turbo Pascal-u (tam mamy 16 kolorów). Tryb ten ma również inne zalety. Bardzo łatwo się go używa (programuje) i nasze procedury zapisane w Asemblerze są szybsze i pewniejsze.

Artykuł który czytasz jest dość specyficzny. Może go czytać zarówno programujący w Pascalu, C/C++, czy Asemblerze. Starałem się wszystko jak najdokładniej tłumaczyć i popierać przykładami (w tych językach). Życzę miłej nauki!

Opis

Jak już wspomniałem tryb ten daje nam rozdzielczość 320x200 i 256 kolorów. Przypominam jednak że współrzędne podajemy od 0, czyli X: 0..319 i Y:0..199. Zajmuje więc 64000 bajtów pamięci (320x200=64000). Wiemy również, że mniej więcej tyle właśnie zajmuje jeden segment pamięci komputera. Segment pamięci ekranu w trybie 13H zaczyna się o adresie A000H. Literka H oznacza, że liczba zapisana jest w systemie szesnastkowym.

Włączenie/Wyłączenie trybu graficznego

Do obsługi trybu graficznego służy przerwanie 10H. Funkcja 0H (Ah=0) ma za zadanie zmiany trybu graficznego/tekstowego. Dostępne są następujące tryby:

ALRodzajRozdz.KoloryKartaSegment pamięci
0tekstowy40x2516/8CGA/EGAB800H
1tekstowy40x2516/8CGA/EGAB800H
2tekstowy80x2516/8 (odcieni)CGA/EGAB800H
3tekstowy80x2516/8CGA/EGAB800H
4graficzny320x2004CGA/EGAB800H
5graficzny320x2004 (odcienie)CGA/EGAB800H
6graficzny640x2002CGA/EGAB800H
7tekstowy80x253MDA/EGAB000H
0DHgraficzny320x20016EGA/VGAA000H
0EHgraficzny640x20016EGA/VGAA000H
0FHgraficzny540x3503EGA/VGAA000H
10Hgraficzny640x3504 lub 16EGA/VGAA000H
11Hgraficzny640x4802VGAA000H
12Hgraficzny640x48014VGAA000H
13Hgraficzny320x200156VGAA000H

My włączamy tryb 13H, czyli nasza procedura Init13H wygląda tak: (pascal)

Procedure Init13H; Assembler;
Asm;
    MOV AX,0013H;
    INT 10H
end;
wersja dla C/C++ [c] void Init13H (void) { union REGS regs; regs.h.ah=0x00; regs.h.al=0x13; int86(0x10,&regs,&regs); } [/c]

Na koniec pracy w grafice trzeba ten tryb zamknąć, a dokładniej mówiąc wywołać tryb standardowy tekstowy (3). Nasza procedura Close13H wygląda więc tak:

Procedure Close13H; Assembler;
Asm;
    MOV AX,0003H
    INT 10H
End;
a dla C: [c] void Close13h (void) { union REGS regs; regs.h.ah=0x00; regs.h.al=0x03; int86(0x10,&regs,&regs); } [/c]

Instrukcje

Punkt o współrzędnych [0,0] ma więc adres A000H:0. Tak więc punkt o współrzędnych [X,Y] znajduje się w pamięci pod adresem A000:Y*320+X.

Turbo Pascal daje nam możliwość odwoływania się do komórek pamięci za pomocą instrukcji MEM. Jeśli chcemy odczytać wartość danej komórki piszemy:

X:=MEM[segment:offset];

Jeśli chcemy zmienić wartość danej komórki, napiszemy:

MEM[segment:offset]:=X;

Prosta procedura rysująca punkt na ekranie mogłaby wyglądać więc tak:

Procedure PutPixel(X,Y : Integer; Kolor : Byte);
Begin
    MEM[$A000:Y*320+X]:=Kolor;
End;

Funkcja odczytująca kolor punktu mogłaby wyglądać tak:

Function GetPixel(X,Y : Integer) : Byte;
Begin
    GetPixel:=MEM[$A000:Y*320+x];
End;

Obie te instrukcje ze względu na działanie matematyczne (Y*320+X) oraz użycie Pascal-owej instrukcji MEM są bardzo wolne. Dlatego należy używać procedury do wstawiania punktu napisanej w Asemblerze. Wiemy, że ten język jest najszybszy. W Asemblerze nasza procedura PutPixel wyglądałaby np. tak:

Procedure PutPixel(X,Y : Integer; Kolor : Byte); Assembler;
Asm
    MOV AX,0A000H
    MOV ES,AX      ; ES - segment pamięci ekranu
    MOV DX,Y       ; DX=Y
    MOV DI,X       ; DI=X
    SHL DX,6       ; DX:=DX*64 [DX=Y*64]
    ADD DI,DX      ; DI:=DI+DX [DI=X+Y*64]
    SHL DX,2       ; DX=DX*4   [DX=DX*64*4=DX*256, DX=Y*256]
    ADD DI,DX      ; DI:=DI+DX [DI=X+Y*64+Y*256 =X+Y(256+64)]
    MOV AL,Kolor   ; AL=kolor
    MOV ES:[DI],AL ; MEM[ES:DI]:=AL;
End;

Sprytne nie. Ta procedura jest znacznie szybsza od poprzedniej. Działa w następujący sposób:

MOV AX,0A000H
MOV ES,AX

W rejestrze ES mamy teraz segment naszego ekranu. Wystarczy wykonać działanie Y*320+X. Można to zrobić używając instrukcji MUL, która służy do mnożenia, jednak jest ona strasznie wolna. Lepiej zastosować tutaj SHL, czyli przesunięcie logiczne. Jest znacznie szybsze, a można za pomocą niego wykonać mnożenie przez potęgę liczby 2. Działanie 320*Y zapisujemy jako Y*256+Y*64. Liczby 256 i 64 są potęgami liczby 2. Dlaczego akurat 256 i 64? Bo wiemy ze wzoru (a+b)*C=A*c+b*c, czyli (256+64)*Y.

Instrukcja GetPixel w Asemblerze jest bardzo podobna.

Function GetPixel(X,Y : Integer) : Byte; Assembler
Asm;
    MOV AX,0A000H
    MOV ES,AX
    MOV DX,Y
    MOV DI,X
    SHL DX,6
    ADD DI,DX
    SHL DX,2
    ADD DX,DI
    MOV AL,ES:[DI]
    MOV @Result,AL
End;

No dobra. Wiemy już jak włączyć tryb graficzny, jak go wyłączyć. Umiemy stawiać punkty, a nawet sprawdzać kolor już postawionych. Zróbmy teraz coś trudniejszego. Narysujmy linię prostą! Jest wiele algorytmów rysowania linii. Ja przedstawię jeden z nich. Algorytm Bresenhama:

Procedure Linia(x1,y1,x2,y2,Kolor : integer);
var c,i : integer;
    sx,sy,y,x : real;
begin
  if x2<x1 then
  begin
   c:=x1;
   x1:=x2;
   x2:=c;
  end;
  if y2<y1 then
  begin
   c:=y2;
   y2:=y1;
   y1:=c;
  end;
  if (x2-x1)>(y2-y1) then
  begin
    sy:=(y2-y1)/(x2-x1);
    y:=y1;
    for i:=x1 to x2 do 
    begin
      putpixel(i,round(y),Kolor);
      y:=y+sy;
    end;
  end else
  begin
    sx:=(x2-x1)/(y2-y1);
    x:=x1;
    for i:=y1 to y2 do 
    begin
      putpixel(round(x),i,Kolor);
      x:=x+sx;
    end;
  end;
end;

To prosty algorytm, ale nie będę się tutaj nad nim rozpisywał. Zapraszam do zajrzenia do działu ALGROYTMY tam zostanie dokładnie omówiony. Zachęcam również do ściągnięcia pliku CirLine, gdzie Mark Feldman opisuje algorytm rysowania linii i koła. Zajrzyj także do działu Źródła algorytmów i Teksty

CDN...

Programy

Przykładowe programy w Turbo Pascalu.

RAYPoruszanie się w trójwymiarowej przestrzeni9 KB???
KoniecEfekt płynącego pionowo tekstu1 KBBinboy
NapisObracany napis1 KBBinboy
ObrótNapis wyginający się na sinusoidzie i obracający się o 360 stopni1 KBBinboy
ProstopadłościanObracane wierzchołki prostopadłościanu1 KBBinboy
ScroolPłynący tekst1 KBBinboy
Sinusoidalny napisNapis płynący po sinusoidzie1 KBBinboy
GwiazdyLatające gwiazdy1 KBBinboy
WyginasNapis wyginający się po sinusoidzie1 KBBinboy
WaterFajny efekt z wodą7 KB???
LaserBardzo ciekawy efekt graficzny5 KB???
CieńObracający się, cieniowany trójkąt15 KB???
LupaEfekt lupy77 KB???
FloorTeksturowanie powierzchni5 KB???
PixturnTrójwymiarowy tunel7 KB???

Przykładowe programy w asemblerze.

DotsObracająca się, stworzona z punktów kula12 KB???
FilldObracający się, wypełniony kolorami sześcian8 KB???
GouraudObracający się sześcian z cieniowaniem12 KB???
GwiazdyLatające gwiazdy3 KB???
LinieObracający się, wykonany z linii sześcian7 KB???
PlazmaCiekawy efekt graficzny91 KB???
ScapeTrójwymiarowa powierzchnia103 KB???
ScroolProsty scrool z ciekawą czcionką28 KB???
TunelTrójwymiarowy tunel10 KB???
Zajrzyj do działu AsmSoft

Moduły potrzebne do uruchomienia niektórych programów.

GraphhighModuł do obsługi różnych trybów graficznych, m.in. VESA (wysokie rozdzielczości)6 KBBinboy
GraphicsModuł do obsługi trybu graficznego 13H. Umożliwia m.in. wstawianie grafiki PCX. Jest w wersji skompilowanej.4 KBBinboy
Vga_libSzybki moduł graficznych do trybu 13H12 KB???
VlibModuł graficzny2 KBGrend
GifModuł umożliwiający wyświetlanie plików graficznych GIF7 KB???
PcxModuł do obsługi plików graficznych PCX5 KBBartok
IkeyModuł do obsługi klawiatury. Umożliwia kontrolowanie kilku klawiszy jednocześnie1 KBBartok
MyszModuł do obsługi myszki2 KB???
CosinModuł wspomagający obliczenia SIN i COS0.5 KBGrend

Autor: Karol Wierzchołowski, opracowano: 12.01.2002 r. Wszelkie prawa zastrzeżone.
Kontakt

Jeśli chcesz się z nami skontaktować napisz na adres: info(at)binboy.org lub odwiedź nasz profil na Facebooku!

O Nas

Serwis binboy.org to kopalnia wiedzy dla wszystkich z branży IT, w szczególności dla programistów i webmasterów. To duży zbiór kursów programowania, tutoriali, darmowych ebooków, setki kodów źródłowych itp.

Bądź w kontakcie

Panel użytkownika

Zaloguj się do panelu użytkownika.
Nie masz konta? Zarejestruj się!
Zapomniałeś hasła?