LEKCJA 37: KA�DY DYSK JEST ZA MA�Y, A KA�DY PROCESOR ZBYT WOLNY... ________________________________________________________________ W trakcie tej lekcji dowiesz si�, jak komputer dysponuje swoimi zasobami w �rodowisku tekstowym (DOS). ________________________________________________________________ Truizmy u�yte w tytule maj� znaczy�, �e "zasoby najlepszego nawet komputera s� ograniczone" i zwykle okazuj� si� wystarczaj�ce tylko do pewnego momentu. Najbardziej newralgiczne zasoby to: * czas mikroprocesora i * miejsce w pami�ci operacyjnej. Tworzone przez nas programy powinny wystrzega� si� zatem najci�szych grzech�w: * nie pozwala� mikroprocesorowi na s�odkie nier�bstwo; Rzadko uzmys�awiamy sobie, �e oczekiwanie na naci�ni�cie klawisza przez u�ytkownika (czasem po przeczytaniu napisu na ekranie) trwa sekundy (1, 2, .... czasem 20), a ka�da sekunda lenistwa PC to stracone miliony cykli mikroprocesora. * oszcz�dnie korzysta� z pami�ci dyskowej, a szczeg�lnie oszcz�dnie z pami�ci operacyjnej RAM. MODELE PAMI�CI IBM PC. Jak zapewne wiesz, Tw�j PC mo�e mie�: * pami�� ROM (tylko do odczytu), * konwencjonaln� pami�� RAM (640 KB), * pami�� rozszerzon� EMS i XMS, * pami�� karty sterownika graficznego ekranu (np. SVGA-RAM), * pami�� Cache dla buforowania operacji dyskowych. Najcz�ciej stosowane modele pami�ci to: * Small - ma�y, * Medium - �redni, * Compact - niewielki (tu mam w�tpliwo��, mo�e "taki sobie" ?), * Large - du�y, * Huge - jeszcze wi�kszy, odleg�y. Dodatkowo mo�e wyst�pi� * Tiny - najmniejszy. Taki podzia� zosta� spowodowany segmentacj� pami�ci komputera przez procesory Intel 8086 i podzia�em pami�ci na bloki o wielko�ci 64 KB. Model Small (Tiny, je�li jest) jest najszybszy, ale najmniej pojemny. Model Huge - odwrotnie - najpojemniejszy, za to najwolniejszy. Model Tiny powoduje ustawienia wszystkich rejestr�w segmentowych mikroprocesora na t� sam� warto�� (pocz�tek tej samej stronicy pami�ci) i umieszczenie wszystkich zasob�w programu wewn�trz wsp�lnego obszaru pami�ci o wielko�ci nie przekraczaj�cej 64 KB. Wszystkie skoki s� wtedy "kr�tkie", a wszystkie pointery (adresy) 16-bitowe. Kompilacja z zastosowaniem modelu Tiny pozwala uzyska� program wykonywalny w wersji *.COM (a nie *.EXE). Ale niestety nie wszystkie programy mieszcz� si� w 64 KB. W modelu Small segment kodu jest jeden (kod max. 64 K) i segment danych te� tylko jeden (dane max. 64 K), ale s� to ju� dwa r�ne segmenty. Zestawienia najwa�niejszych parametr�w poszczeg�lnych modeli pami�ci przedstawia tabelka poni�ej: Modele pami�ci komputera IBM PC. ________________________________________________________________ Model Segment kodu Segment danych *dp *cp ________________________________________________________________ Tiny 1 1 (CS = DS) 16 bit 16 bit Small 1 1 16 bit 16 bit Medium wiele 1 16 bit 32 bit Compact 1 wiele 32 bit 16 bit Large wiele wiele 32 bit 32 bit Huge wiele wiele 32 bit 32 bit ________________________________________________________________ *dp - data pointer - wska�nik do danych (near/far) *cp - code pointer - wska�nik do kodu. Large - kod + dane = max. 1 MB. Huge - kod = max. 1 MB, wiele segment�w danych po 64 K ka�dy. Wynikaj�ce z takich modeli pami�ci kwalifikatory near, far, huge dotycz�ce pointer�w w C++ nie s� akceptowane przez standard ANSI C (poniewa� odnosz� si� tylko do IBM PC i nie maj� charakteru uniwersalnego). Trzeba tu zaznaczy�, �e typ wska�nika jest przez kompilator przyjmowany domy�lnie (automatycznie) zgodnie z wybranym do kompilacji modelem pami�ci. Je�li poruszamy si� wewn�trz niewielkiego obszaru pami�ci, mo�esz "forsowa�" bli�szy typ pointera, przyspieszaj�c tym samym dzia�anie program�w: huge *p; ... near *ptr; //Bliski pointer ... near int Funkcja(...) //Bliska funkcja { ... } #define ILE (1024*640) near unsigned int Funkcja(void) { huge char *ptr; // tu d�ugi pointer jest niezb�dny long suma = 0; for (p = 0; p < ILE; p++) suma += *p; return (suma); } Zar�wno zadeklarowanie funkcji jako bliskiej (near), jak i jako statycznej (static) powoduje wygenerowanie uproszczonej sekwencji wywo�ania funkcji przez kompilator. Daje to w efekcie mniejszy i szybszy kod wynikowy. IDENTYFIKACJA KLAWISZY. Znane Ci z pliku <stdio.h> i <conio.h> "klasyczne" funkcje obs�ugi konsoli maj� pewne zalety. Korzystanie z klasycznych, nieobiektowych mechanizm�w powoduje z regu�y wygenerowanie znacznie kr�tszego kodu wynikowego. Funkcje scanf() i gets() wymagaj� wci�ni�cia klawisza [Enter]. Dla szybkiego dialogu z komputerem znacznie bardziej nadaj� si� szybsze getch() i kbhit(). Poniewa� klawiatura zawiera tak�e klawisze specjalne (F1 ... F10, [Shift], [Del], itp.), pe�n� informacj� o stanie klawiatury mo�na uzyska� za po�rednictwem funkcji bioskey(), korzystaj�cej z przerywania BIOS Nr 16. Oto kr�tki przyk�ad zastosowania funkcji bioskey(): #include "bios.h" #include "ctype.h" #include "stdio.h" #include "conio.h" # define CTRL 0x04 # define ALT 0x08 # define RIGHT 0x01 # define LEFT 0x02 int klawisz, modyfikatory; void main() { clrscr(); printf("Funkcja zwraca : %d", bioskey(1)); printf("\n Nacisnij klawisz ! \n"); while (!bioskey(1)); printf("Funkcja zwrocila: %c", bioskey(1)); printf("\nKod: %d", (char)bioskey(1)); ... A to jeszcze inny spos�b korzystania z tej bardzo przydatnej funkcji, tym razem z innymi parametrami: /* Funkcja z parametrem (0) zwraca kod klawisza: ------ */ klawisz = bioskey(0); /* Funkcja sprawdza stan klawiszy specjalnych --------- */ modyfikatory = bioskey(2); if (modyfikatory) { printf("\n"); if (modyfikatory & RIGHT) printf("RIGHT"); if (modyfikatory & LEFT) printf("LEFT"); if (modyfikatory & CTRL) printf("CTRL"); if (modyfikatory & ALT) printf("ALT"); printf("\n"); } /* drukujemy pobrany klawisz */ if (isalnum(klawisz & 0xFF)) printf("'%c'\n", klawisz); else printf("%#02x\n", klawisz); } Nale�y tu zwr�ci� uwag�, �e funkcje kbhit() i bioskey() nie dokonuj� czyszczenia bufora klawiatury. Identyfikuj� znak (znaki) w buforze, ale pozostawiaj� bufor w stanie niezmienionym do dalszej obr�bki. Zwr�� uwag�, �e funkcja getch() mo�e oczekiwa� na klawisz w niesko�czono��. Sprawdzi� szybciej, czy u�ytkownik nacisn�� ju� cokolwiek mo�esz np. tak: if (kbhit()) ...; if (!kbhit()) ...; while (!bioskey(1)) ... if (bioskey(1)) ...; Inn� wielce przydatn� "szybk�" funkcj� jest getch(). Oto praktyczny przyk�ad pobierania i testowania naci�ni�tych klawiszy klawiatury. [P131.CPP] # include "stdio.h" # include "conio.h" char z1, z2; void Odczyt(void) { z2 = '\0'; z1 = getch(); if (z1 == '\0') z2 = getch(); } main() { clrscr(); printf("\nKropka [.] = Quit"); printf("\nRozpoznaje klawisze [F1] ... [F3] \n\n"); for (;;) { while(!kbhit()); Odczyt(); if (z1 == '.') break; if (z1 != '\0') printf("\nZnak: %c", z1); else switch (z2) { case ';' : printf("\n F1"); break; case '<' : printf("\n F2"); break; case '=' : printf("\n F3"); break; default : printf("\n Inny klawisz specjalny!"); } } return 0; } Klawisze specjalne powoduj� wygenerowanie dwubajtowego kodu (widzianego w powy�szym przyk�adowym programie jako dwa jednobajtowe znaki z1 i z2). Funkcja getch() pobiera te bajty z bufora klawiatury kolejno jednocze�nie czyszcz�c bufor. W przypadku klawiszy specjalnych pierwszy bajt jest zerowy (NULL, '\0', 00h), co jest sprawdzane w programie. A oto tabela kod�w poszczeg�lnych klawiszy: Kody klawiszy klawiatury IBM PC. ________________________________________________________________ Klawisze Kody ASCII (dec) ________________________________________________________________ Home G 71 (00:47h) '\0', 'G' End O 79 (00:4Fh) '\0', 'O' PgUp I 73 PgDn Q 81 Ins R 82 Del S 83 F1 ; 59 F2 ... F10 <, ... D 60, ... 68 Shift + F1 T 84 ... Shift + F10 ] 93 Ctrl + F1 ^ 94 ... Ctrl + F10 f 103 Alt + F1...F10 h, ... q 104, ... 113 Alt + 1...9 x, ... � (?) 120, ... 128 Alt + 0 � (?) 129 Strza�ki kursora: LeftArrow K 75 RightArrow M 77 UpArrow H 72 DownArrow P 80 Ctrl + PgDn v 118 Ctrl + PgUp � (?) 132 Ctrl + Home w 119 Ctrl + End u 117 ______________...
marekpel