Jaka jest różnica między kodem obiektowym, kodem maszynowym a kodem asemblera?
Czy możesz podać wizualny przykład ich różnicy?
Jaka jest różnica między kodem obiektowym, kodem maszynowym a kodem asemblera?
Czy możesz podać wizualny przykład ich różnicy?
Odpowiedzi:
Kod maszynowy to kod binarny (1 i 0), który może być wykonany bezpośrednio przez CPU. Jeśli otworzysz plik kodu maszynowego w edytorze tekstowym, zobaczysz śmieci, w tym znaki niedrukowalne (nie, nie te znaki niedrukowalne;)).
Kod obiektowy to część kodu maszynowego, która nie została jeszcze połączona z kompletnym programem. Jest to kod maszynowy dla jednej konkretnej biblioteki lub modułu, który będzie stanowić gotowy produkt. Może także zawierać symbole zastępcze lub przesunięcia, których nie ma w kodzie maszynowym ukończonego programu. Łącznik będzie używać tych zastępczych i offsety, aby połączyć wszystko razem.
Kod asemblera jest zwykłym tekstem i (nieco) czytelnym dla człowieka kodem źródłowym, który w większości ma bezpośredni analog 1: 1 z instrukcjami maszynowymi. Odbywa się to za pomocą mnemoniki rzeczywistych instrukcji, rejestrów lub innych zasobów. Przykłady obejmują JMP
i MULT
do skoku i mnożenia instrukcji procesorów. W przeciwieństwie do kodu maszynowego, procesor nie rozumie kodu asemblera. Konwertujesz kod asemblera na maszynę za pomocą asemblera lub kompilatora , chociaż zwykle myślimy o kompilatorach w powiązaniu z językiem programowania wysokiego poziomu, które są oderwane od instrukcji CPU.
Zbudowanie kompletnego programu wymaga napisania kodu źródłowego programu w języku asemblera lub języku wyższego poziomu, takim jak C ++. Kod źródłowy jest składany (dla kodu asemblera) lub kompilowany (dla języków wyższego poziomu) z kodem obiektowym, a poszczególne moduły są ze sobą łączone, aby stać się kodem maszynowym dla końcowego programu. W przypadku bardzo prostych programów krok łączenia może nie być potrzebny. W innych przypadkach, takich jak IDE (zintegrowane środowisko programistyczne), można wywołać konsolidator i kompilator razem. W innych przypadkach można użyć skomplikowanego skryptu make lub pliku rozwiązania , aby poinformować środowisko, jak zbudować końcową aplikację.
Istnieją również języki interpretowane, które zachowują się inaczej. Języki interpretowane opierają się na kodzie maszynowym specjalnego programu tłumaczącego. Na poziomie podstawowym interpreter analizuje kod źródłowy i natychmiast konwertuje polecenia na nowy kod maszynowy i wykonuje je. Współcześni tłumacze, zwani czasem także środowiskiem wykonawczym lub maszyną wirtualną , są znacznie bardziej skomplikowane: ocenianie całych sekcji kodu źródłowego na raz, buforowanie i optymalizowanie w miarę możliwości oraz obsługa złożonych zadań zarządzania pamięcią. Zinterpretowany język można również wstępnie skompilować do pośredniego języka lub kodu bajtowego niższego poziomu, podobnie jak kod asemblera.
Pozostałe odpowiedzi dobrze opisały różnicę, ale poprosiłeś także o wizualizację. Oto schemat pokazujący, jak przechodzą od kodu C do pliku wykonywalnego.
Kod zestawu to czytelna dla człowieka reprezentacja kodu maszynowego:
mov eax, 77
jmp anywhere
Kod maszynowy to czysty kod szesnastkowy:
5F 3A E3 F1
Zakładam, że masz na myśli kod obiektowy jak w pliku obiektowym. Jest to wariant kodu maszynowego, z tą różnicą, że skoki są tak sparametryzowane, że linker może je wypełnić.
Asembler służy do konwersji kodu asemblera na kod maszynowy (kod obiektu). Linker łączy kilka plików obiektów (i bibliotek) w celu wygenerowania pliku wykonywalnego.
Kiedyś napisałem program asemblerowy w postaci czystego heksa (brak dostępnego asemblera) na szczęście było to dawno temu na starym dobrym (starożytnym) 6502. Ale cieszę się, że są asemblery dla pentium.
Nie wspomniałem jeszcze o jednym, że istnieje kilka różnych rodzajów kodu asemblera. W najbardziej podstawowej formie wszystkie liczby użyte w instrukcjach muszą być określone jako stałe. Na przykład:
1902 USD: BD 37 14: LDA 1437 USD, X 1905 USD: 85 03: STA 03 USD 1907 USD: 85 09: STA 09 USD 1909 USD: CA: DEX 190 USD: 10: 1902 BPL
Powyższy fragment kodu, jeśli jest przechowywany pod adresem 1900 USD we wkładzie Atari 2600, wyświetli liczbę wierszy w różnych kolorach pobranych z tabeli rozpoczynającej się pod adresem 1437 USD. W przypadku niektórych narzędzi wpisanie adresu wraz z prawą częścią wiersza powyżej zapisuje w pamięci wartości pokazane w środkowej kolumnie i rozpoczyna następny wiersz o następującym adresie. Pisanie kodu w tej formie było znacznie wygodniejsze niż pisanie szesnastkowe, ale trzeba było znać dokładne adresy wszystkiego.
Większość asemblerów pozwala używać adresów symbolicznych. Powyższy kod zostałby napisany bardziej jak:
rainbow_lp: lda ColorTbl, x sta WSYNC sta COLUBK dex bpl rainbow_lp
Asembler automatycznie dostosuje instrukcję LDA, aby odnosiła się do dowolnego adresu mapowanego na etykietę ColorTbl. Korzystanie z tego stylu asemblera znacznie ułatwia pisanie i edycję kodu, niż byłoby to możliwe, gdyby ktoś musiał ręcznie wpisywać i utrzymywać wszystkie adresy.
Kod źródłowy, kod zestawu, kod maszynowy, kod obiektu, kod bajtowy, plik wykonywalny i plik biblioteki.
Wszystkie te warunki są często bardzo mylące dla większości ludzi, ponieważ uważają, że wzajemnie się wykluczają . Zobacz diagram, aby zrozumieć ich relacje. Opis każdego terminu znajduje się poniżej.
Instrukcje w języku czytelnym dla ludzi (programistycznym)
Instrukcje napisane w języku wysokiego poziomu (programowania),
np. C, C ++ i programy Java
Instrukcje napisane w języku asemblera (rodzaj języka programowania niskiego poziomu). Jako pierwszy krok procesu kompilacji kod wysokiego poziomu jest konwertowany na tę formę. Jest to kod zestawu, który jest następnie konwertowany na rzeczywisty kod maszynowy. W większości systemów te dwa kroki są wykonywane automatycznie w ramach procesu kompilacji.
np. program.asm
Produkt procesu kompilacji. Może mieć postać kodu maszynowego lub kodu bajtowego.
np. plik.o
Instrukcje w języku maszynowym.
np. a.out
Instrukcja w formie pośredniej, którą może wykonać interpreter, taki jak JVM.
np. plik klasy Java
Produkt procesu łączenia. Są to kod maszynowy, który może być bezpośrednio wykonany przez CPU.
np. plik .exe.
Zauważ, że w niektórych kontekstach plik zawierający instrukcje bajtowe lub instrukcje języka skryptowego może być również uznany za wykonywalny.
Niektóre kody są kompilowane w tej formie z różnych powodów, takich jak możliwość ponownego użycia, a później wykorzystywane przez pliki wykonywalne.
cc1
pliku wykonywalnym). Myślę, że okrąg asm powinien wystawać z lewej strony koła „źródłowego”, ponieważ niektóre asm to tylko asm, a nie źródło. Oczywiście nigdy nie jest to kod obiektowy , ale niektóre asm są krokiem na drodze od plików źródłowych do obiektów obiektowych.
Kod zestawu jest omawiany tutaj .
„Język asemblera jest językiem niskiego poziomu do programowania komputerów. Implementuje symboliczną reprezentację numerycznych kodów maszynowych i innych stałych potrzebnych do zaprogramowania konkretnej architektury procesora”.
Kod maszynowy omówiono tutaj .
„Kod maszynowy lub język maszynowy to system instrukcji i danych wykonywanych bezpośrednio przez komputerową jednostkę centralną.”
Zasadniczo kod asemblera jest językiem i jest tłumaczony na kod obiektowy (natywny kod uruchamiany przez CPU) przez asembler (analogicznie do kompilatora).
Myślę, że to są główne różnice
Z drugiej strony czytelność kodu może poprawić lub zastąpić kod 6 miesięcy po jego stworzeniu, ale jeśli wydajność ma krytyczne znaczenie, możesz użyć języka niskiego poziomu do ukierunkowania na konkretny sprzęt, który będziesz mieć na produkcji, aby uzyskać szybsze wykonanie.
Dzisiaj IMO komputery są wystarczająco szybkie, aby umożliwić programistom szybkie wykonanie z OOP.
Zestawienie to krótkie opisowe terminy, które ludzie mogą zrozumieć, które można bezpośrednio przełożyć na kod maszynowy faktycznie wykorzystywany przez procesor.
Choć nieco zrozumiały dla ludzi, Asembler jest wciąż na niskim poziomie. Wykonanie czegokolwiek pożytecznego wymaga dużo kodu.
Zamiast tego używamy języków wyższego poziomu, takich jak C, BASIC, FORTAN (OK, wiem, że sam się umawiałem). Po skompilowaniu tworzą kod obiektowy. Wczesne języki miały język maszynowy jako kod obiektowy.
Obecnie wiele języków, takich jak JAVA i C #, zwykle kompiluje się do kodu bajtowego, który nie jest kodem maszynowym, ale taki, który można łatwo zinterpretować w czasie wykonywania w celu wygenerowania kodu maszynowego.
Pliki źródłowe twoich programów są kompilowane w pliki obiektowe, a następnie linker łączy te pliki obiektowe razem, tworząc plik wykonywalny zawierający kody maszynowe twojej architektury.
Zarówno plik obiektowy, jak i plik wykonywalny obejmuje kod maszynowy architektury w postaci drukowalnych i niedrukowalnych znaków, gdy jest otwierany przez edytor tekstowy.
Niemniej jednak dychotomia między plikami polega na tym, że pliki obiektowe mogą zawierać nierozwiązane odwołania zewnętrzne (takie jak printf
na przykład). Może być konieczne powiązanie go z innymi plikami obiektowymi. Oznacza to, że nierozwiązane odwołania zewnętrzne muszą zostać rozwiązane, aby uzyskać przyzwoity plik wykonywalny, łącząc się z innymi plikami obiektowymi, takimi jak biblioteka środowiska wykonawczego C / C ++ .