Czy jest jakaś różnica między kompilatorem a asemblerem?


15

Czy jest jakaś różnica między nimi? Zgodnie z książką Ullmana , kompilatory konwertują jeden język na inny (zwykle na niskim poziomie), podobnie jak asembler. Czym się różnią?


1
Asembler to kompilator, który wykonuje określony zestaw zadań. Terminy te nieco się rozeszły w praktyce, ale obowiązuje podstawowa definicja „kompilatora” (tłumaczenie między językami).
Raphael

Wszystkie asemblery są (prostymi) kompilatorami, ponieważ przekształcają jeden język na inny. Nie wszystkie kompilatory są asemblerami.
user253751,

Odpowiedzi:


16

Asembler tłumaczy kod asemblera na kod maszynowy. Tłumaczenie jest mechaniczne i może być wykonane tylko w jeden sposób. Natomiast kompilator ma większą swobodę podczas kompilacji odpowiedniego języka programowania - może na przykład optymalizować, a nawet nieoptymalizujące kompilatory wytwarzają inny kod. Kompilatory można również pisać w sposób, który oddziela „front-end” (odpowiadający językowi programowania) i „back-end” (odpowiadający architekturze komputerowej), podczas gdy w asemblerze oba są zawsze takie same.


2
Dlaczego tłumaczenie można wykonać tylko w jeden sposób? Czy to oznacza, że ​​nie można wygenerować źródłowego kodu asm dla danego kodu maszynowego (i architektury docelowej)? To brzmi dla mnie sprzecznie z intuicją. Ponieważ jeśli dana instrukcja kodu maszynowego może być odwzorowana na wiele instrukcji asm, to w jaki sposób maszyna decyduje, którą instrukcję wykonać? Czy coś brakuje?
Utku

3
Obawiam się, że źle zrozumiałeś tutaj znaczenie słowa „jeden sposób”. Oznacza to, że biorąc pod uwagę kod zespół istnieje pojedynczy tłumaczenie T ( ) od A do kodu maszynowego. ZAT.(ZA)ZA
Yuval Filmus

Dzięki, widzę też, że w książce Ullmana kompilator ma interfejs i backend. Jeśli mam rację, backend wykonuje optymalizację w języku pośrednim, generowanie kodu maszynowego i optymalizację kodu maszynowego, a każde z trzech zadań można wykonać na więcej niż jeden sposób. czy część „backend” jest asemblerem? Czy język pośredni jest językiem asemblera? Chyba tak, ale twoja odpowiedź wspomina, że ​​asembler wykonuje swoją pracę tylko w jeden sposób.
Tim


Język pośredni zwykle odnosi się do języka niezależnego od maszyny.
Yuval Filmus,

11

Najważniejsze jest to, że pisanie kompilatora jest bardziej zabawne niż asembler. Języki asemblera są zwykle zaprojektowane tak, aby były prawie trywialne do analizowania i sprawdzania typu i zwykle obejmują wiele generatorów opartych na tabeli („kod operacji dodawania to 01110”, „dla instrukcji ładowania rejestr operandu docelowego jest określony bitami od 17 do 21 „). Zwykle najciekawszą częścią asemblera jest część, która przekształca symboliczne etykiety na liczby.

Jednak większość asemblerów może wykonać niewielką arytmetykę (dodając na przykład symboliczne etykiety z małymi stałymi), a większość asemblerów ma lub jest zintegrowana z narzędziem do przetwarzania makr. (W większości systemów uniksowych funkcja makr jest faktycznie zapewniana przez uruchomienie preprocesora C nad zestawem przed przekazaniem go do właściwego asemblera).

