Выполнение программы |
---|
Общие понятия |
Типы кода |
Стратегии компиляции |
Заметное время выполнения |
|
Известные компиляторы и инструментальные средства |
|
|
В компьютерном программировании, машинный код является любым языком программирования низкого уровня, состоящий из машинного языка инструкций, который используется для управления компьютером в центральном процессоре (ЦП). Каждая инструкция заставляет ЦП выполнять очень конкретную задачу, такую как загрузка, сохранение, переход или операция арифметико-логического устройства (АЛУ) над одним или несколькими блоками данных в регистрах или памяти ЦП.
Машинный код - это строго числовой язык, который предназначен для работы с максимально возможной скоростью и может рассматриваться как представление самого низкого уровня скомпилированной или собранной компьютерной программы или как примитивный и аппаратно- зависимый язык программирования. Хотя можно писать программы непосредственно в машинном коде, управление отдельными битами и вычисление числовых адресов и констант вручную утомительно и чревато ошибками. По этой причине в современных условиях программы очень редко пишутся непосредственно в машинном коде, но могут выполняться для низкоуровневой отладки, исправления программ (особенно когда исходный код ассемблера недоступен) и дизассемблирования языка ассемблера.
Большинство практических программ сегодня написано на языках более высокого уровня или ассемблере. Затем исходный код транслируется в исполняемый машинный код такими утилитами, как компиляторы, ассемблеры и компоновщики, за важным исключением интерпретируемых программ, которые не транслируются в машинный код. Однако сам интерпретатор, который может рассматриваться как исполнитель или процессор, выполняющий инструкции исходного кода, обычно состоит из непосредственно исполняемого машинного кода (сгенерированного из исходного кода на языке сборки или языка высокого уровня).
Машинный код по определению является самым низким уровнем детализации программирования, видимым программисту, но внутри многие процессоры используют микрокод или оптимизируют и преобразуют инструкции машинного кода в последовательности микроопераций. Обычно это не считается машинным кодом.
Каждый процессор или семейство процессоров имеет свой собственный набор команд. Инструкции - это комбинации битов, цифр или символов, которые соответствуют машинным командам. Таким образом, набор команд специфичен для класса процессоров, использующих (в основном) одну и ту же архитектуру. Конструкции последующих или производных процессоров часто включают инструкции предшественника и могут добавлять новые дополнительные инструкции. Иногда последующий дизайн прерывает или изменяет значение некоторого кода инструкции (обычно потому, что он нужен для новых целей), в некоторой степени влияя на совместимость кода; даже совместимые процессоры могут показывать несколько иное поведение для некоторых инструкций, но это редко является проблемой. Системы также могут отличаться другими деталями, такими как расположение памяти, операционные системы или периферийные устройства. Поскольку программа обычно полагается на такие факторы, разные системы обычно не будут запускать один и тот же машинный код, даже если используется один и тот же тип процессора.
В наборе команд процессора могут быть все команды одинаковой длины или могут быть команды переменной длины. Как организованы шаблоны, зависит от конкретной архитектуры и типа обучения. Большинство инструкций имеют одно или несколько полей кода операции, которые определяют базовый тип инструкции (например, арифметическая, логическая, переход и т. Д.), Операцию (например, сложение или сравнение) и другие поля, которые могут указывать тип операнда (s), режим (ы) адресации, смещение (а) адресации или индекс, или само значение операнда (такие постоянные операнды, содержащиеся в инструкции, называются немедленными).
Не все машины или отдельные инструкции имеют явные операнды. Аккумулятор машина имеет комбинированный левый операнд и результат в неявном аккумуляторе для большинства арифметических команд. Другие архитектуры (например, 8086 и семейство x86) имеют аккумуляторные версии общих инструкций, при этом аккумулятор рассматривается как один из общих регистров более длинными инструкциями. Стек машина имеет большую часть или все свои операнды на неявной стеке. В инструкциях специального назначения также часто отсутствуют явные операнды (например, CPUID в архитектуре x86 записывает значения в четыре неявных регистра назначения). Это различие между явными и неявными операндами важно в генераторах кода, особенно в частях выделения регистров и отслеживания текущего диапазона. Хороший оптимизатор коды может отслеживать неявно, а также явные операнды, которые могут позволить более частому распространение постоянная, постоянное складывание регистров (регистр, назначенный результат выражения постоянная высвободившемуся, заменив его на этой константе) и других усовершенствования кода.
Компьютерная программа представляет собой список инструкций, которые могут быть выполнены с помощью центрального процессора (CPU). Выполнение программы выполняется для того, чтобы ЦП, выполняющий ее, решил проблему и, таким образом, достиг результата. В то время как простые процессоры могут выполнять инструкции одну за другой, суперскалярные процессоры могут выполнять множество инструкций одновременно.
На выполнение программы могут влиять специальные инструкции «перехода», которые передают выполнение на адрес (и, следовательно, инструкцию), отличный от следующего числового последовательного адреса. Возникновение этих условных переходов зависит от такого условия, как значение, которое больше, меньше или равно другому значению.
Гораздо более удобное для человека представление машинного языка, называемое языком ассемблера, использует мнемонические коды для обозначения инструкций машинного кода, а не напрямую числовые значения инструкций, и использует символические имена для обозначения мест хранения, а иногда и регистров. Например, на процессоре Zilog Z80 машинный код 00000101
, который заставляет ЦП декрементировать B
регистр процессора, будет представлен на языке ассемблера как DEC B
.
Архитектура MIPS представляет собой конкретный пример машинного кода, инструкции которого всегда имеют длину 32 бита. Общий тип инструкции задается полем op (операция), старшие 6 бит. Инструкции J-типа (переход) и I-типа (немедленные) полностью определены op. Р-тип (регистр) инструкции включают в себя дополнительные полях FUNCT для определения точной операции. Поля, используемые в этих типах:
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 и rd обозначают регистровые операнды; shamt дает величину сдвига; а поля адреса или непосредственного присутствия содержат непосредственно операнд.
Например, сложение регистров 1 и 2 и помещение результата в регистр 6 кодируется:
[ op | rs | rt | rd |shamt| funct] 0 1 2 6 0 32 decimal 000000 00001 00010 00110 00000 100000 binary
Загрузите значение в регистр 8, взятое из ячейки памяти 68 ячеек после ячейки, указанной в регистре 3:
[ op | rs | rt | address/immediate] 35 3 8 68 decimal 100011 00011 01000 00000 00001 000100 binary
Переход по адресу 1024:
[ op | target address ] 2 1024 decimal 000010 00000 00000 00000 10000 000000 binary
В некоторых компьютерных архитектурах машинный код реализуется с помощью еще более фундаментального базового уровня, называемого микрокодом, который обеспечивает общий интерфейс на машинном языке в линейке или семействе различных моделей компьютеров с сильно различающимися базовыми потоками данных. Это сделано для облегчения портирования программ на машинном языке между разными моделями. Примером такого использования является семейство компьютеров IBM System / 360 и их преемники. Благодаря ширине пути потока данных от 8 до 64 бит и более, они, тем не менее, представляют общую архитектуру на уровне машинного языка по всей линии.
Использование микрокода для реализации эмулятора позволяет компьютеру представить архитектуру совершенно другого компьютера. Линия System / 360 использовала это, чтобы позволить переносить программы с более ранних машин IBM на новое семейство компьютеров, например, эмулятор IBM 1401/1440/1460 на IBM S / 360 model 40.
Машинный код обычно отличается от байт-кода (также известного как p-код), который либо выполняется интерпретатором, либо сам компилируется в машинный код для более быстрого (прямого) выполнения. Исключение составляют случаи, когда процессор предназначен для использования определенного байт-кода непосредственно в качестве своего машинного кода, как в случае с процессорами Java.
Машинный код и ассемблерный код иногда называют собственным кодом, когда речь идет о платформенно-зависимых частях языковых функций или библиотек.
Гарварда архитектура является компьютерной архитектурой с физически отдельными хранением и сигнальными путями для кода (инструкция) и данными. Сегодня большинство процессоров реализуют такие отдельные пути прохождения сигналов по соображениям производительности, но реализуют модифицированную гарвардскую архитектуру, поэтому они могут поддерживать такие задачи, как загрузка исполняемой программы из дискового хранилища в качестве данных и последующее ее выполнение. Гарвардская архитектура отличается от архитектуры фон Неймана, где данные и код хранятся в одной и той же памяти, которая считывается процессором, позволяя компьютеру выполнять команды.
С точки зрения процесса, пространство кода - это часть его адресного пространства, где хранится исполняемый код. В многозадачных системах это сегмент кода программы и обычно разделяемые библиотеки. В многопоточной среде разные потоки одного процесса совместно используют пространство кода вместе с пространством данных, что значительно снижает накладные расходы на переключение контекста по сравнению с переключением процессов.
Памела Самуэльсон написала, что машинный код настолько нечитаем, что Бюро регистрации авторских прав США не может определить, является ли конкретная закодированная программа оригинальной авторской работой; Однако Бюро регистрации авторских прав США действительно позволяют для регистрации авторских прав на компьютерные программы и машинного кода программы иногда может быть декомпилированы для того, чтобы сделать его работу более легко понятной для человека. Однако в выводе декомпилятора или дизассемблера будут отсутствовать комментарии и символические ссылки, поэтому, хотя вывод может быть легче читаем, чем объектный код, он все равно будет сложнее, чем исходный исходный код. Эта проблема не существует для форматов объектного кода, таких как SQUOZE, где исходный код включен в файл.
Профессор когнитивных наук Дуглас Хофштадтер сравнил машинный код с генетическим кодом, заявив, что «взгляд на программу, написанную на машинном языке, отдаленно сравним с взглядом на молекулу ДНК, атом за атомом».