Kod maszynowy - Machine code

Maszyna Monitor języka w W65C816S pojedynczy komputer pokładowy , wyświetlanie kodu demontaż , a także rejestr procesora i pamięci wysypisk.

W programowaniu komputerowym , kod maszynowy jest dowolny język niskiego poziomu , składający się z językowymi maszyna instrukcji , który jest używany do sterowania komputerem za jednostkę centralną (CPU). Każda instrukcja powoduje, że CPU wykonuje bardzo specyficzne zadanie, takie jak ładowanie, zapisywanie, skok lub operacja jednostki arytmetyczno-logicznej (ALU) na jednej lub większej liczbie jednostek danych w rejestrach lub pamięci CPU .

Kod maszynowy jest językiem ściśle numerycznym, który został zaprojektowany tak, aby działał tak szybko, jak to możliwe i może być uważany za najniższą reprezentację skompilowanego lub złożonego programu komputerowego lub jako prymitywny i zależny od sprzętu język programowania. Chociaż możliwe jest pisanie programów bezpośrednio w kodzie maszynowym, zarządzanie poszczególnymi bitami oraz ręczne obliczanie adresów i stałych numerycznych jest żmudne i podatne na błędy. Z tego powodu, programy są bardzo rzadko pisane bezpośrednio w kodzie maszynowym we współczesnych kontekstach, ale mogą być zrobione dla debugowania niskiego poziomu , łatania programów (zwłaszcza gdy źródło asemblera nie jest dostępne) i dezasemblacji języka asemblera .

Większość dzisiejszych praktycznych programów jest napisana w językach wyższego poziomu lub języku asemblera. Kod źródłowy jest następnie tłumaczony na wykonywalny kod maszynowy przez narzędzia takie jak kompilatory , assemblery i linkery , z ważnym wyjątkiem programów interpretowanych , które nie są tłumaczone na kod maszynowy. Jednak sam interpreter , który może być postrzegany jako executor lub procesor wykonujący instrukcje kodu źródłowego, zazwyczaj składa się z bezpośrednio wykonywalnego kodu maszynowego (generowanego z asemblera lub kodu źródłowego języka wysokiego poziomu).

Kod maszynowy jest z definicji najniższym poziomem szczegółowości programowania widocznym dla programisty, ale wewnętrznie wiele procesorów używa mikrokodu lub optymalizuje i przekształca instrukcje kodu maszynowego w sekwencje mikrooperacji . Nie jest to powszechnie uważane za kod maszynowy.

Zestaw instrukcji

Każdy procesor lub rodzina procesorów ma swój własny zestaw instrukcji . Instrukcje to wzory bitów , cyfr lub znaków, które odpowiadają poleceniom maszyny. Tak więc zestaw instrukcji jest specyficzny dla klasy procesorów używających (w większości) tej samej architektury. Kolejne lub pochodne projekty procesorów często zawierają instrukcje poprzednika i mogą dodawać nowe instrukcje dodatkowe. Od czasu do czasu następca projektu przerwie lub zmieni znaczenie jakiegoś kodu instrukcji (zwykle dlatego, że jest on potrzebny do nowych celów), wpływając do pewnego stopnia na kompatybilność kodu; nawet zgodne procesory mogą wykazywać nieco inne zachowanie w przypadku niektórych instrukcji, ale rzadko stanowi to problem. Systemy mogą również różnić się innymi szczegółami, takimi jak rozmieszczenie pamięci, systemy operacyjne lub urządzenia peryferyjne . Ponieważ program zwykle opiera się na takich czynnikach, różne systemy zazwyczaj nie będą uruchamiać tego samego kodu maszynowego, nawet jeśli używany jest ten sam typ procesora.

Zestaw instrukcji procesora może mieć wszystkie instrukcje o tej samej długości lub może mieć instrukcje o zmiennej długości. Sposób organizacji wzorców różni się w zależności od konkretnej architektury i rodzaju instrukcji. Większość instrukcji ma jedno lub więcej pól kodu operacji, które określają podstawowy typ instrukcji (taki jak arytmetyczny, logiczny, skok itp.), operację (takie jak dodaj lub porównaj) i inne pola, które mogą podać typ operandu (-ów ), tryb (y) adresowania, offset(y) adresowania lub indeks, lub samą wartość argumentu (takie stałe argumenty zawarte w instrukcji są nazywane natychmiastowymi ).

