2010-08-17 13 views
12

Próbuję uczyć się języka asemblerowego i potrzebuję wyjaśnienia czegoś. Proszę mnie poprawić, jeśli nie mam racji, ponieważ nie wiem zbyt wiele na temat montażu.Alokacja pamięci zespołu

Wszystkie samouczki, które oglądam, mają zmienne programów montażowych przypisanych do adresu pamięci, takiego jak 0x0000, i rozumiem, że należy ręcznie przypisać adresy pamięci w zespole, ale skąd wiadomo, jakiego adresu użyć?

Oczywiście ma sens rozpoczęcie od najniższego możliwego adresu pamięci, ale co, jeśli przypisana zmienna jest większa niż pamięć dostępna pod numerem 0x0000? Czy zmienna, o której mowa, przejdzie na 0x0001 lub 0x0002? Gdyby tak było, nie zepsułoby to innych zmiennych przypisanych przestrzeniami o podobnej numeracji (czy nie powinno się ich przypisywać tak blisko)?

Jeśli mam dwa programy napisane w zespole uruchomionym w tym samym czasie (w nowoczesnym systemie operacyjnym) i użyłem tych samych adresów pamięci w obu programach, czy jeden program będzie w konflikcie z drugim, czy system operacyjny po prostu przypisze dostępny adres pamięci niezależnie od tego, co faktycznie zapisano w programie?

Wszelkie informacje na ten temat są mile widziane.

Odpowiedz

18

Odpowiedź na drugą część pytania (w przypadku większości nowoczesnych systemów operacyjnych) to pamięć wirtualna.

Zaczynasz od warstwy sprzętowej z pamięcią fizyczną. To rzeczy, które możesz naprawdę szturchnąć palcem. Oto, co widzi system operacyjny. System operacyjny pozwala uruchamiać procesy na abstrakcji zwanej pamięcią wirtualną.

Każdy proces otrzymuje własną wirtualną przestrzeń pamięci. Może więc udawać, że jest to jedyny proces działający i ma masę pamięci. Następnie za każdym razem, gdy uzyskujesz dostęp do pamięci, podajesz adres wirtualny, który jest mapowany na adres fizyczny. System operacyjny przechowuje tabelę, której wirtualny adres jest mapowany na rzeczywiste fizyczne adresy w pamięci RAM. Zwykle odbywa się to za pomocą specjalnego sprzętu (MMU, jednostka zarządzania pamięcią) ze względu na wydajność, ale można to zrobić w 100% również w oprogramowaniu.

Kiedy mówisz 0x000 w twoim programie, jest to adres wirtualny. To jest tłumaczone na fizyczny adres przez komputer podczas czytania lub pisania. W innym procesie ten sam wirtualny adres 0x000 odwzorowuje inny fizyczny adres. Ten system pozwala napisać program, nie wiedząc dokładnie, ile pamięci RAM jest dostępne lub jaki adres zostanie załadowany do programu. Zapobiega to także zniszczeniu pamięci programu należącego do innego programu.

Co do pierwszej części, absolutnie. Różne rodzaje danych pobierają różne ilości pamięci. Musisz wiedzieć, ile potrzebujesz miejsca, kiedy układasz struktury danych. Są też kwestie związane z wyrównaniem bajtów, o których należy pamiętać. Wielobajtowe typy danych (np. Liczby zmiennoprzecinkowe) często muszą rozpoczynać się od adresu, który jest podzielny przez 2 lub 4 lub liczbę bajtów potrzebnych do przechowywania float - jest to wymóg procesora lub pamięci RAM.Więc nie możesz po prostu zgnieść wszystkich swoich danych razem, jeden bajt po drugim, musisz ułożyć go w określonej kolejności, np. Dopasowując kawałki układanki, jeśli chcesz zminimalizować nieużywaną pamięć.

+0

Dzięki za szczegółową odpowiedź! W ostatniej części odpowiedzi, w jaki sposób dokładnie obliczyć, ile miejsca potrzeba na każdy bit danych? ręczne obliczanie setek zmiennych dla programu wydaje się niewykonalne. Używając swoich słów, jak to "wyłożyć"? – ubiquibacon

+0

Nigdy nie pracowałem z montażem w dużych projektach, ale heurystyka zalecana w mojej klasie OS polegała na sortowaniu zmiennych według wielkości, a następnie umieszczaniu najmniejszych na najniższych adresach pamięci. Nie zawsze jest to najlepszy układ - możesz być w stanie dopasować małe typy danych pomiędzy dużymi. Powinieneś być w stanie określić na podstawie typu zmiennej, jaka ilość pamięci jest potrzebna - zapoznaj się z dokumentacją dla swojego języka asemblerowego. Pamiętaj, że zmienna zajmuje taką samą ilość pamięci przez cały czas trwania twojego programu. Nie może "rosnąć". Właśnie dlatego powstają przepełnienia. –

+1

Świetna odpowiedź, tylko jedna korekta. Prawidłowe wyrównywanie danych nie polega na oszczędzaniu miejsca, tak jak i całej przyległej pamięci. Ma to związek ze sposobem mapowania magistrali danych do pamięci. Pierwsze 8 bitów rozpoczyna się od adresu 0, kolejne 8 bitów łączy się z adresem 1. Oznacza to, że 16-bitowa liczba całkowita zaczynająca się od adresu 0 może być odczytywana w jednym czytaniu, ponieważ wykorzystuje obie strony magistrali danych. Jeśli jednak 16-bitowa liczba całkowita zaczyna się od 1, teraz musi wykonać dwa odczytu, aby uzyskać całą liczbę całkowitą. W przypadku 32-bitowych liczb całkowitych powinny one zaczynać się od adresów podzielnych przez 4 z tego samego powodu. – Despertar

1

Zależy od celu i rodzaju pamięci (RAM, ROM itp.), O której mówisz. Jeśli mówisz o pamięci RAM jako niewielkim wbudowanym projekcie, możesz mieć po prostu kilka plików do śledzenia, a karty danych dla mikro będą wskazywać różne adresowanie regionu pamięci. W przypadku, gdy istnieje kilka "modułów", należy użyć łącznika, aby połączyć pliki obiektów do pliku wykonywalnego. Łącznik może ponownie przypisać adres pamięci, aby się nie nakładał, lub możesz mieć plik centralny, w którym zdefiniowane są wszystkie lokalizacje pamięci, a pozostałe moduły używają tego jako zasobu. Przepraszam. To duże pytanie z wieloma odpowiedziami.

5

To nie jest dokładnie odpowiedź, ale w tej książce jest odpowiedź. Mogę to tylko polecić. Nauczy Cię podstaw, tak jak nazwa mówi, że to Programowanie od podstaw.

ProgrammingGroundUp

Powiązane problemy