lekcja7 UXSPYX65TFQBY3E7J7I3JR737236RTWJJPUTWUA


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 nieprzekraczają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.

KODY KLAWISZY KLAWIATURY IBM PC

KLAWISZE

KODY

ASCII (dec)

Home

G

71 (00:47h) `\0','G'

End

O

79 (00:47h) `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,...,g

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

Wyprowadzanie znaków na ekran można przeprowadzić szybciej posługując się przerywaniem DOS INT 29H. Drukowanie na ekranie w trybietekstowym przebiega wtedy szybciej niż robią to standardowe funkcje <stdio.h>, <conio.h>, czy <iostream.h>. Poniżej prosty przykład praktyczny wykorzystania przerywania 29H:

[P132.CPP]

# include <stdlib.h>

# include <conio.h>

# pragma inline

void SpeedBox(int, int, int, int, char);

main()

{

clrscr();

for (; !kbhit(); )

{

int x = rand() % 40;

int y = rand() % 12;

SpeedBox(x, y, (80 - x), (24 - y), ('€' + x % 50));

}

return 0;

}

void SpeedBox(int x1, int y1, int x2, int y2, char znak)

{

int k;

for (; y1 < y2; y1++) { gotoxy(x1, y1);

for (k = x1; k < x2; k++)

{

asm MOV AL, znak

asm INT 29H

}

}

}

[Z]

1. Opracuj program pozwalający porównać szybkość wyprowadzania danych na ekran monitora różnymi technikami (cout, puts(), printf(), asm).

2. Porównaj wielkość plików wynikowych .EXE powstających w różnych wariantach z poprzedniego zadania.

5



Wyszukiwarka

Podobne podstrony:
Lekcja kliniczna 2 VI rok WL
Lekcja Przysposobienia Obronnego dla klasy pierwszej liceum ogólnokształcącego
Lekcja wychowania fizycznego jako organizacyjno metodyczna forma lekcji ruchu
Lekcja kliniczna nr 2 VI rok WL
04 Lekcja
PF7 Lekcja2
lekcja52
Printing bbjorgos lekcja41 uzupelnienie A
lekcja 18 id 265103 Nieznany
Hydrostatyka i hydrodynamika lekcja ze wspomaganiem komputerowym
Lekcja 6 Jak zapamietywac z notatki Tajemnica skutecznych notatek
lekcja 20
lekcja20
Lekcja 04 Szene 04
LINGO ROSYJSKI raz a dobrze Intensywny kurs w 30 lekcjach PDF nagrania audio audio kurs
Printing bbjorgos lekcja01 05 A
'Half Life', czyli pół życia przed monitorem zagrożenia medialne foliogramy gim modul 3 lekcja 5
Lekcja od mamy
lekcja 3 id 265134 Nieznany

więcej podobnych podstron