Nie wszystkie maszyny lub poszczególne instrukcje mają wyraźne argumenty. Maszyna akumulator ma łączną lewy operand i wynik w akumulatorze niejawny dla większości instrukcji arytmetycznych. Inne architektury (takie jak 8086 i rodzina x86) mają wersje akumulatorowe typowych instrukcji, przy czym akumulator jest traktowany jako jeden z rejestrów ogólnych przez dłuższe instrukcje. Maszyna stosowa ma większość lub całość swoich argumentów na niejawny stosie. Instrukcje specjalnego przeznaczenia również często nie mają jawnych operandów (na przykład CPUID w architekturze x86 zapisuje wartości do czterech niejawnych rejestrów docelowych). To rozróżnienie między jawnymi i niejawnymi operandami jest ważne w generatorach kodu, zwłaszcza w alokacji rejestru i częściach śledzenia zakresu na żywo. Dobry optymalizator kodu może śledzić zarówno niejawne, jak i jawne operandy, które mogą pozwolić na częstsze propagację stałej , stałe składanie rejestrów (rejestr przypisany wynik wyrażenia stałego uwolniony przez zastąpienie go tą stałą) i inne ulepszenia kodu.

Programy

Program komputerowy to lista instrukcji, które mogą być wykonane przez jednostkę centralną (CPU). Wykonywanie programu odbywa się w celu rozwiązania problemu przez procesor, który go wykonuje, a tym samym osiągnięcia wyniku. Podczas gdy proste procesory są w stanie wykonywać instrukcje jedna po drugiej, procesory superskalarne są w stanie wykonywać wiele instrukcji jednocześnie.

Na przebieg programu mogą mieć wpływ specjalne instrukcje „skoku”, które przenoszą wykonanie na adres (a tym samym instrukcję) inny niż następny numerycznie sekwencyjny adres. To, czy te skoki warunkowe wystąpią, zależy od warunku, takiego jak wartość większa, mniejsza lub równa innej wartości.

Języki asemblera

O wiele bardziej przyjazna dla człowieka wersja języka maszynowego, zwana językiem asemblerowym , używa kodów mnemonicznych do odwoływania się do instrukcji kodu maszynowego, zamiast bezpośrednio używać wartości numerycznych instrukcji i używa nazw symbolicznych do odwoływania się do miejsc przechowywania, a czasem rejestrów . Na przykład, na procesorze Zilog Z80 , kod maszynowy 00000101, który powoduje, że procesor zmniejsza B rejestr procesora , będzie reprezentowany w języku asemblera jako DEC B.

Przykład

Architektura MIPS stanowi przykład specyficzne dla kodu maszynowego, którego instrukcje są zawsze 32 bity długości. Ogólny typ instrukcji jest określony przez pole op (operacja), najwyższe 6 bitów. Instrukcje typu J (skok) i typu I (natychmiastowe) są w pełni określone przez op . Typ R (rejestr) instrukcje zawierają dodatkowe pole FUNCT do określenia dokładnej operacji. Pola używane w tych typach to:

   6      5     5     5     5      6 bits
[  op  |  rs |  rt |  rd |shamt| funct]  R-type
[  op  |  rs |  rt | address/immediate]  I-type
[  op  |        target address        ]  J-type

rs , rt , i rd wskazują operandy rejestru; shamt daje kwotę zmiany; a adres lub pola bezpośrednie zawierają operand bezpośrednio.

Np. dodanie rejestrów 1 i 2 oraz umieszczenie wyniku w rejestrze 6 jest zakodowane:

[  op  |  rs |  rt |  rd |shamt| funct]
    0     1     2     6     0     32     decimal
 000000 00001 00010 00110 00000 100000   binary

Załaduj do rejestru 8 wartość pobraną z komórki pamięci 68 komórek po lokalizacji wymienionej w rejestrze 3:

[  op  |  rs |  rt | address/immediate]
   35     3     8           68           decimal
 100011 00011 01000 00000 00001 000100   binary

Skok na adres 1024:

[  op  |        target address        ]
    2                 1024               decimal
 000010 00000 00000 00000 10000 000000   binary

