Машинный код: различия между версиями
[непроверенная версия] | [отпатрулированная версия] |
м Добавляет шаблон {{Выполнение программы}} |
Yurakum (обсуждение | вклад) отмена правки 140271524 участника 198.163.197.28 (обс.) предположительно, вандализм, модели "48" вообще не значится в списке Метка: отмена |
||
(не показаны 3 промежуточные версии 3 участников) | |||
Строка 1: | Строка 1: | ||
⚫ | |||
{{эта статья|о системе команд в целом|Код операции|об инструкциях}} |
{{эта статья|о системе команд в целом|Код операции|об инструкциях}} |
||
{{нет ссылок|дата=2022-12-11}} |
{{нет ссылок|дата=2022-12-11}} |
||
Строка 67: | Строка 66: | ||
[[Категория:Машинный код| ]] |
[[Категория:Машинный код| ]] |
||
⚫ |
Текущая версия от 16:07, 20 сентября 2024
В статье не хватает ссылок на источники (см. рекомендации по поиску). |
Маши́нный код (платфо́рменно-ориенти́рованный код), маши́нный язы́к — система команд (набор кодов операций) конкретной вычислительной машины, которая интерпретируется непосредственно процессором или микропрограммами этой вычислительной машины.[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!»
[править | править код]Программа «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. Отдельные инструкции выделены цветом:
- BB 11 01, B9 0D 00, B4 0E, 8A 07 — команды присвоения значений регистрам.
- 43 — инкремент регистра BX.
- CD 10, CD 20 — вызов программных прерываний 1016 и 2016.
- 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!' ; строка, которую требуется напечатать
См. также
[править | править код]Примечания
[править | править код]- ↑ 1 2 3 Толковый словарь по вычислительным системам = Dictionary of Computing / Под ред. В. Иллингуорта и др.: Пер. с англ. А. К. Белоцкого и др.; Под ред. Е. К. Масловского. — М.: Машиностроение, 1990. — 560 с. — 70 000 (доп.) экз. — ISBN 5-217-00617-X (СССР), ISBN 0-19-853913-4 (Великобритания).
- ↑ Kate Gregory. Managed, Unmanaged, Native: What Kind of Code Is This? (28 апреля 2003). Дата обращения: 27 марта 2012. Архивировано 30 мая 2012 года.