Programowanie niskopoziomowe / Moduł 4: Programowanie hybrydowe

Z Studia Informatyczne
< Programowanie niskopoziomowe
Wersja z dnia 22:28, 15 paź 2006 autorstwa Akokno (dyskusja | edycje)
(różn.) ← poprzednia wersja | przejdź do aktualnej wersji (różn.) | następna wersja → (różn.)
Przejdź do nawigacjiPrzejdź do wyszukiwania

PNP M4 S01.png

...


PNP M4 S02.png

...


PNP M4 S03.png

...


PNP M4 S04.png

Rejestr 1 jest używany prze asembler MIPS do rozwijania pseudoinstrukcji asemblera w sekwencje 2..3 instrukcji procesora. Rejestr ten zawiera tymczasową wartość, przekazywaną pomiędzy instrukcjami składającymi się na jedną pseudoinstrukcję.

Rejestry k0 i k1 są zarezerwowane do użytku systemu operacyjnego. Z punktu widzenia aplikacji są one ulotne, gdyż wykonanie programu może zostać w każdej chwili przerwane, a w tym czasie system operacyjny może zmienić zawartość tych rejestrów.

Rejestr 28 ułatwia dostęp do danych statycznych.

Rejestr 30 może być użyty jako wskaźnik ramki, zwykle jednak kompilatory dlła MIPS adresują obiekty ramki sou względem wskaźnika stosu, a rejestr 30 służy jako dziewiąty rejestr zachowywany.


PNP M4 S05.png

Konwencja wołania – to zestaw reguł rządzących zachowaniem programów, w tym użyciem przez nie rejestrów i innych zasobów procesora, użyciem stosu systemowego, sposobem przekazywania argumentów do procedur, wywoływania procedur, alokacji zmiennych lokalnych, przekazywania wartości i powrotów z procedur.

Konwencja wołania może być zdefiniowana na różnych poziomach – zależy to od stopnia kontroli podmiotu definiującego konwencję wołania nad obszarem zastosowań tej konwencji.

W komputerach zbudowanych na bazie procesorów MIPS obowiązuje jedna konwencja wołania, zdefiniowana przez projektantów procesora i opisana w dokumentacji procesora. Jest ona stosowana w e wszystkich środowiskach – wszystkich systemach operacyjnych, językach programowania i kompilatorach.

W implementacjach systemów rodziny Unix dla procesorów innych niż MIPS przyjęto, że system operacyjny narzuca konwencję wołania, z której korzysta całe oprogramowania działające w systemie operacyjnym. Konwencja jest wspólna dla wszystkich systemów rodziny Unix/Linux, co daje w efekcie pełną przenośność oprogramowania pomiędzy tymi systemami operacyjnymi. Konwencje te są opisane w dokumentach Unix System V Applicatiion Binary Interface dla poszczególnych rodzin procesorów.

Jeśli konwencja wołania nie została zdefiniowana na poziomie systemu operacyjnego, definiuje ją twórca kompilatora. Jest to sytuacja niekorzystna, gdyż każdy dostawca kompilatora może zdefiniować konwencję wołania odmiennie, co powoduje niemożność łączenia modułów pisanych w tym samym języku programowania i kompilowanych przez różne kompilatory. Sytuacja taka miała miejsce w systemie operacyjnym DOS i częściowo we wczesnych systemach rodziny Windows.

Należy zauważyć, że istnieją środowiska, w których różne języki programowania używają różnych konwencji wołania, chociaż sytuacje takie należą już raczej do przeszłości.


PNP M4 S06.png

Sama architektura procesora (np. x86) lub konwencja wołania (np. MIPS) określają, które z rejestrów procesora pełnią rolę wskaźnika stosu w pamięci i wskaźnika ramki. W niektórych konwencjach wołania można nie używać wskaźnika ramki.

Pozostałe funkcje rejestrów w ramach konwencji wołania są przypisane wyłącznie przez samą konwencję.

Rejestry argumentów służą do przekazywania argumentów wywołania. Konwencja wołanie określa dokładnie ile i jakich argumentów można przekazać w rejestrach.


PNP M4 S07.png

