Эта статья о системе команд в целом; об инструкциях см.
Код операции
.
Маши?нный код
(
платфо?рменно-ориенти?рованный код
),
маши?нный язы?к
?
система команд
(набор кодов операций) конкретной
вычислительной машины
, которая
интерпретируется
непосредственно
процессором
или
микропрограммами
этой вычислительной машины.
[1]
Компьютерная программа
, записанная на машинном языке, состоит из
машинных инструкций
, каждая из которых представлена в машинном коде в виде т. н.
опкода
?
двоичного кода
отдельной операции из системы команд машины. Для удобства
программирования
вместо числовых опкодов, которые только и понимает процессор, обычно используют их условные буквенные
мнемоники
. Набор таких мнемоник, вместе с некоторыми дополнительными возможностями (например, некоторыми макрокомандами,
директивами
), называется
языком ассемблера
.
Каждая модель процессора имеет собственный набор команд, хотя во многих моделях эти наборы команд сильно перекрываются. Говорят, что процессор
A
совместим
с процессором
B
, если процессор
A
полностью ≪понимает≫ машинный код процессора
B
. Если процессоры
A
и
B
имеют некоторое подмножество инструкций, по которым они взаимно совместимы, то говорят, что они одной ≪архитектуры≫ (имеют одинаковую
архитектуру набора команд
).
Каждая машинная инструкция выполняет определённое действие, такое как операция с данными (например,
сложение
или копирование
машинного слова
в
регистре
или в
памяти
) или переход к другому участку кода (изменение порядка исполнения; при этом переход может быть
безусловным
или
условным
, зависящим от результатов предыдущих инструкций). Любая
исполнимая программа
состоит из последовательности таких атомарных машинных операций.
Операции, записываемые в виде одной машинной инструкции, можно разделить на ≪простые≫ (
элементарные операции
) и ≪сложные≫. Кроме того, большинство современных процессоров состоит из отдельных ≪исполнительных устройств≫ ? вычислительных блоков, которые умеют исполнять лишь ограниченный набор простейших операций. При исполнении очередной инструкции специальный блок процессора ? декодер ?
транслирует
(декодирует) её в последовательность элементарных операций, понимаемых конкретными исполнительными устройствами.
Архитектура набора команд
процессора определяет, какие операции он способен выполнять, и какой машинной инструкции какие числовые
коды операций
(опкоды) соответствуют. Опкоды бывают постоянной длины (у
RISC
-,
MISC
-архитектур) и диапазонной (у
CISC
-архитектур; например: для архитектуры
x86
команда имеет длину от 8 до 120 битов).
Современные
суперскалярные процессоры
способны выполнять несколько машинных инструкций за один
такт
.
Машинный код можно рассматривать как примитивный
язык программирования
или как самый низкий уровень представления
скомпилированных
или
ассемблированных
компьютерных программ. Хотя вполне возможно создавать программы прямо в машинном коде, сейчас это делается редко в силу громоздкости кода и трудоёмкости ручного управления ресурсами процессора, за исключением ситуаций, когда требуется экстремальная
оптимизация
. Поэтому подавляющее большинство программ пишется на
языках более высокого уровня
и транслируется в машинный код
компиляторами
. Машинный код иногда называют
нативным кодом
(также
собственным
или
родным кодом
? от
англ.
native code
), когда говорят о платформенно-зависимых частях языка или библиотек.
[2]
Программы на
интерпретируемых языках
(таких как
Basic
или
Python
) не транслируются в машинный код; вместо этого они либо исполняются непосредственно
интерпретатором
языка, либо транслируются в псевдокод (
байт-код
). Однако интерпретаторы этих языков (которые сами можно рассматривать как процессоры), как правило, представлены в машинном коде.
В некоторых
компьютерных архитектурах
поддержка машинного кода реализуется ещё более низкоуровневым слоем программ, называемых
микропрограммами
. Это позволяет обеспечить единый интерфейс машинного языка у всей линейки или семейства компьютеров, которые могут иметь значительные структурные отличия между собой, и облегчает перенос программ в машинном коде между разными моделями компьютеров. Примером такого подхода является семейство компьютеров
IBM System/360
и их преемников: несмотря на разные
шины
шириной от 8 до 64 бит и выше, тем не менее, у них общая архитектура на уровне машинного языка.
Использование слоя микрокода для реализации
эмулятора
позволяет компьютеру представлять архитектуру совершенно другого компьютера. В линейке System/360 это использовалось для переноса программ с более ранних машин IBM на новое семейство ? например, эмулятор IBM 1401/1440/1460 на IBM S/360 model 40.
Абсолютный код
(
англ.
absolute code
) ? программный код, пригодный для прямого выполнения процессором
[1]
, то есть код, не требующий дополнительной обработки (например,
разрешения ссылок
между различными частями кода или привязки к адресам в памяти, обычно выполняемой
загрузчиком программ
). Примерами абсолютного кода являются исполнимые файлы в формате
.COM
и загрузчик ОС, располагаемый в
MBR
. Часто абсолютный код понимается в более узком смысле как позиционно-зависимый код (то есть код, привязанный к определённым адресам памяти).
Позиционно-независимый код
(
англ.
position-independent code
) ? программа, которая может быть размещена в любой области памяти, так как все ссылки на ячейки памяти в ней относительные (например, относительно
счётчика команд
). Такую программу можно переместить в другую область памяти в любой момент, в отличие от
перемещаемой программы
, которая хотя и может быть загружена в любую область памяти, но после загрузки должна оставаться на том же месте.
[1]
Возможность создания позиционно-независимого кода зависит от архитектуры и системы команд целевой платформы. Например, если во всех инструкциях перехода в системе команд должны указываться абсолютные адреса, то код, требующий переходов, практически невозможно сделать позиционно-независимым. В архитектуре
x86
непосредственная адресация в инструкциях работы с данными представлена только абсолютными адресами, но поскольку адреса данных считаются относительно
сегментного регистра
, который можно поменять в любой момент, это позволяет создавать позиционно-независимый код со своими ячейками памяти для данных. Кроме того, некоторые ограничения набора команд могут сниматься с помощью
самомодифицирующегося кода
или нетривиальных последовательностей инструкций.
Программа ≪
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
Данная программа работает при её размещении по смещению 100
16
. Отдельные инструкции выделены цветом:
- BB 11 01
,
B9 0D 00
,
B4 0E
,
8A 07
? команды присвоения значений регистрам.
- 43
?
инкремент
регистра BX.
- CD 10
,
CD 20
? вызов программных
прерываний
10
16
и 20
16
.
- E2 F9
? команда для организации цикла.
- Малиновым
показаны данные (строка ≪Hello, world!≫).
Тот же код
ассемблерными командами
:
XXXX:0100
mov bx, 0111h
; поместить в bx смещение строки HW
XXXX:0103
mov cx, 000Dh
; поместить в cx длину строки HW
XXXX:0106
mov ah, 0Eh
; поместить в ah номер функции прерывания 10h
XXXX:0108
mov al, [bx]
; поместить в al значение ячейки памяти, адрес которой находится в bx
XXXX:010A
inc bx
; перейти к следующему байту строки (увеличить смещение на 1)
XXXX:010B
int 10h
; вызов прерывания 10h
XXXX:010D
loop 0108
; уменьшить cx на 1 и, если результат≠0, то перейти по адресу 0108
XXXX:010F
int 20h
; прерывание 20h: завершить программу
XXXX:0111
HW db 'Hello, World!'
; строка, которую требуется напечатать
|
---|
Общие понятия
| |
---|
Типы кода
| |
---|
Стратегии компиляции
| |
---|