Związek z mikrokodem

W niektórych architekturach komputerowych kod maszynowy jest implementowany przez jeszcze bardziej podstawową warstwę zwaną mikrokodem , zapewniającą wspólny interfejs języka maszynowego w całej linii lub rodzinie różnych modeli komputerów z bardzo różnymi bazowymi przepływami danych . Ma to na celu ułatwienie przenoszenia programów w języku maszynowym między różnymi modelami. Przykładem takiego zastosowania jest rodzina komputerów IBM System/360 i ich następcy. Dzięki szerokości ścieżek przepływu danych od 8 do 64 bitów i więcej, prezentują jednak wspólną architekturę na poziomie języka maszynowego w całej linii.

Wykorzystanie mikrokodu do implementacji emulatora umożliwia komputerowi przedstawienie architektury zupełnie innego komputera. Linia System/360 wykorzystała to, aby umożliwić przenoszenie programów z wcześniejszych maszyn IBM do nowej rodziny komputerów, np. emulator IBM 1401/1440/1460 na IBM S/360 model 40.

Związek z kodem bajtowym

Kod maszynowy zasadniczo różni się od kodu bajtowego (znanego również jako kod p), który jest wykonywany przez interpreter lub sam kompilowany do kodu maszynowego w celu szybszego (bezpośredniego) wykonania. Wyjątkiem jest sytuacja, gdy procesor jest zaprojektowany do używania określonego kodu bajtowego bezpośrednio jako kodu maszynowego, tak jak w przypadku procesorów Java .

Kod maszynowy i kod asemblera są czasami nazywane kodem natywnym, gdy odnoszą się do części funkcji językowych lub bibliotek zależnych od platformy.

Przechowywanie w pamięci

Architektura Harvard jest architektura komputerowa z fizycznie oddzielnych ścieżek sygnałowych i przechowywania kodu (instrukcje) i danych . Obecnie większość procesorów implementuje takie oddzielne ścieżki sygnału ze względu na wydajność, ale implementuje zmodyfikowaną architekturę Harvard , dzięki czemu mogą obsługiwać takie zadania, jak ładowanie programu wykonywalnego z pamięci dyskowej jako danych, a następnie jego wykonywanie. Architektura Harvarda kontrastuje z architekturą Von Neumanna , w której dane i kod są przechowywane w tej samej pamięci, która jest odczytywana przez procesor, umożliwiając komputerowi wykonywanie poleceń.

Z punktu widzenia procesu The przestrzeń kod jest częścią jego przestrzeni adresowej , gdzie przechowywany jest kod w realizacji. W systemach wielozadaniowych obejmuje to segment kodu programu i zwykle biblioteki współdzielone . W środowisku wielowątkowym różne wątki jednego procesu współdzielą przestrzeń kodu wraz z przestrzenią danych, co znacznie zmniejsza obciążenie związane z przełączaniem kontekstu w porównaniu z przełączaniem procesów.

Czytelność przez ludzi

Pamela Samuelson napisała, że ​​kod maszynowy jest tak nieczytelny, że Urząd Praw Autorskich Stanów Zjednoczonych nie może określić, czy dany zakodowany program jest oryginalnym dziełem autora; Jednak US Copyright Office nie pozwalają na rejestrację praw autorskich do programów komputerowych oraz program w kodzie maszynowym czasami można dekompilować , aby uczynić jego funkcjonowania bardziej zrozumiałe dla ludzi. Jednak dane wyjściowe dekompilatora lub deasemblera będą pozbawione komentarzy i odniesień symbolicznych, więc chociaż dane wyjściowe mogą być łatwiejsze do odczytania niż kod wynikowy, nadal będą trudniejsze niż oryginalny kod źródłowy. Ten problem nie występuje w przypadku formatów kodu obiektowego , takich jak SQUOZE , gdzie kod źródłowy jest zawarty w pliku.

Profesor nauk kognitywnych Douglas Hofstadter porównał kod maszynowy z kodem genetycznym , mówiąc, że „Patrzenie na program napisany w języku maszynowym jest niejasno porównywalne do patrzenia na cząsteczkę DNA atom po atomie”.

Zobacz też

Uwagi i referencje

Dalsza lektura