Staram się naprawdę zrozumieć, jak dokładnie język wysokiego poziomu jest konwertowany na kod maszynowy, a następnie wykonywany przez procesor.
Rozumiem, że kod jest wkompilowany w kod maszynowy, który jest kodem niskiego poziomu, którego może używać procesor. Jeśli mam oświadczenie o przypisaniu, powiedz:
x = x + 5;
y = x - 3;
Czy procesor wykonuje każdą linię pojedynczo? Więc najpierw wykona x = x + 5; instrukcja, a następnie następną instrukcją, którą wykona CPU, jest y = x- 3; Naprawdę staram się zrozumieć proces wykonywania i sposób, w jaki kod, który piszę, jest faktycznie wykonywany przez procesor.
computer-science
cpu
Frankie
źródło
źródło
Odpowiedzi:
Wiersze kodu nie mają nic wspólnego z tym, jak procesor go wykonuje. Poleciłbym przeczytać o asemblerze, ponieważ to nauczy cię wiele o tym, jak sprzęt faktycznie robi rzeczy. Możesz również uzyskać dane wyjściowe asemblera z wielu kompilatorów.
Ten kod może się skompilować w coś takiego (w gotowym języku asemblera):
Jeśli jednak kompilator wie, że zmienna nie jest ponownie używana, operacja przechowywania może nie zostać wysłana.
Aby debugger wiedział, jaki kod maszynowy odpowiada linii źródła programu, kompilator dodaje adnotacje, aby pokazać, który wiersz odpowiada miejscu w kodzie maszynowym.
źródło
ADD Rx, Rx, $5
iSUB Ry, Rx, $3
(zakładając, że zmienne xiy zostały zamapowane w rejestrach). Opisujesz podejście RISC do ładowania / przechowywania.To zależy.
Tak, na początku naprawdę prostych maszyn, tak, kod wykonywany był po jednym wierszu na raz. Gdy maszyny stały się większe, szybsze i bardziej złożone, zaczęłaś widzieć zdolność wykonywania wielu instrukcji jednocześnie, a pamięć odczytuje i zapisuje znacznie dłużej niż operacje na rejestrach.
Optymalizacja kompilatorów musiała wziąć to pod uwagę, a podane linie można było wykonywać mniej więcej równolegle, przy czym jedna część procesora działała na obliczeniach y, podczas gdy inna część przechowywała wcześniej obliczoną nową wartość x (a obliczenie y wykorzystywało tę nową wartość z rejestru).
Control Data 6600 był pierwszą znaną mi maszyną, która zrobiła takie rzeczy. Dodanie liczby całkowitej zajęło 300 nsek. Odniesienie do pamięci (odczyt lub zapis) zajęło 1000 nsek. Mnożenie i dzielenie trwało dużo dłużej. Można wykonać około dziesięciu instrukcji równolegle, w zależności od wymaganych jednostek funkcjonalnych. Kompilatory CDC 6600 FORTRAN były BARDZO dobre w planowaniu tego wszystkiego.
źródło
x
? W ten sposób już wykonał kod i zapisał go w pamięci podręcznej.Nie, nie ma odwzorowania jeden na jeden między wierszami kodu / instrukcjami w językach wyższego i niższego poziomu. W rzeczywistości obie powyższe linie są tłumaczone na wiele instrukcji kodu maszynowego , takich jak
Rzeczywiste szczegóły tych instrukcji różnią się w zależności od platformy.
To jest podstawowy pogląd na rzeczy. Jednak w celu dalszego skomplikowania problemów nowoczesne procesory stosują między innymi takie techniki, jak potoki wykonywania , wykonywanie poza kolejnością i wiele rdzeni . Powoduje to, że CPU wykonuje wiele czynności jednocześnie, np. Rurociągi przetwarzają różne fazy kolejnych instrukcji równolegle w tej samej jednostce przetwarzania, podczas gdy wiele rdzeni może przetwarzać równolegle niezależne instrukcje.
źródło
Powinieneś przyjrzeć się szczegółom w książce, aby znaleźć więcej szczegółów na temat tego, jak to działa, być może także klasę kompilatora.
Zasadniczo twoje pytanie koncentruje się na 2 różnych aspektach.
1) W jaki sposób kod jest tłumaczony na kod maszynowy?
2) Kiedy / jak oblicza się kod przy użyciu równoległości?
Odpowiedź na 1) zależy od języka, którego używasz (chociaż w twoim przykładzie jest trywialny, więc wynik będzie taki sam). Sposób, w jaki kompilator dokonuje tłumaczenia na kod maszynowy, jest jedną z sił tego języka. Poza tym w twoim przykładzie należy wziąć pod uwagę kilka kwestii, kod powinien załadować dane do pamięci, przechowywać itp.
Wreszcie, równoległość jest funkcją, którą można wymusić z punktu widzenia programowania, ale w skrócie, niektóre procesory mogą próbować myśleć, że pewna część kodu może być uruchomiona w tym samym czasie, ponieważ są one niezależne. W twoim przypadku najwyraźniej tak nie jest, ponieważ musisz wykonywać instrukcje sekwencyjnie, więc nie, nie będzie działać w tym samym czasie.
źródło