|
|
Programowanie Główna assembler Pamięć
Pamięć - centrum każdego komputera jest nie mniej ważna niż procesor. Jest aż tak ważna, że ciężko wyobrazić sobie komputery bez tej właśnie jednostki. Co prawda istniały kiedyś maszyny bez pamięci, ale były to wielkie szafy, praktycznie nieprzydatne, później, gdy pamięci przybyło, powstały komputery IBM PC o ilości pamięci zmierzającej do 1MB powstali problem jej adresowania. Moznaby adresować poszczególne jej komórki bezpośrednio, czyli przy 1MB pamięci pierwsza miałaby numer 0, a ostatnia FFFFFh, lecz byłoby to niewygodne. Wyobraź sobie, gdybyśmy nie mieli podziału na miesiące i dni, a jedynie na jednostk. Czy mówiłoby Ci cos takie zdanie? \'Spotkajmy sie o F834A2h!\'. Wątpię. Tak samo byłoby w przypadku pamięci, mądre głowy wymyśliły wiec, że pamięć będzie dzielić się na segmenty, które zaczynać się będą co 16B i zajmować będą FFFFh bajtów:
Struktura pamieci:
S 16B
E S 16B
G E S
M G E |
E M G |
N E M
T N E FFFFb
1 T N / 2 T | 3 /
Oznacza, to, ze od chwili wprowadzenia ich szatańskiego pomysłu, aby dostać się do konkretnego bajtu w pamięci trzeba najpierw podać numer segmentu, a po dwukropku numer tego właśnie bajtu w segmencie. Przykładowo szesnasty bajt pamięci to [0:16] , lub tez [1:0]. Ostatnim bajtem pamięci jest [FFFF:FFFF] zakładając, ze mamy do czynienia z pamięcią 1-Megabajtowa. Jeśli chcesz zaadresować wyższe bajty pamięci to będziesz potrzebować różnych specjalnych sposobów, których tu nie będę omawiać. Aby zapisać cos do pamięci powinieneś skorzystać ze znanego Ci polecenia MOV GDZIE,CO. Aż się chce napisać cos takiego:
Niestety, sytuacja nie jest tak prosta. Otóż numer segmentu zawsze podajemy w rejestrze. Nie dość jeszcze, że w rejestrze to na dodatek w specjalnym rejestrze! W rejestrze segmentowym!
Rejestry segmentowe:
CS - Code Segment - Segment Kodu - Ten rejestr zawiera numer segmentu w ktorym zawarty jest kod programu DS - Data Segment - Segment Informacji - Tu zas zawarty jest numer segmentu zawierajacego zmienne SS - Stack Segment - Segment Stosu - Numer segmentu stosu. Co to jest stos dowiesz sie pozniej, bo narazie Cie to wcale nie interesuje. ES - Extra Segment - Segment Dodatkowy - Jakikolwiek numer jakiegokolwiek segmentu. Teoretycznie mógłbyś do polecenia mov użyć dowolnego z tych rejestrów. W praktyce jednak będziesz korzystać jedynie z ES, bo jest to jedyny rejestr segmentowy, którego zawartość możesz zmieniać bez obawy o to, że coś popsujesz. Wiedząc o tym mógłbyś spróbować dobrać się do pamięci tak:
1 2 3 4
| asm mov es,$B900 mov ES:0 , 32 end; |
Mógłbyś, gdyby nie kolejny wymysł wielkich mądrych głów, które stworzyły Pascala. Otóż z niewiadomych przyczyn do rejestru segmentowego przenosić możesz jedynie zawartość rejestrów ogólnego przeznaczenia! Najpierw więc musisz przenieść numer segmentu do np. AX, później do ES, a później dopiero odwołując się do ES zapisać cos w pamięci:
1 2 3 4 5
| asm mov ax,$B900 mov es,ax mov es:0 , 32 end; |
Wszystko byłoby cacy, gdyby nie fakt, ze pamięci możesz przenosić tylko wartości z połówek rejestrów ogólnego przeznaczenia (lub ze zmiennych typu byte)! Musisz wiec Przenieść numer segmentu do AX, później z AX do ES, później jeszcze do np. AL przenieść liczbę, a później dopiero z AL do pamięci:
1 2 3 4 5 6
| asm mov ax,$B900 mov es,ax
mov al,32 mov es:0 , al. |
Taadaa!! Przeniosles do miejsca o adresie B900h:0 wartosc 63!
Teraz mogę Ci powiedzieć w sekrecie, ze segment B900h nie jest zwykłym, losowo wybranym segmentem pamięci. Odpowiada on za pamięć karty graficznej! Jeśli zmienisz bajt zerowy na bajt odpowiadający jakiemuś znaku (kod ASCII) to w lewym górnym rogu ekranu pojawi się ten właśnie znak! Powyższa procedura np. wstawiała spacje jako znak w lewym górnym rogu ekranu. Warto jeszcze zauważyć, ze kolejny, drugi znak nie jest bajtem o numerze 1 , a o numerze 2, znak trzeci jest bajtem o numerze 4 , czwarty ma numer 6 itd.. Po prostu na każdy znak przypadają dwa bajty: pierwszy - kod znaku, drugi - jego kolor.Popatrz na poniższy program i zgadnij - co on robi?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| asm mov ax,$B900 mov es,ax mov al,32 mov ah,0 mov bx,0 @znak: mov es:[bx],al. {Jesli za numer komorki podajemy rejestrrnto musimy umiescic go w nawiasach kwadratowych} inc bx mov es:[bx],ah inc bx cmp bx,4000 {Czy doszlismy do ostatniego znakurnna ekranie?} jnz @znak {Jesli nie to wroc do @znak} end; end; |
Ten program przenosi do es numer segmentu karty graficznej, oraz do bx liczbę zero. W AL jest wartość odpowiadająca spacji, a w ah wartość zero, czyli zwykły tekst. Później program zapisuje do es:0 kod 32, do es:1 wartość zero, do es:2 znowu kod 32 itd do czasu, gdy BX nie wzrośnie do 4000, czyli do ostatniego znaku ekranu (25 linii*80 znaków na linie*2 bajty na znak = 4000). Innymi słowy mówiąc: czyści ekran :-)
Istnieje pewna rzecz, o której powinieneś wiedzieć zanim dorwiesz się do pamięci: nie należy ona tylko do Ciebie! Mimo, ze to właśnie twój program jest uruchomiony w pamięci cały czas znajdują się inne programy, np. sterownik myszy, czy DOS. One także używają kawałka pamięci. Jeśli go zmienisz to możesz zdrowo namieszać! Zamiast więc tworzyć sobie zmienne w pamięci nie patrząc na to, co w niej jest lepiej skorzystaj z pascalowych zmiennych. Co prawda maja pewne ograniczenia, ale mniej z nimi jest roboty. Obsługa pamięci przyda Ci się np. podczas obsługi trybu graficznego, gdy aby postawić pixel będziesz musiał odwoływać się do specjalnego segmentu.
|
|