Stos wywołań zaczyna się na dole czy na górze?

11

Stos to coś, co układa się oddolnie.

Dlatego stos wywołań dodaje nowe elementy do stosu, gdy wywoływane są funkcje, a elementy są usuwane ze stosu, gdy każda funkcja kończy się, aż stos jest pusty, a następnie program się kończy.

Jeśli powyższe informacje są poprawne, dlaczego ludzie odnoszą się do sterowania przesuwaniem „w górę” stosu wywołań? Z pewnością kontrola przesuwa się w dół stosu wywołań, aż osiągnie dno.

CJ7
źródło
Po wywołaniu funkcji element jest dodawany na górę stosu, a kontrola jest przekazywana do tej funkcji. Stąd kontrola przesuwa się od przedmiotu leżącego na stosie do najwyższego przedmiotu - w górę.
treekoder
1
@greengit: wyrażenie „w górę stosu wywołań” jest używane z wyjątkami, gdzie kontrola faktycznie porusza się w odwrotny sposób.
Michael Borgwardt
@MichaelBorgwardt: Masz rację.
treekoder
1
@MichaelBorgwardt: Widziałem wyrażenie „błędy przesuwają się w górę stosu wywołań”. Z pewnością to jest nieprawidłowe.
CJ7

Odpowiedzi:

9

Istnieją dwa możliwe powody tego użycia:

  • W kontekście wyjątków formant przechodzi do funkcji / metody wywołującej, a ta hierarchia wywołań jest zazwyczaj wizualizowana za pomocą głównej metody na górze, a wywołania metod tworzą hierarchię w dół, ze zmniejszającym się poziomem abstrakcji. W tej hierarchii wyjątek przesuwa się w górę.

  • Rzeczywisty stos programów w normalnej aplikacji x86 jest odwrócony, tzn. Rośnie w dół. Instrukcje kodu maszynowego PUSH / PUSHW / PUSHD zmniejszają wskaźnik stosu. Inne architektury mogą współdzielić ten model.

Michael Borgwardt
źródło
Czy idea odgórna nie jest sprzeczna z codzienną koncepcją „stosu”, który jest stosem przedmiotów zaczynających się od dołu?
CJ7
@CraigJ: podobnie jest z faktem, że bity każdego bajtu zawartości stosu będą fizycznie przechowywane w osobnych układach scalonych. Kogo to obchodzi?
Michael Borgwardt
1

Wszystko zależy od definicji słów; co dokładnie masz na myśli przez słowa „góra” i „dół” w tym kontekście, a także na temat implementacji systemu operacyjnego lub architektury komputera.

Pamiętam, jak dawno temu, kiedy programowałem na Commodore 64. Pamięć między adresami 0800 $ (2048) i 9FFF (40959) była zarezerwowana dla programów BASIC. Kod twojego programu BASIC był przechowywany zaczynając od niższego adresu (0800 $, stamtąd rośnie). Stos do przechowywania zmiennych i adresów zwrotnych podprogramów zaczynał się na górze (9FFF) tego zakresu i rozwijał się w kierunku niższych adresów. W tym kontekście logiczne było widzenie stosu rosnącego w dół, a gdy wracasz z podprogramu, ramka stosu podprogramu została odrzucona poprzez zwiększenie wskaźnika stosu, abyś mógł powiedzieć, że „przesuwasz się w górę stosu”, gdy powrót z podprogramu.

Nie wiem, jak to działa na nowoczesnych wersjach na przykład procesorów Windows lub Intel x86. Być może stos działa odwrotnie, tzn. Rośnie z niższych adresów na wyższe. W takim przypadku prawdopodobnie użyłbyś słów „góra”, „dół” i „góra”, „dół” dokładnie na odwrót.

Jesper
źródło
0

Aby wywołać funkcję taką jak foo (6, x + 1) ...

  1. Oceń rzeczywiste wyrażenia parametrów, takie jak x + 1, w kontekście osoby wywołującej.
  2. Przydziel pamięć dla lokalnych użytkowników foo (), wypychając odpowiedni „lokalny blok” pamięci na „stos wywołań” środowiska wykonawczego przeznaczony do tego celu. Dla parametrów, ale nie zmiennych lokalnych, przechowuj wartości z kroku (1) w odpowiednim gnieździe w bloku lokalnym foo ().
  3. Zapisz bieżący adres wykonania dzwoniącego (jego „adres zwrotny”) i przełącz wykonanie na foo ().
  4. foo () wykonuje się z blokiem lokalnym wygodnie dostępnym na końcu stosu wywołań.
  5. Po zakończeniu foo () kończy działanie, usuwając swoich mieszkańców ze stosu i „wraca” do dzwoniącego, używając wcześniej zapisanego adresu zwrotnego. Teraz miejscowi dzwoniącego są na końcu stosu i może wznowić wykonywanie.

Odniesienie:

http://cslibrary.stanford.edu/102/PointersAndMemory.pdf (p15)

CodeART
źródło
Pamiętaj, że jest to wysoce specyficzne dla konwencji wywoływania. Istnieją konwencje wywoływania, które pozwalają na wyczyszczenie dzwoniącego, większość używa przynajmniej niektórych rejestrów itp.
0

Jeśli konceptualizujesz stos jako rzecz oddolną, jak cylinder z piłkami tenisowymi w normalnej rzeczywistości grawitacyjnej, wówczas sterowanie przesuwa się w górę stosu, gdy wywoływane są funkcje. Po zakończeniu funkcji kontrolka przesuwa się w dół stosu.

Jeśli konceptualizujesz stos jako rzecz z góry na dół, jak ten sam cylinder piłek tenisowych, ale z odwróconą grawitacją, wówczas sterowanie przesuwa się w górę stosu, gdy wywoływane są funkcje, i w górę stosu, gdy funkcje są kompletne.

Oba są tylko modelami w twojej głowie i są w zasadzie całkowicie arbitralne. Jeśli chcesz, możesz to pojąć jako side-side, ale możesz mieć problemy z komunikacją z ludźmi. Osobiście uważam, że jeśli A wywołuje B, a B wywołuje C, to C jest dolną częścią stosu (odwrócona rzeczywistość grawitacyjna), a jeśli wyjątek występuje w C, chcesz przenieść ten wyjątek „do” na A. Myślę, że może to być bardziej powszechne użycie języka, ponieważ wydaje się, że C jest głęboko, a A jest górą. Pierwsza funkcja jest dla mnie bardziej intuicyjna, a funkcje pogłębiają się przy każdym połączeniu.

Ken Falk
źródło