Asembler MIPS musiał pójść o krok dalej i podjął kilka interesujących decyzji dotyczących generowania kodu i dokonał niewielkiej optymalizacji. Język maszynowy MIPS wymaga na przykład różnych sekwencji kodu, aby załadować różne stałe, więc asembler musiał wybrać sekwencję kodu po zbudowaniu stałej . Co więcej, kod maszynowy MIPS miał pojęcie szczelin opóźniających , ale asembler był odpowiedzialny za ich wyodrębnienie i przedstawienie kompilatorowi bardziej „normalnego” języka asemblera abstrakcyjnego. Asembler MIPS musi więc wykonać szereg lokalnych instrukcji.

Rozróżnienie jest dodatkowo rozmyte przez niektóre Norman Ramsey pracy „s, w szczególności jego C-- przenośnego asemblerze. (Odpowiedni artykuł to Ramsey i Peyton Jones, „Pojedynczy język średniozaawansowany, który obsługuje wiele implementacji wyjątków”, Prog. Lang. Impl. I Dsgn. , (PLDI-21): 285–298, 2000 ). I na koniec jest również Wpisane Zgromadzenie Język David Walker i Greg Morrisett z asemblera, które mogą zagwarantować bezpieczeństwo pamięci.


0

Trochę uproszczonej odpowiedzi tutaj, rzeczywistość jest bardziej skomplikowana. Spodziewałbym się, że różnica między asemblerem (A) i kompilatorem (C) będzie między innymi:

  1. Jedna linia kodu źródłowego odnosi się bezpośrednio do jednego kodu operacyjnego procesora (A) lub nie (C)
  2. Wysoce zależny od faktycznego procesora (A) lub niezależnego od maszyny (C)

Zwykle nazywamy język asemblera „niskim poziomem”, a język źródłowy kompilator rozumie „wysoki poziom” (jest to jednak rażące uproszczenie, ale nadal).

W języku asemblera możesz jako przykład wykonać operację dodawania, mówiąc:

  • dodaj a, b (dla jednego konkretnego procesora)
  • dodaj R5, R6 (dla innego procesora)
  • dodaj (A5), D2 (dla innego procesora)

W języku wysokiego poziomu możesz napisać:

  • x = y + z;

Może to skutkować jedną instrukcją lub setkami instrukcji w zależności od szeregu okoliczności. Jednym z nich jest procesor, dla którego kompilator tworzy instrukcje.

Jak widać język źródłowy asemblera jest najczęściej: (A) jeden wiersz kodu źródłowego daje jeden wiersz kodów procesora CPU i bardzo zależy od tego, na który procesor celujesz. Kompilator języka wysokiego poziomu (C) obsługuje wszystkie te szczegóły - jeden wiersz kodu źródłowego może być zerowy, jeden lub wiele kodów operacyjnych procesora, a kompilator obsługuje szczegóły tego, co może zrobić procesor.

Obecnie kompilator często składa się z kilku różnych etapów. Można je nazwać frontend / backend lub być nazywane innymi rzeczami. Zwykle postrzegam je jako cztery etapy:

  1. Pierwszy etap odczytuje rzeczywisty kod źródłowy i tworzy wewnętrzną reprezentację. Ten etap zna rzeczywisty język źródłowy.
  2. Drugi etap analizuje wewnętrzną reprezentację i dokonuje szeregu optymalizacji. W dzisiejszych czasach kompilator zwykle szukałby przyspieszenia programu i nie dbania o to, czy będzie on większy. Optymalizacja odbywa się na wewnętrznej reprezentacji. Co ciekawe, części tego mogą być ogólne dla kilku różnych języków.
  3. Trzeci etap obejmuje wewnętrzną reprezentację i tworzy rzeczywisty kod dla wybranego procesora. Może istnieć kilka różnych wersji tego etapu, przeznaczonych dla różnych procesorów. W efekcie możesz raz napisać kod źródłowy, a następnie skompilować go dla różnych CPUS-ów.
  4. Końcowe przygotowania do „pakowania” programu (ten etap może być linkerem).

Pisanie dobrych kompilatorów to zawód wymagający wysokich umiejętności - tworzenie kompilatora w języku zabawek może być wykonane po południu przez amatora (lub cóż, nieco dłużej).

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.