Powrót do strony wyboru lekcji

Wiadomości wstępne



Wszystkie systemy Windows począwszy od Windows 3.1 udostępniają tzw API. Jest to zestaw procedur dostępnych dla programisty za pomocą których może budować działające aplikacje, a trzymając się pewnych standardów także przyśpieszyć znacząco budowę swoich programów. W programie pisanym w Asemblerze pod systemem Windows wykorzystywane są one na szeroką skale.

Powstawanie typowego programu w asemblerze wiąże się z podziałem kodu programu asemblerowego na osobne bloki tj. na sekcję kodu .CODE i sekcję danych .DATA.

Komentarze w programie definiujemy po znaku ;.Dane w programie to wszystkie zmienne, czyli liczby, tablice, rekordy, wszystko co wykorzystujemy w celu przeprowadzenia w programie jakiejkolwiek operacji. Jednak zdefiniowanie sekcji danych w schemacie najprostszego programu nie jest wymagane. O ile w językach wysokiego poziomu pewne schematy budowania programów są ściśle narzucone przez kompilator, o tyle w asemblerze można utworzyć plik wykonywalny od całkowitych podstaw i ma się na tę operację największy możliwy wpływ. Przykładowy schemat najprostszego programu można przedstawić następująco:


.586 ;typ instrukcji procesora

.MODEL FLAT,STDCALL

.CODE;początek sekcji kodu

Start:

RET

END Start

Dyrektywa .586 ustala że program może wykorzystywać instrukcje procesora 80586 lub wcześniejsze. Polecenie MODEL FLAT,STDCALL określa tryb pamięci używany w programie jako płaski (flat), a także definiuje sposób wywołania wszystkich procedur stosowanych w programie na tzw. STDCALL. Określenie sekcji kodu dokonujemy za pomocą .CODE. Początek programu określamy za pomocą etykiety Start:. Program nie istnieje jeśli nie zawiera żadnej instrukcji wykonywalnej. W przypadku najprostszego programu zdefiniowanego powyżej jest to instrukcja RET czyli powrót z procedury, dzięki której sterowanie oddawane jest z powrotem do systemu operacyjnego. Polecenie END określa koniec programu. Etykietę Start należy wpisać również po dyrektywie END, ponieważ w ten sposób informujemy asembler, żeby wpisał dane punktu wejścia programu do nagłówka ładowanego modułu .

Z technicznego punktu widzenia system wywołuje program , a na stosie odkłada adres powrotu , umiejscowiony gdzieś w kodzie systemu. Schemat wywołania programu określony jest na Rys1.

Nie można wyświetlić obrazu
Rys.1. Schemat wywołania programu w systemie Windows.

Wczytanie programu do pamięci powoduje załadowanie do pamięci odpowiednio sekcji kodu i danych. Tym samym zmienne, do których program odwołuje się w sekcji kodu automatycznie są inicjowane przez system. Następuje przekazanie sterowania przez system do pierwszej instrukcji programu. W momencie wywołania funkcji ExitProcess sterowanie oddawane jest do systemu, pobierana jest wcześniej odłożona na stos wartość przez system operacyjny i tym samym program kończy działanie, poprzez "powrót z procedury" i zwolnienie zasobów programu .

Zanim jednak uruchomimy nasz program na etapie konsolidacji następuje dołączenie innych modułów obiektowych i bibliotek do modułu głównego który w punkcie startowym segmentu musi mieć zdefiniowaną etykietę Start:. Za pomocą dyrektywy INCLUDE możemy dołączyć pliki zawierające dane, czy też procedury, które zostaną dołączone do modułu głównego i wywołane razem z nim. Pliki dołączone tą dyrektywą maja rozszerzenie .inc . Przykładowo do kodu podanego powyżej możemy dołączyć standardową bibliotekę zawierającą wszystkie pliki nagłówkowe, zawierającą się w folderze include o nazwie masm32rt.inc:


INCLUDE \masm32\include\masm32rt.inc ;dołączona biblioteka

.586 ;typ instrukcji procesora

.MODEL FLAT,STDCALL

.CODE;początek sekcji kodu

Start:

RET

END Start

Alternatywą dla INCLUDE jest INCLUDELIB, dzięki której dołącza się procedury z innych modułów obiektowych. Dyrektywa zostaje zapisana w kodzie obiektowym i jest później wykorzystywana przez program link.exe. Ogólnie wywoływanie procedur zdefiniowanych w innych modułach obiektowych można przeprowadzić na 2 sposoby:
a) Wykorzystując dyrektywę INVOKE w następującej postaci:


INVOKE NAZWA_PROCEDURY,p4,p3,p2,p1

,gdzie p4, p3, p2, p1 to parametry procedury.

b) Zdefiniowanie procedury w module głównym w następujący sposób:


EXTERN NAZWA_PROCEDURY@16:NEAR

,gdzie EXTERN oznacza jej deklarację, a liczba podana za znakiem @ wyznacza ilość potrzebnych bajtów jakie należy odłożyć na stos dla parametrów przed wywołaniem procedury. W procedurze zdeklarowanej powyżej jest to 16 bajtów. NEAR zaznacza, iż zdefiniowana procedura znajduje się w tym samym segmencie, co moduł wywołujący, ponieważ jak już wcześniej było wspomniane w systemie Windows, pamięć traktowana jest jak jeden segment - sekcja .MODEL FLAT.

Następnie taką procedurę wywołujemy za pomocą zwykłej instrukcji CALL, a jej parametry podajemy od góry do dołu, zaczynając od parametru najbardziej po prawej stronie. W przypadku procedury NAZWA_PROCEDURY@16, którą przykładowo zdeklarowaliśmy i wywoływaliśmy również za pomocą funkcji INVOKE, analogiczne wywołanie tym sposobem wyglądałoby następująco:


PUSH p1
PUSH p2
PUSH p3
PUSH p4
CALL NAZWA_PROCEDURY@16

Powrót do strony kursuKolejna lekcja>