что такое машинная команда
Структура и форматы машинных команд
Машинная команда представляет собой код, определяющий операцию вычислительной машины и данные, участвующие в операции. Команда должна содержать в явной или неявной форме информацию об адресе результата операции, и об адресе следующей команды.
Машинная операция – это действия машины по преобразованию информации, выполняемые под воздействием одной команды.
Программа – последовательность команд, отображающих все действия, необходимые для решения задачи по некоторому алгоритму.
Машинный такт – период тактовой частоты работы процессора.
Машинный цикл – количество машинных тактов, требуемых для выполнения одной команды.
По характеру выполняемых операций различают следующие основные группы команд:
Машинная команда состоит из операционной и адресной частей. Эти части могут состоять из нескольких полей. В общем виде машинная команда имеет следующую структуру:
Операционная часть содержит код, задающий вид операции (сложение, умножение, передача и т.д.).
Адресная часть содержит информацию об адресах операндов, результата операции и следующей команды.
Структура команды определяется составом, назначением и расположением полей в команде.
Формат команды – это структура команды с разметкой номеров разрядов, определяющих границы отдельных полей команды.
Возможные структуры машинных команд
Двухадресная структура
используется в вычислительных машинах, построенных так, что результат операции будет всегда помещаться в фиксированный регистр процессора, например на место первого операнда. В этом случае адрес результата может явно не указываться.
Безадресная структура фиксирует адреса обоих операндов и результата операции, например при работе со стековой памятью.
Обычно в вычислительной машине используется несколько форматов команд разной длины (чаще всего безадресные, одноадресные и двухадресные).
Машинный код
Из Википедии — свободной энциклопедии
Маши́нный код (платфо́рменно-ориенти́рованный код), маши́нный язы́к — система команд (набор кодов операций) конкретной вычислительной машины, которая интерпретируется непосредственно процессором или микропрограммами этой вычислительной машины. [1]
Компьютерная программа, записанная на машинном языке, состоит из машинных инструкций, каждая из которых представлена в машинном коде в виде т. н. опкода — двоичного кода отдельной операции из системы команд машины. Для удобства программирования вместо числовых опкодов, которые только и понимает процессор, обычно используют их условные буквенные мнемоники. Набор таких мнемоник, вместе с некоторыми дополнительными возможностями (например, некоторыми макрокомандами, директивами), называется языком ассемблера.
Каждая модель процессора имеет собственный набор команд, хотя во многих моделях эти наборы команд сильно перекрываются. Говорят, что процессор A совместим с процессором B, если процессор A полностью «понимает» машинный код процессора B. Если процессоры A и B имеют некоторое подмножество инструкций, по которым они взаимно совместимы, то говорят, что они одной «архитектуры» (имеют одинаковую архитектуру набора команд).
Национальная библиотека им. Н. Э. Баумана
Bauman National Library
Персональные инструменты
Машинный код
Машинный код или машинный язык представляет собой набор инструкций, выполняемых непосредственно центральным процессором компьютера (CPU). Каждая команда выполняет очень конкретную задачу, например, загрузки (load), перехода (jump) или элементарной арифметической или логической операции для единицы данных в регистре процессора или памяти. Каждая программа выполняется непосредственно процессором и состоит из ряда таких инструкций.
Машинный код можно рассматривать как самое низкоуровневое представление скомпилированной или собранной компьютерной программы или в качестве примитивного и аппаратно-зависимого языка программирования. Писать программы непосредственно в машинном коде возможно, однако это утомительно и подвержено ошибкам, так как необходимо управлять отдельными битами и вычислять числовые адреса и константы вручную. По этой причине машинный код практически не используется для написания программ.
Почти все практические программы сегодня написаны на языках более высокого уровня или ассемблере. Исходный код затем транслируется в исполняемый машинный код с помощью таких утилит, как интерпретаторы, компиляторы, ассемблеры, и/или линкеры. [Источник 1]
Содержание
Инструкции машинного кода (ISA)
Каждый процессор или семейство процессоров имеет свой собственный набор инструкций машинного кода. Инструкции являются паттернами битов, которые в силу физического устройства соответствуют различным командам машины. Говорят, что процессор A совместим с процессором B, если процессор A полностью «понимает» машинный код процессора B. Если процессоры A и B имеют некоторое подмножество инструкций, по которым они взаимно совместимы, то говорят, что они одной архитектуры. Таким образом, набор команд является специфическим для одного класса процессоров. Новые процессоры одной архитектуры часто включают в себя все инструкции предшественника и могут включать дополнительные. Иногда новые процессоры прекращают поддержку или изменяют значение какого-либо кода команды (как правило, потому, что это необходимо для новых целей), влияя на совместимость кода до некоторой степени; даже почти полностью совместимые процессоры могут показать различное поведение для некоторых команд, но это редко является проблемой.
Системы также могут отличаться в других деталях, таких как расположение памяти, операционные системы или периферийные устройства. Поскольку программа обычно зависит от таких факторов, различные системы, как правило, не запустят один и тот же машинный код, даже если используется тот же тип процессора. [Источник 2]
Виды ISA
x86 всегда был архитектурой с инструкциями переменной длины, так что когда пришла 64-битная эра, расширения x64 не очень сильно повлияли на ISA. ARM это RISC-процессор разработанный с учетом инструкций одинаковой длины, что было некоторым преимуществом в прошлом. Так что в самом начале все инструкции ARM кодировались 4-мя байтами. Это то, что сейчас называется «режим ARM».
На самом деле, самые используемые инструкции процессора на практике могут быть закодированы c использованием меньшего количества информации. Так что была добавлена ISA с названием Thumb, где каждая инструкция кодируется всего лишь 2-мя байтами. Теперь это называется «режим Thumb». Но не все инструкции ARM могут быть закодированы в двух байтах, так что набор инструкций Thumb ограниченный. Код, скомпилированный для режима ARM и Thumb может сосуществовать в одной программе. Затем создатели ARM решили, что Thumb можно расширить: так появился Thumb-2 (в ARMv7). Thumb-2 это всё ещё двухбайтные инструкции, но некоторые новые инструкции имеют длину 4 байта. Распространено заблуждение, что Thumb-2 — это смесь ARM и Thumb. Это неверно. Режим Thumb-2 был дополнен до более полной поддержки возможностей процессора и теперь может легко конкурировать с режимом ARM. Основное количество приложений для iPod/iPhone/iPad скомпилировано для набора инструкций Thumb-2, потому что Xcode делает так по умолчанию. Потом появился 64-битный ARM. Это ISA снова с 4-байтными инструкциями, без дополнительного режима Thumb. Но 64-битные требования повлияли на ISA, так что теперь у нас 3 набора инструкций ARM: режим ARM, режим Thumb (включая Thumb-2) и ARM64. Эти наборы инструкций частично пересекаются, но можно сказать, это скорее разные наборы, нежели вариации одного. Существует ещё много RISC ISA с инструкциями фиксированной 32-битной длины — это как минимум MIPS, PowerPC и Alpha AXP. [Источник 3]
Выполнение инструкций
Компьютерная программа представляет собой последовательность команд, которые выполняются процессором. В то время как простые процессоры выполняют инструкции один за другим, суперскалярные процессоры способны выполнять несколько команд одновременно.
Программа может содержать специальные инструкций, которые передают выполнение инструкции, не идущей по порядку вслед за предыдущей. Условные переходы принимаются (выполнение продолжается по другому адресу) или нет (выполнение продолжается на следующей инструкции) в зависимости от некоторых условий.
Абсолютный и позиционно-независимый код
Позиционно-независимый код — программа, которая может быть размещена в любой области памяти, так как все ссылки на ячейки памяти в ней относительные (например, относительно счётчика команд). Такую программу можно переместить в другую область памяти в любой момент, в отличие от перемещаемой программы, которая хотя и может быть загружена в любую область памяти, но после загрузки должна оставаться на том же месте.
Возможность создания позиционно-независимого кода зависит от архитектуры и системы команд целевой платформы. Например, если во всех инструкциях перехода в системе команд должны указываться абсолютные адреса, то код, требующий переходов, практически невозможно сделать позиционно-независимым. В архитектуре x86 непосредственная адресация в инструкциях работы с данными представлена только абсолютными адресами, но поскольку адреса данных считаются относительно сегментного регистра, который можно поменять в любой момент, это позволяет создавать позиционно-независимый код со своими ячейками памяти для данных. Кроме того, некоторые ограничения набора команд могут сниматься с помощью самомодифицирующегося кода или нетривиальных последовательностей инструкций.
Хранение в памяти
Гарвардская архитектура представляет собой компьютерную архитектуру с физически разделенным хранением сигнальных путей для инструкций и данных. На сегодняшний день, в большинстве процессоров реализованы отдельные сигнальные пути для повышения производительности. Модифицированная Гарвардская архитектура поддерживает такие задачи, как загрузка исполняемой программы из дисковой памяти в качестве данных, а затем её выполнение. Гарвардская архитектура контрастирует с архитектурой фон Неймана, где данные и код хранятся в памяти вместе, и считываются процессором, позволяя компьютеру выполнять команды.
С точки зрения процесса, кодовое пространство является частью его адресного пространства, в котором код сохраняется во время исполнения. В многозадачных системах оно включает в себя сегмент кода программы и, как правило, совместно используемые библиотеки. В многопоточной среде различные потоки одного процесса используют кодовое пространство и пространство данных совместно, что повышает скорость переключения потока.
Связь с языками программирования
Ассемблерные языки
Гораздо более читаемым представлением машинного языка называется язык ассемблера, использующий мнемонические коды для обозначения инструкций машинного кода, а не с помощью числовых значений. Например, на процессоре Zilog Z80, машинный код 00000101, который дает указание процессору декрементировать регистр процессора B, будет представлен на языке ассемблера как DEC B.
Связь с микрокодом
В некоторых компьютерных архитектурах, машинный код реализуется с помощью более фундаментального базового слоя программ, называемых микропрограммами, обеспечивающими общий интерфейс машинного языка для линейки различных моделей компьютеров с самыми различными базовыми потоками данных. Это делается для облегчения портирования программ на машинном языке между различными моделями. Примером такого использования являются компьютеры IBM System/360 и их наследники. Несмотря на то, что ширина потоков данных разнится от 8 до 64 бит и более, тем не менее они представляют общую архитектуру на уровне машинного языка по всей линейке.
Использование микрокода для реализации эмулятора позволяет компьютеру симулировать совершенно другую архитектуру. Семейство System / 360 использовало это для портирования программ с более ранних машин IBM на новые семейства компьютеров, например на IBM 1401/1440/1460.
Связь с байткодом
Машинный код, как правило, отличается от байт-кода (также известного как р-код), который либо выполняется интерпретатором, или сам компилируется в машинный код для более быстрого исполнения. Исключением является ситуация, когда процессор предназначен для использования конкретного байт-кода как машинного, например, как в случае с процессорами Java. Машинный и ассемблерный код иногда называют собственным (внутренним) кодом ЭВМ, когда ссылаются на платформо-зависимые части свойств или библиотек языка. [Источник 4]
Примеры
Пример MIPS 32-bit инструкции
Набор инструкций MIPS – пример машинного кода с инструкциями фиксированной длины – 32 бита. Тип инструкции содержится в поле op (поле операции) – первые 6 бит. Например типы инструкций перехода или немедленных операций полностью определяются этим полем. Инструкции регистров включают дополнительное поле funct, для определения конкретной операции. Все поля, использущиеся в данных типах инструкций:
Rs,rt и rd – индикаторы задействования регистров, shamt – параметр сдвига,а поле address/immediate явно содержит операнд.
Пример: сложение значений в регистрах 1 и 2 и запись результата в регистр 6:
Пример: загрузка значения в регистр 8, взятое из ячейки памяти, находящейся на 68 ячеек дальше, чем адрес, находящийся в регистре 3:
Пример: переход к адресу 1024:
Пример для x86 (MS DOS) – “Hello, World!”
Программа «Hello, world!» для процессора архитектуры x86 (ОС MS-DOS, вывод при помощи BIOS прерывания int 10h) выглядит следующим образом (в шестнадцатеричном представлении):
BB 11 01 B9 0D 00 B4 0E 8A 07 43 CD 10 E2 F9 CD 20 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21
Данная программа работает при её размещении по смещению 10016. Отдельные инструкции выделены цветом:
Машинный код
Машинный код (платформенно-ориентированный код), машинный язык — система команд (набор кодов операций) конкретной вычислительной машины, которая интерпретируется непосредственно процессором или микропрограммами этой вычислительной машины. [1]
Каждая инструкция выполняет определённое (обычное элементарное) действие, такое как операция с данными (например, сложение или копирование; в регистре или в памяти) или переход к другому участку кода (изменение порядка исполнения; при этом переход может быть безусловным или условным, зависящим от результатов предыдущих инструкций). Каждая исполнимая программа состоит из последовательности таких атомарных инструкций.
Машинный код можно рассматривать как примитивный язык программирования или как самый низкий уровень представления скомпилированных или ассемблированных компьютерных программ. Хотя вполне возможно создавать программы прямо в машинном коде, сейчас это делается редко в силу громоздкости кода и трудоёмкости управления ресурсами процессора, за исключением ситуаций, когда требуется экстремальная оптимизация. Поэтому подавляющее большинство программ пишется на языках более высокого уровня и транслируется в машинный код компиляторами. Машинный код иногда называют нативным кодом (также собственным или родным кодом — от англ. native code ), когда говорят о платформенно-зависимых частях языка или библиотек. [2]
Программы на интерпретируемых языках (таких как Бейсик или Python) не транслируются в машинный код, вместо этого они либо исполняются непосредственно интерпретатором, либо транслируются в псевдокод (байт-код). Однако интерпретаторы этих языков (которые сами можно рассматривать как процессоры) как правило представлены в машинном коде.
Каждая модель процессора имеет свой собственный набор команд, хотя во многих моделях эти наборы команд сильно перекрываются. Говорят, что процессор A совместим с процессором B, если процессор A полностью «понимает» машинный код процессора B. Если процессор A знает несколько команд, которых не понимает процессор B, то B несовместим с A.
Раньше процессоры просто выполняли инструкции одну за другой, но новые суперскалярные процессоры способны выполнять несколько инструкций за раз.
Также инструкции бывают постоянной длины (у RISC-, MISC-архитектур) и диапазонной (у CISC-архитектур; например, для архитектуры x86 команда имеет длину от 8 до 120 битов).
Содержание
Микрокод
В некоторых компьютерных архитектурах поддержка машинного кода реализуется ещё более низкоуровневым слоем программ, называемых микропрограммами, что позволяет обеспечить единый интерфейс машинного языка у всей линейки или семейства компьютеров, которые могут иметь значительные структурные отличие между собой. Это делается для облегчения переноса программ в машинном коде между разными моделями компьютеров. Примером этого является семейство компьютеров IBM System/360 и их преемников: несмотря на разные шины шириной от 8 до 64 бит и выше, тем не менее у них общая архитектура на уровне машинного языка.
Использование слоя микрокода для реализации эмулятора позволяет компьютеру представлять архитектуру совершенно другого компьютера. В линейке System/360 это использовалось для переноса программ с более ранних машин IBM на новое семейство — например, эмулятор IBM 1401/1440/1460 на IBM S/360 model 40.
Абсолютный и позиционно-независимый код
Позиционно-независимый код (англ. position-independent code ) — программа, которая может быть размещена в любой области памяти, так как все ссылки на ячейки памяти в ней относительные (например, относительно счётчика команд). Такую программу можно переместить в другую область памяти в любой момент, в отличие от перемещаемой программы, которая хотя и может быть загружена в любую область памяти, но после загрузки должна оставаться на том же месте. [1]
Возможность создания позиционно-независимого кода зависит от архитектуры и системы команд целевой платформы. Например, если во всех инструкциях перехода в системе команд должны указываться абсолютные адреса, то код, требующий переходов, практически невозможно сделать позиционно-независимым. В архитектуре x86 непосредственная адресация в инструкциях работы с данными представлена только абсолютными адресами, но поскольку адреса данных считаются относительно сегментного регистра, который можно поменять в любой момент, это позволяет создавать позиционно-независимый код со своими ячейками памяти для данных. Кроме того, некоторые ограничения набора команд могут сниматься с помощью самомодифицирующегося кода или нетривиальных последовательностей инструкций.
Программа «Hello, world!»
Программа «Hello, world!» для процессора архитектуры x86 (ОС DOS, вывод при помощи BIOS Int 10h (англ.) выглядит следующим образом (в шестнадцатеричном представлении побайтно):
BB 11 01 B9 0D 00 B4 0E 8A 07 43 CD 10 E2 F9 CD 20 48 65 6C 6C 6F 2C 20 57 6F 72 6C 64 21
Данная программа работает при её размещении по смещению 10016. Отдельные инструкции выделены цветом:
Что такое машинная команда
Теперь познакомимся еще с одним принципом архитектуры ЭВМ, предложенным фон Нейманом. Он называется принципом хранимой программы.
Наряду с данными в оперативную память компьютера помещается программа управления его работой.
Компьютер является исполнителем программ и, следовательно, обладает своей системой команд (СКИ).
Команды управления работой компьютера принято называть машинными командами.
Компьютеры разных типов имеют разную структуру команд.
Всякая машинная команда состоит из кода операции и адресной части.
В «УК Нейман» машинные команды имеют трехадресную структуру (формат). Это значит, что ячейка, в кото-рой хранится команда, делится на четыре части (по одному байту на каждую часть). Будем их обозначать следующим образом:
КОП — код операции,
А1 — адрес первого операнда,
А2 — адрес второго операнда,
A3 — адрес результата.
Операндами называют данные, над которыми производится операция. В арифметических операциях это слагаемые, сомножители, уменьшаемое и вычитаемое, делимое и делитель.
Вот пример команды сложения двух чисел (в шестнадцатеричной форме):
КОП | А1 | А2 | A3 |
01 | 44 | 48 | 4С |
01 — это код операции сложения;
44 — адрес первого слагаемого;
48 — адрес второго слагаемого;
4С — адрес ячейки, в которую помещается сумма.
Для всех арифметических операций ответ на вопрос: «Какую команду выполнять следующей?» всегда одинаковый: следующей выполняется команда, находящаяся в следующей ячейке памяти.
Записывать команды на бумаге удобнее в шестнадцатеричной форме. В памяти ЭВМ команда имеет двоичный вид. Используя двоично-шестнадцатеричную таблицу, легко получить внутреннее представление приведенной выше команды:
КОП | А1 | А2 | A3 |
00000001 | 01000100 | 01001000 | 01001100 |
В ТАБЛИЦЕ 2 содержится система команд «УК Нейман».
ТАБЛИЦА 2. Система команд «УК Нейман»:
КОП | Операция | Пояснение |
00 | Пересылка | (А1)=>АЗ |
01 | Сложение | (А1) + (А2)=>АЗ |
02 | Вычитание | (А1)-(А2)=>АЗ |
03 | Умножение | (А1)*А2)=>АЗ |
77 | Останов | Прекращение выполнения программы программы |
Запись (А1) + (А2) => A3 надо понимать так: содержимое ячейки с адресом А1 сложить с содержимым ячейки с адресом А2 и результат записать в ячейку A3;
(А1)=> A3 — содержимое ячейки А1 занести (скопировать) в ячейку A3.
Совокупность правил записи программ управления компьютером с использованием машинных команд называется машинным языком (или языком машинных команд).
Рассмотрим пример небольшой программы на машинном языке. Пусть, например, требуется вычислить выражение
Каждое число, участвующее в расчетах, занимает ячейку памяти. Программист должен сам распределять память под данные. Под величины А, В, С выделим следующие ячейки памяти:
(20) = А,    (24) = В,   (28) = С.
Результат вычисления выражения поместим в ячейку 2С. Команды программы тоже помещаются в определенные ячейки. Вот фрагмент программы, решающей нашу задачу:
Адрес | КОП | А1 | А2 | A3 | Пояснение |
ОС | 01 | 20 | 24 | 2С | (20)+(24) => 2С     А+В |
10 | 03 | 2С | 28 | 2С | (2С)х(28)=>2С    (А+В)*С |
В графе «Адрес» указываются номера ячеек, в которых располагаются команды. Команды этой программы выполняются в «естественном порядке» возрастания адресов ячеек: сначала ОС, затем 10 (еще раз напомним, что адреса ячеек меняются с шагом 4).
Занесение значения в ячейку памяти называется присваиванием.
В результате присваивания старое значение, которое хранилось в этой ячейке, стирается и заменяется на новое.
Если ячейке ничего не присвоено, то ее значение является неопределенным.
Ячейке 2С значение присваивается дважды: сначала результат суммирования, затем — умножения. Первый результат — промежуточный, второй — окончательный.
Однако приведенная программа не может быть исполнена. Во-первых, не определены значения исходных данных А, В, С. Во-вторых, пользователь не сможет узнать результаты вычислений, поскольку они останутся внутри памяти, в ячейке 2С, а в нее не заглянешь.
Исходные данные должны задаваться вводом.
Ввод — это процесс занесения данных в оперативную память с помощью устройств ввода.
Результаты вычислений должны быть выведены.
Вывод — это отражение информации в оперативной памяти на устройствах вывода.
Вывод делает результаты выполнения программы доступными для пользователя.
Устройством ввода на «УК Нейман» является клавиатура. Устройством вывода — экран.
В «УК Нейман» ввод и вывод организованы следующим образом: с клавиатурой и экраном связана последняя ячейка памяти — ячейка FC. Будем называть ее буферной ячейкой ввода-вывода.
При вводе набираемое на клавиатуре значение попадает в ячейку FC. На экране постоянно отражается содержимое ячейки FC в шестнадцатеричном виде. Поэтому для вывода значения из любой ячейки памяти его надо переслать в буферную ячейку FC.
Из ТАБЛИЦЫ 2 следует, что команда пересылки имеет вид:
00 | А1 |     | A3 |
В этой команде содержимое адреса А2 не влияет на ее исполнение (в дальнейшем на месте А2 будем писать нули). В результате выполнения команды пересылки значение в ячейке A3 становится равным (А1). При этом значение ячейки А1 не меняется. Иначе это называется так: ячейке A3 присваивается значение ячейки А1.
Поясним на примере.
Пусть в 10-й ячейке находится число 5, а в 20-й ячейке число 7:
После выполнения команды
их значения станут одинаковыми:
В рассмотренной выше задаче вычисления (А + В) * Сна экран нужно вывести результат, полученный в ячейке 2С. Для этого его следует присвоить ячейке FC. Значит, команда вывода будет такой:
Как запрограммировать ввод значения А в ячейку 20? Делается это так:
Запишем команды ввода и вывода в общем виде:
00 FC 00 A3 — ввод числа в ячейку
A3 00 А1 00 FC — вывод числа из ячейки А1
А теперь запишем программу вычисления выражения (А+В) * С в окончательном виде. Договоримся, что любая программа будет располагаться в начале памяти. Первая команда всегда находится в ячейке 00.
Адрес | КОП | А1 | А2 | A3 | Пояснения |
00 | 00 | FC | 00 | 20 | ввод А |
04 | 00 | FC | 00 | 24 в | ввод В |
08 | 00 | FC | 00 | 28 | ввод С |
ОС | 01 | 20 | 24 | 2С | А+В |
10 | 03 | 2С | 28 | 2С | (А+В)*С |
14 | 00 | 2С | 00 | FC | вывод результата |
18 | 77 | 00 | 00 | 00 | стоп |
В ячейке 18 находится команда останова с кодом операции 77. Результат ее остановка работы машины. Содержимое адресной части в этой команде не имеет значения.
Коротко о главном
Программа, управляющая работой компьютера, помещается в его оперативную память.
В машинной команде заключена следующая информация: какая выполняется операция, где хранятся операнды, куда поместить результат, какую команду выполнять следующей (если нет указания, то следующей выполняется команда, расположенная в следующей ячейке).
Машинная команда состоит из кода операции (КОП) и адресной части.
«УК Нейман»имеет трехадресную структуру команды: КОП A1 A2 A3.
Для арифметических операций А1 и А2 — адреса операндов, A3 — адрес результата.
Исходные данные вводятся в память по команде ввода, результаты выводятся по команде вывода.