Код сборки против машинного кода против объектного кода?


227

В чем разница между объектным кодом, машинным кодом и кодом сборки?

Можете ли вы привести наглядный пример их различия?


Мне также любопытно, откуда появилось название «объектный код»? Что слово «объект» должно означать в нем? Это как-то связано с объектно-ориентированным программированием или просто совпадением имен?
SasQ


Я не спрашиваю о том, что такое объектный код, капитан Очевидность. Я спрашиваю, откуда появилось имя и почему оно называется «объектным» кодом.
BarbaraKwarc

Ответы:


296

Машинный код - это двоичный код (1 и 0), который может выполняться непосредственно процессором. Если бы вы открыли файл машинного кода в текстовом редакторе, вы бы увидели мусор, включая непечатные символы (нет, не те непечатные символы;)).

Объектный код - это часть машинного кода, которая еще не была связана в законченную программу. Это машинный код одной конкретной библиотеки или модуля, который будет составлять готовый продукт. Он также может содержать заполнители или смещения, не найденные в машинном коде завершенной программы. Компоновщик будет использовать эти заполнители и коррекции для подключения все вместе.

Код ассемблера представляет собой простой текстовый и (в некоторой степени) читаемый исходный код, который в основном имеет прямой аналог 1: 1 с машинными инструкциями. Это достигается с помощью мнемоники для фактических инструкций, регистров или других ресурсов. Примеры включают JMPи MULTдля команд перехода и умножения процессора. В отличие от машинного кода, процессор не понимает ассемблерный код. Вы преобразуете ассемблерный код в машину с использованием ассемблера или компилятора , хотя мы обычно думаем о компиляторах в сочетании с языком программирования высокого уровня, который абстрагируется дальше от инструкций процессора.

Создание полной программы включает в себя написание исходного кода для программы либо на ассемблере, либо на языке более высокого уровня, таком как C ++. Исходный код собирается (для ассемблера) или компилируется (для языков более высокого уровня) в объектный код, а отдельные модули связываются вместе, чтобы стать машинным кодом для конечной программы. В случае очень простых программ этап связывания может не понадобиться. В других случаях, например, в IDE (интегрированная среда разработки), компоновщик и компилятор могут вызываться вместе. В других случаях может использоваться сложный сценарий make или файл решения, чтобы сообщить среде, как создать окончательное приложение.

Есть также интерпретируемые языки, которые ведут себя по-разному. Интерпретируемые языки полагаются на машинный код специальной программы переводчика. На базовом уровне интерпретатор анализирует исходный код и немедленно преобразует команды в новый машинный код и выполняет их. Современные интерпретаторы, которые иногда также называют средой выполнения или виртуальной машиной , намного сложнее: оценивать целые разделы исходного кода за раз, кэшировать и оптимизировать, где это возможно, и обрабатывать сложные задачи управления памятью. Интерпретированный язык также может быть предварительно скомпилирован для промежуточного языка или байт-кода более низкого уровня, аналогично ассемблерному коду.


24
+1: хороший, но несколько упрощенный ответ - не все инструкции по сборке переводятся 1: 1 в машинные инструкции, а объектные файлы могут также содержать другие данные (информация о перемещении, таблицы символов, ...)
Кристоф

5
Добавлено добавленное слово для вашей первой проблемы, отредактированное, чтобы сделать 2-е прояснение.
Джоэл Коухорн

2
@Christoph: вы говорите, что «не все инструкции по сборке переводятся 1: 1 в машинные инструкции», приведите пример.
Олоф Форшелл

5
@Olof: RISC-архитектуры иногда предоставляют виртуальный набор команд на уровне сборки - например, псевдоинструкции MIPS ( en.wikipedia.org/wiki/MIPS_architecture#Pseudo_instructions )
Кристоф,

3
@Panzercrisis Ассемблер не добавляет ничего. Это прямой перевод того, что вы написали, для настоящих машинных инструкций. И я бы не назвал дополнительный код, вставленный компиляторами, «ненужным»
Джоэл Кехорн

125

Другие ответы дали хорошее описание разницы, но вы также попросили визуальный. Вот диаграмма, показывающая, как они переходят от кода C к исполняемому файлу.


3
Я нахожу это действительно полезным, но в нем отсутствует ярлык «Машинный код»
Alexx Roche

Итак, когда это на уровне исполняемого кода, это эквивалентно машинному коду?
CMCDragonkai

3
В контексте этой схемы «объектный код» является машинным кодом.
Графика Нуб

5
На самом деле, и объектный код, и исполняемый код являются машинными кодами. Разница в том, что объектный код не является законченной программой. Его необходимо объединить с другими кодами вспомогательных библиотек / модулей, как показано на схеме, для формирования полной исполняемой программы / кода.
okey_on

@ okeyxyz на каком уровне было бы правильно сказать, что он непосредственно выполняется процессором? После ассемблера, после компоновщика, после загрузчика, после того, как он конвертируется в микроконтроллер?
Celeritas

49

Ассемблерный код представляет собой удобочитаемое представление машинного кода:

mov eax, 77
jmp anywhere

Машинный код - это чистый шестнадцатеричный код:

5F 3A E3 F1

Я предполагаю, что вы имеете в виду объектный код, как в объектном файле. Это вариант машинного кода, с той разницей, что переходы параметризованы таким образом, что компоновщик может их заполнить.

Ассемблер используется для преобразования ассемблерного кода в машинный код (объектный код). Компоновщик связывает несколько файлов объектов (и библиотек) для создания исполняемого файла.

Однажды я написал программу на ассемблере в чистом шестнадцатеричном формате (ассемблер не доступен), к счастью, это было в далеком старом (старом) 6502. Но я рад, что есть ассемблеры для кодов операций Pentium.


76
Нет нет Нет Нет. Машинный код не является шестнадцатеричным кодом. это чистый двоичный файл. Шестнадцатеричный код - это просто удобное представление бинарного файла.
Бретон

56
Если мы действительно впадаем в крайности, это не двоично, это количество накопленного электричества в цепи. ;-)
Мульт Крайте