Bardzo istotny jest podział rejestrów na zachowywane i tymczasowe. Większość błędów w programach hybrydowych ma swoje źródło w zignorowaniu przez programistę tego podziału.

Rejestry przechowywane służą do alokacji zmiennych lokalnych. ich zawartość nie może być zmieniona przez żadną procedurę. Oznacza to, że albo procedura nie używa tych rejestrów, albo używa ich dla zmiennych lokalnych, ale w tym przypadku zawartość każdego używanego rejestr musi być w prologu procedury zapamiętana na stosie w pamięci, a w epilogu (przed powrotem) – odtworzona.

Rejestry tymczasowe mogą być dowolnie modyfikowane prze każdą procedurę, co oznacza, że nie ma gwarancji przechowania ich zawartości przez procedurę wywoływaną. Rejestry te są zwykle używane do przechowywania danych tymczasowych w dowolnych procedurach (pomiędzy wywołaniami procedur) albo do przechowywania zmiennych lokalnych w procedurach nie wywołujących innych procedur.

Jeżeli rejestry tymczasowe miałyby być używane do przechowywania zmiennych lokalnych w innych przypadkach, procedura musi zapamiętać ich zawartość na stosie przed każdym wywołaniem innej procedura i odtworzyć ich zawartość po wywołaniu.


PNP M4 S08.png

Czynności wykonywane w prologu procedury są zdefiniowane przez konwencję wołania.

W niektórych środowiskach na początku procedura wywołana wyrównuje stos do określonej granicy (np. 16 bajtów).

Jeżeli procedura korzysta ze wskaźnika ramki, musi ona zachować wskaźnik ramki procedury wywołującej.

Kolejnymi czynnościami są: alokacja miejsca na stosie na wartości argumentów przekazane przez rejestry (o ile konwencja nie określa, że czynność tę wykonuje procedura wołająca) i opcjonalne składowanie rejestrów argumentów na stosie.

Następnie procedura ustanawia własną wartość wskaźnika ramki, po czym następuje alokacja zmiennych lokalnych i składowanie rejestrów.

Konwencja wołania może inaczej ustalić kolejność wymienionych czynności.


PNP M4 S09.png

W epilogu procedury następuje odwrócenie efektów wykonania prologu.

Ostatnią czynnością wykonywaną w epilogu jest powrót według śladu wywołania.


PNP M4 S10.png

Konwencja wołania MIPS została określona przez projektantów procesora. 30 z 32 rejestrów architektury MIPS nie ma funkcji przypisanych przez sam model programowy. Ustalenie ich funkcji jest jednym z elementów konwencji wołania. Konwencja nadaje rejestrom alternatywne nazwy mnemoniczne.


PNP M4 S11.png

Tabela przedstawia funkcje rejestrów MIPS w konwencji wołania.

Rejestr 0 nie jest rejestrem, lecz lokacją zwracającą 0 przy odczycie.

Instrukcje skoku ze śladem pozostawiają ślad w rejestrze numer 31.


PNP M4 S12.png

Rejestr 1 jest używany przez asembler MIPS do rozwijania metainstrukcji asemblera w sekwencje 2..3 instrukcji procesora. Rejestr ten zawiera tymczasową wartość, przekazywaną pomiędzy instrukcjami składającymi się na jedną metainstrukcję.

Rejestry k0 i k1 są zarezerwowane do użytku systemu operacyjnego. Z punktu widzenia aplikacji są one ulotne, gdyż wykonanie programu może zostać w każdej chwili przerwane, a w tym czasie system operacyjny może zmienić zawartość tych rejestrów.

Rejestr 28 ułatwia dostęp do danych statycznych.

Rejestr 30 może być użyty jako wskaźnik ramki, zwykle jednak kompilatory dla MIPS adresują obiekty ramki stosu względem wskaźnika stosu, a rejestr 30 służy jako dziewiąty rejestr zachowywany.


PNP M4 S13.png

...


PNP M4 S14.png

...


PNP M4 S15.png

...


PNP M4 S16.png

...


PNP M4 S17.png

...


PNP M4 S18.png

...


PNP M4 S19.png

...


PNP M4 S20.png

...


PNP M4 S21.png

...


PNP M4 S22.png

...