Monter | ||
Data pierwszej wersji | 1949 | |
---|---|---|
Rozszerzenie pliku | asm i s | |
Montaż język lub montaż język jest w programowaniu komputerowym , do najniższego poziomu języka , który reprezentuje język maszynowy w postaci czytelnej dla człowieka. Kombinacje bitów języka maszynowego są reprezentowane przez tak zwane symbole „ mnemoniczne ” , to znaczy łatwe do zapamiętania. Program asemblerowy konwertuje te mnemoniki na język maszynowy, a także wartości (zapisywane dziesiętnie) na binarne, a etykiety lokalizacji na adresy, w celu utworzenia, na przykład, pliku obiektowego lub pliku wykonywalnego .
W obecnej praktyce ten sam termin asembler jest używany zarówno do określenia języka asemblera, jak i programu asemblera, który go tłumaczy. Mówimy więc o „programowaniu w asemblerze”.
Tłumaczenie raz na zawsze przez wielu interpreterów każdej nazwy zmiennej napotkanej w (zaawansowanej) instrukcji przez skojarzoną pozycję w pamięci i każdej stałej (zapisanej przez użytkownika w postaci dziesiętnej) na binarne jest typowe dla operacji d. '', Chociaż asembler nazw nie jest powszechnie używany w tym konkretnym przypadku.
Programy EDSAC (1949), pierwszego komputera z nagranymi programami , zostały napisane przy użyciu alfabetycznej mnemoniki składającej się z jednej litery dla każdej instrukcji. Tłumaczenie zostało następnie wykonane ręcznie przez programistów, co było długą, żmudną i podatną na błędy operacją.
Pierwszy program asemblera został napisany przez Nathaniela Rochestera dla IBM 701 (pierwszego komputera wydanego przez IBM ) w 1954 roku.
Języki asemblera wyeliminowały wiele błędów popełnianych przez programistów pierwszej generacji komputerów, rezygnując z konieczności zapamiętywania numerycznych kodów instrukcji i wykonywania obliczeń adresowych. Programowanie w asemblerze było następnie używane do pisania wszelkiego rodzaju programów.
XX wieku wykorzystanie asemblera do pisania aplikacji zostało w dużej mierze wyparte przez użycie języków programowania wysokiego poziomu: Fortran , COBOL , PL / I itp. : moc maszyn na to pozwalała i poświęcenie kilku minut komputera na kompilację, aby zaoszczędzić kilka godzin czasu programisty, było operacją dochodową, nawet jeśli kompilatory czasu dostarczały mniej wydajnego kodu (większego i często wolniejszego). Ponadto te języki wysokiego poziomu umożliwiły przezwyciężenie zależności od pojedynczej architektury sprzętowej.
Te systemy operacyjne były pisane w asemblerze do momentu wprowadzenia MCP do Burroughs w 1961 roku, który został napisany w ESPOL, dialekt Algol .
Asembler powrócił nieco na korzyść pierwszych mikrokomputerów, gdzie charakterystyka techniczna (zmniejszony rozmiar pamięci, mała moc obliczeniowa, specyficzna architektura pamięci itp.) Narzuciła silne ograniczenia, do których dodaje się istotny czynnik psychologiczny, postawa „hobbystyczna” pierwszych użytkowników mikrokomputerów, którzy nie byli zadowoleni z powolności programów napisanych w zinterpretowanym języku BASIC dostarczanym zwykle z komputerem.
Duże programy zostały napisane w całości w montażu dla mikrokomputerów, takich jak DOS operacyjnego systemu z IBM PC (około 4000 linii kodu) i Lotus 1-2-3 arkusza kalkulacyjnego (jego rywal Multiplan, który istniał już pod CP / M , był napisane w C ). W latach 90. miało to również miejsce w przypadku większości gier na konsole wideo (na przykład na Mega Drive lub Super Nintendo ).
Język maszynowy jest jedynym językiem, który może wykonać procesor . Jednak każda rodzina procesorów używa innego zestawu instrukcji .
Na przykład procesor z rodziny x86 rozpoznaje instrukcję typu:
10110000 01100001W języku asemblera ta instrukcja jest reprezentowana przez odpowiednik łatwiejszy do zrozumienia dla programisty:
movb $0x61,%al(10110000 = movb% al
01100001 = 0x61 $)
To znaczy: „zapisz liczbę 97 (wartość podana szesnastkowo : 61 16 = 97 10 ) w rejestrze AL”.
Zatem język asemblera, dokładna reprezentacja języka maszynowego, jest specyficzny dla każdej architektury procesora . Ponadto dla jednego zestawu instrukcji może istnieć wiele grup mnemotechniki lub składni języka asemblera, tworząc w ten sposób makropolecenia .
Transformacja kodu asemblera na język maszynowy jest wykonywana przez program zwany programem asemblerowym . Operacja odwrotna , a mianowicie znalezienie odpowiednika asemblera do fragmentu kodu maszynowego, ma swoją nazwę: jest to demontaż .
Wbrew temu, co mogłoby się wydawać, nie zawsze istnieje zgodność jeden do jednego ( bijekcja ) między kodem asemblera a językiem maszynowym. W przypadku niektórych procesorów demontaż może zatem skutkować powstaniem kodu, który jest bardzo trudny do zrozumienia dla człowieka, a jednocześnie pozostaje doskonale skompilowany przez komputer. Niemożność demontażu może mieć różne przyczyny: użycie samomodyfikującego się kodu, instrukcje o zmiennej wielkości, niemożność rozróżnienia kodu od danych itp. ( nieprzenikniony kod )
Co więcej, wiele elementów występujących w asemblerze ginie podczas tłumaczenia na język maszynowy. Tworząc kod w asemblerze, programista może nadawać nazwy pozycjom w pamięci, komentować swój kod , używać makropoleceń lub używać kodu wygenerowanego w warunkach w momencie asemblacji. Wszystkie te elementy są zredukowane podczas montażu do tego, co jest absolutnie niezbędne dla maszyny i dlatego nie pojawiają się wyraźnie podczas demontażu: na przykład pozycja w pamięci jest oznaczona tylko adresem numerycznym lub przesunięciem .
Niektóre podstawowe operacje są dostępne w większości zestawów instrukcji.
Są też szczegółowe instrukcje z jedną lub kilkoma instrukcjami dotyczącymi operacji, które powinny zająć dużo czasu. Przykłady:
Oprócz kodowania instrukcji maszynowych, języki asemblera mają dodatkowe dyrektywy dotyczące łączenia bloków danych i przypisywania adresów do instrukcji przez definiowanie znaczników lub etykiet.
Są w stanie zdefiniować wyrażenia symboliczne, które są oceniane w każdym zestawie, dzięki czemu kod jest jeszcze łatwiejszy do odczytania i zrozumienia.
Zwykle mają wbudowany język makr, który ułatwia generowanie złożonych kodów lub bloków danych.
Oto kilka prostych przykładów:
(Komentarze są po średnikach)
str: .ascii "Bonjour\n" .global _start _start: movl $4, %eax movl $1, %ebx movl $str, %ecx movl $8, %edx int $0x80 movl $1, %eax movl $0, %ebx int $0x80 ;Compilation: ;as code.s -o code.o ;ld code.o -o code ;Execution: ;./codeOto te same przykłady, z kilkoma różnicami:
(Komentarze są po średnikach)
section .data ; Variables initialisées Buffer: db 'Bonsoir', 10 ; En ascii, 10 = '\n'. La virgule sert à concaténer les chaines BufferSize: equ $-Buffer ; Taille de la chaine section .text ; Le code source est écrit dans cette section global _start ; Définition de l'entrée du programme _start: ; Entrée du programme mov eax, 4 ; Appel de sys_write mov ebx, 1 ; Sortie standard STDOUT mov ecx, Buffer ; Chaine à afficher mov edx, BufferSize ; Taille de la chaine int 80h ; Interruption du kernel mov eax, 1 ; Appel de sys_exit mov ebx, 0 ; Code de retour int 80h ; Interruption du kernelTrwają debaty na temat użyteczności języka asemblera. W wielu przypadkach kompilatory - optymalizatory mogą przekształcić język wysokiego poziomu w kod, który działa równie wydajnie, jak kod asemblera napisany ręcznie przez bardzo dobrego programistę, a jednocześnie jest znacznie łatwiejszy, szybszy (i dlatego mniej wydajny). .
Wydajność była problemem już w latach pięćdziesiątych XX wieku, ślad tego znajdujemy w podręczniku języka Fortran (wydanym w 1956 r.) Dla komputera IBM 704 : Programy obiektowe produkowane przez Fortran będą prawie tak samo wydajne, jak te napisane przez dobrych programistów .
Kompilatory, które w międzyczasie poczyniły ogromne postępy, jest zatem oczywiste, że zdecydowana większość programów jest obecnie napisana w językach wysokiego poziomu ze względów ekonomicznych, a dodatkowy koszt programowania przewyższa zysk wynikający z oczekiwanej poprawy wydajności.
Jednak nadal istnieją bardzo specyficzne przypadki, w których użycie asemblera jest nadal uzasadnione:
Niektóre kompilatory przekształcają, gdy ich najwyższa opcja optymalizacji nie jest włączona , programy napisane w języku wysokiego poziomu w kod asemblera, przy czym każda instrukcja wysokiego poziomu skutkuje serią ściśle równoważnych instrukcji asemblera i używa tych samych symboli; pozwala to zobaczyć kod do celów debugowania i profilowania , co czasami pozwala zaoszczędzić dużo więcej czasu, zmieniając algorytm . W żadnym wypadku nie można zachować tych technik do ostatecznej optymalizacji.
Programowanie systemów wbudowanych , często opartych na mikrokontrolerach , jest tradycyjną „niszą” programowania w asemblerze. W rzeczywistości systemy te mają często bardzo ograniczone zasoby (na przykład mikrokontroler PIC 16F84 jest ograniczony do 1024 14-bitowych instrukcji, a jego pamięć RAM zawiera 136 bajtów) i dlatego wymagają bardzo zoptymalizowanego programowania niskopoziomowego, aby wykorzystać jego możliwości. Jednak ewolucja sprzętu sprawia, że komponenty tych systemów stają się coraz bardziej wydajne przy stałych kosztach i stałym zużyciu energii, inwestycja w programowanie „dowolnego asemblera” jest znacznie droższa w godzinach pracy, a następnie staje się inwestycją. , nonsens pod względem wysiłku. Zazwyczaj programowanie w asemblerze jest znacznie dłuższe, delikatniejsze (ponieważ programista musi brać pod uwagę wszystkie mikro-szczegóły programowania, od których powstrzymuje się w języku wysokiego poziomu), a zatem znacznie droższe niż programowanie w języku wysokiego poziomu. Dlatego powinno być zarezerwowane tylko dla sytuacji, w których nie można postąpić inaczej.
Wiele asemblerów obsługuje język makr . Jest to kwestia zgrupowania kilku instrukcji w celu uzyskania bardziej logicznej i mniej żmudnej sekwencji.
Na przykład (w asemblerze Microsoft MASM ):
to makro, które wyświetla znak w systemie MS-DOS . Będzie używany na przykład w następujący sposób:
I wygeneruje:
mov dl,"X" mov ah,2 int 21hPseudoinstrukcja to specjalny typ makropolecenia. Jest on predefiniowany przez edytora oprogramowania asemblera i jego funkcją jest emulowanie brakującej instrukcji procesora lub ułatwienie korzystania z istniejącej instrukcji. Ponieważ pseudo rozkaz ma nazwę bardzo podobną do prawdziwej instrukcji procesora, na pierwszy rzut oka można ją pomylić z jedną z tych ostatnich. Na przykład procesor RISC może nie mieć instrukcji JMP, która umożliwia przejście do określonego punktu w programie i kontynuowanie wykonywania go po kolei. W tym przypadku edytor oprogramowania utworzy dla programisty pseudo-instrukcję „JMP <parametr>”, która zostanie zastąpiona podczas asemblacji instrukcją „mov pc , <parametr>”, gdzie pc będzie wskaźnikiem. być straconym. Innym przykładem „push <parametr>” pseudo instrukcja zostanie zastąpiony przechowywania <parametr> adresem wskazywanego przez sp ze wstępnym Dekrementowanie tych ostatnich sp stanowiącego stos wskaźnik z procesorem.
W mikroprocesorach lub mikrokontrolerach RISC, takich jak z rodziny ARM , nie ma instrukcji asemblera umożliwiającej załadowanie do rejestru dowolnej stałej natychmiastowej, niezależnie od jej wartości. Większość asemblerów posiada pseudo-instrukcję pozwalającą na takie ładowanie w możliwie najbardziej efektywny sposób pod względem czasu wykonywania, oszczędzając to zadanie programiście.
Wsparcie dla programowania strukturalnego : niektóre elementy programowania strukturalnego zostały zintegrowane w celu kodowania przepływu wykonywania przez Dr. HD Mills (Marzec 1970) i zaimplementowany przez Marvina Kesslera, który rozszerzył asembler makr S / 360 o bloki if / else / endif, a nawet bloki sterowania przepływem. Był to sposób na ograniczenie lub wyeliminowanie użycia operacji przeskoku w kodzie asemblera.