17
Ну конечно; естественно. Существует взаимосвязь между шестнадцатеричным и тем, что вы бы назвали «машинным кодом», но не совсем точно сказать, что шестнадцатеричное - это машинный код. Это все, что я пытаюсь сказать.
Бретон

9
@ Бретон В этом смысле не существует такой вещи, как «шестнадцатеричный код», верно? «Шестнадцатеричный код» - это просто способ просмотра машинного кода. Вы можете просматривать машинный код в шестнадцатеричном, двоичном, восьмеричном, десятичном или любом другом виде. Кроме того, опять же, в этом смысле, нет и «двоичного кода». Опять же, «двоичный код» - это просто способ просмотра машинного кода.
Утку

9
@ Бретон То, что вы говорите, на самом деле не имеет особого смысла .. Бинарный - это способ представления, как и гекс. Если он не шестнадцатеричный, он не двоичный.
Корай Тугай

18

8B 5D 32 это машинный код

mov ebx, [ebp+32h] это сборка

lmylib.soсодержащий 8B 5D 32объектный код


8

Еще один момент, о котором не упоминалось, это то, что существует несколько различных типов кода сборки. В самой основной форме все числа, используемые в инструкциях, должны быть указаны как константы. Например:

1902 год: 37 долларов США; 1437 долларов США:
$ 1905: 85 03: STA $ 03
$ 1907: 85 09: STA $ 09
$ 1909: CA: DEX
190 $: 10: BPL $ 1902

Приведенный выше фрагмент кода, если он хранится по адресу $ 1900 в картридже Atari 2600, будет отображать количество строк разных цветов, извлеченных из таблицы, которая начинается по адресу $ 1437. На некоторых инструментах ввод адреса вместе с крайней правой частью строки выше сохранял бы в памяти значения, показанные в среднем столбце, и начинал следующую строку со следующего адреса. Ввод кода в такой форме был намного удобнее, чем ввод в шестнадцатеричном формате, но нужно было знать точные адреса всего.

Большинство ассемблеров позволяют использовать символические адреса. Приведенный выше код будет написан больше как:

rainbow_lp:
  lda ColorTbl, x
  Sta WSYNC
  Sta COLUBK
  Dex
  bpl rainbow_lp

Ассемблер автоматически настроит инструкцию LDA, чтобы она ссылалась на любой адрес, сопоставленный с меткой ColorTbl. Использование этого стиля ассемблера значительно облегчает написание и редактирование кода, чем это было бы возможно, если бы пришлось вручную и вручную поддерживать все адреса.


1
+1. Еще один дополнительный пункт: есть также различные ассемблере Синтаксисы , наиболее известными из которых являются Intel и AT & T .
informatik01

1
@ informatik01: Как насчет мнемоники Intel 8080 и Zilog Z80? Я предполагаю, что это предшествовало войне синтаксиса Intel против AT & T.
суперкат

Не споря, я только что упомянул этот аспект (другой синтаксис) и привел пример двух самых популярных / известных / известных синтаксисов.
informatik01

4

Исходный код, код сборки, машинный код, код объекта, байт-код, исполняемый файл и файл библиотеки.

Все эти термины часто вводят многих людей в заблуждение тем, что они думают, что они взаимоисключающие . Смотрите схему, чтобы понять их отношения. Описание каждого термина приведено ниже.


Типы кода


Исходный код

Инструкции на человекочитаемом (программирующем) языке


Код высокого уровня

Инструкции, написанные на языке высокого уровня (программирования),
например, C, C ++ и Java программы


Код сборки

Инструкции написаны на ассемблере (разновидность низкоуровневого языка программирования). В качестве первого шага процесса компиляции высокоуровневый код преобразуется в эту форму. Это код сборки, который затем преобразуется в фактический машинный код. В большинстве систем эти два шага выполняются автоматически как часть процесса компиляции.
например, program.asm


Код объекта

Продукт процесса компиляции. Это может быть в форме машинного кода или байтового кода.
например, file.o


Машинный код

Инструкции на машинном языке.
например,


Байт код

Инструкция в промежуточной форме, которая может быть выполнена таким переводчиком, как JVM.
например, файл класса Java


Запускаемый файл

Продукт связывания процесса. Это машинный код, который может напрямую выполняться процессором.
например, файл .exe.

Обратите внимание, что в некоторых контекстах файл, содержащий байт-код или инструкции языка сценариев, также может считаться исполняемым.


Библиотечный файл

Некоторый код компилируется в эту форму по разным причинам, таким как возможность повторного использования и позднее используется исполняемыми файлами.


1
Я бы сказал, что не все сборки действительно источником в самом строгом смысле кода, написанного и / или поддерживаемого людьми. Часто он генерируется машиной из исходного кода и никогда не предназначен для потребления человеком (например, gcc действительно создает asm-текст, который он передает отдельному ассемблеру, вместо того, чтобы иметь встроенный ассемблер внутри cc1исполняемого файла). Я думаю, что асм-круг должен выступать с левой стороны от «исходного» круга, потому что некоторый асм это просто асм, а не источник. Конечно, это никогда не объектный код, но некоторый asm - это шаг на пути от исходного к объектному файлу.
Питер Кордес

@PeterCordes Большое спасибо за комментарий. Я не знал, что вы сказали о работе gcc. Тем не менее, я боюсь, что смогу с вами полностью согласиться. Я имею в виду, что исходный код написан с использованием понятного человеку языка программирования. Это может или не может быть написано или поддержано людьми. Я уверен, что вы будете в курсе транскомпиляторов. С вашей точки зрения, в какую категорию вы поместите продукт такого компилятора? Исходный код или что-то еще? Пожалуйста, поправьте меня, если я ошибаюсь. Дальнейшие комментарии всегда приветствуются.
Бертрам Гилфойл

1

Код сборки обсуждается здесь .

«Ассемблер является языком низкого уровня для программирования компьютеров. Он реализует символическое представление числовых машинных кодов и других констант, необходимых для программирования конкретной архитектуры ЦП».

Машинный код обсуждается здесь .

«Машинный код или машинный язык - это система инструкций и данных, выполняемых непосредственно центральным процессором компьютера».

По сути, ассемблерный код - это язык, и он транслируется ассемблером (аналогично компилятору) в объектный код (нативный код, выполняемый процессором).


1

Я думаю, что это основные отличия

  • удобочитаемость кода
  • контроль над тем, что делает ваш код

С другой стороны, читаемость может улучшить или заменить код через 6 месяцев после его создания, но если производительность критична, возможно, вы захотите использовать язык низкого уровня, чтобы ориентироваться на конкретное оборудование, которое будет у вас на производстве, чтобы получить более быстрое исполнение.

ИМО сегодня компьютеры достаточно быстры, чтобы позволить программисту быстро выполнять работу с ООП.


1

Сборка - это короткие описательные термины, которые могут понять люди, которые могут быть непосредственно переведены в машинный код, который фактически использует процессор.

Хотя ассемблер несколько понятен людям, он все еще находится на низком уровне. Требуется много кода, чтобы сделать что-нибудь полезное.

Таким образом, вместо этого мы используем языки более высокого уровня, такие как C, BASIC, FORTAN (хорошо, я знаю, что встречался сам). При компиляции они производят объектный код. Ранние языки имели машинный язык в качестве объектного кода.

Сегодня многие языки, такие как JAVA и C #, обычно компилируются в байт-код, который не является машинным кодом, а легко интерпретируется во время выполнения для создания машинного кода.


Ваш комментарий о Java и C # - оба используют компиляцию Just In Time, поэтому байтовые коды не интерпретируются. C # (в общем случае .NET) компилируется в промежуточный язык (IL), который затем JITed на родной машинный язык для целевого процессора.
Крейг Ширер

-1

Исходные файлы ваших программ компилируются в объектные файлы, а затем компоновщик связывает эти объектные файлы вместе, создавая исполняемый файл, включая машинные коды вашей архитектуры.

Как объектный файл, так и исполняемый файл содержат машинный код архитектуры в форме печатных и непечатаемых символов, когда он открывается текстовым редактором.

Тем не менее, дихотомия между файлами заключается в том, что объектный файл (файлы) может содержать неразрешенные внешние ссылки (такие как printf, например). Таким образом, возможно, его необходимо связать с другими объектными файлами. То есть неразрешенные внешние ссылки необходимо разрешить, чтобы получить достойный исполняемый исполняемый файл путем связывания с другими объектными файлами, такими как библиотека времени выполнения C / C ++. ,

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.