Машинный код
Машинный код (платформенно-ориентированный код), машинный язык — система команд (набор кодов операций) конкретной вычислительной машины, которая интерпретируется непосредственно процессором или микропрограммами этой вычислительной машины. [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.
Абсолютный и позиционно-независимый код
Абсолютный код (англ. absolute code ) — программный код, пригодный для прямого выполнения процессором [1] , то есть код, не требующий дополнительной обработки (например, разрешения ссылок между различными частями кода или привязки к адресам в памяти, обычно выполняемой загрузчиком программ). Примерами абсолютного кода являются исполнимые файлы в формате .COM и загрузчик ОС, располагаемый в MBR. Часто абсолютный код понимается в более узком смысле как позиционно-зависимый код (то есть код, привязанный к определённым адресам памяти).
Позиционно-независимый код (англ. 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. Отдельные инструкции выделены цветом:
- 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≠0, то уменьшить cx на 1 и перейти по адресу 0108 XXXX:010F int 20h ; прерывание 20h: завершить программу XXXX:0111 HW db 'Hello, World!' ; строка, которую требуется напечатать
См. также
- Язык ассемблера
- JIT-компиляция
Примечания
- ↑ 123 Толковый словарь по вычислительным системам = 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). Архивировано из первоисточника 30 мая 2012.Проверено 27 марта 2012.
9.Что такое машинный код?
Команды, поступающие в процессор, являются совокупностью нулей и единиц, т.е. числами, поэтому программа представляет собой последовательность чисел, называемую машинным кодом.
Язык самой машины – машинный код – очевиден и однозначен для каждого вида компьютеров. Но эта последовательность нулей и единиц противоестественна для памяти человека, хотя несколько поколений программистов работали только в машинных кодах. Программа может состоять из миллионов комбинаций единиц и нулей, и ошибка лишь в одном знаке приведет к неправильной работе всей программы. При всех различиях языков программирования все они, в конечном счете, сводятся к языкам высокого и низкого уровня. «Низкий» не значит «плохой». Операторы такого языка близки к машинному коду. К ним относятся языки ассемблера, в которых двоичные последовательности были заменены символами (мнемониками). Первым таким языком был ассемблер компьютера «Эдсак», созданный в 1949 г. английским математиком М. Уилксом. Разумеется, ассемблеры проще машинных кодов, в них можно создавать инструкции для определенных действий. Однако применение ассемблера оставляет нерешенными ряд задач:
-во-первых, программирование на языке ассемблера требует хорошего знания архитектуры машины, на которой программа будет выполняться. Это значительно сужает круг потенциальных разработчиков программного обеспечения. Например, для разработки программного обеспечения для решения экономических задач программист должен одинаково хорошо разбираться как в предметной области, так и в архитектуре компьютера; наладить совместную работу двух разных людей, каждый из которых является специалистом в одном из этих вопросов, значительно сложнее;
-во-вторых, как следствие, низкий уровень языка вынуждает программиста мыслить не категориями предметной области, а в терминах ячеек памяти, индексных и базовых регистров и т.п.;
-в-третьих, язык ассемблера вследствие жесткой привязки к архитектуре определенного компьютера делает программы
непереносимыми: на другой тип компьютеров, делает непригодными все ранее разработанные программы, поскольку новый компьютер имеет другие мнемоники и формат команд, другие методы адресации аргументов и т.п. Кроме того, переучивание программистов на новую систему команд также потребует определенного времени, что делает переход на другую архитектуру еще более трудным
11.Что такое транслятор
Ограниченность ассемблеров была преодолена в языках высокого уровня. Первым распространенным языком высокого уровня явился Фортран, разработанный в 1954-1957 гг. Дж. Бекусом в фирме IBM и до сих пор применяемый для научных расчетов. Поскольку его применение занимало много времени «тихоходных» в то время машин, для него был создан компилятор, переводивший его программы в машинный код. Это положило начало особым видам программ – трансляторам, которые для каждого типа компьютеров переводят программы, написанные на языке высокого уровня, в их машинный код.
Трансляторы бывают двух видов – компиляторы и интерпретаторы
Компилятор транслирует в ходе непрерывного процесса всю программу, написанную на языке высокого уровня. При том создается полная программа в машинных кодах, которую затем ЭВМ выполняет без участия компилятора
Интерпретатор последовательно анализирует по одному оператору программы, превращая при этом каждую синтаксическую конструкцию, записанную на языке высокого уровня, в машинные коды и выполняя их одна за другой. Интерпретатор должен постоянно присутствовать в зоне основной памяти вместе с интерпретируемой программой, что требует значительных объемов памяти. Следует заметить, что любой язык программирования может быть как интерпретируемым, так и компилируемым, но в большинстве случаев у каждого языка есть свой предпочтительный способ реализации. Языки Фортран, Паскаль в основном компилируют; язык Ассемблер почти всегда интерпретирует; языки Бейсик и Лисп широко используют оба способа.
МАШИННЫЙ КОД/ЯЗЫК
(machine code, machine language) Язык, который компьютер может понимать непосредственно. Является основным языком программирования. Каждому действию, инструкцию о выполнении которого может получить процессор, соответствует определенное число, обычно выраженное в восьмеричной (octal notation) или Шестнадцатеричная системах счисления (hexadecimal notation). Программа, написанная на машинном языке, представляет собой серию таких чисел с вкраплениями других чисел, являющих собой или параметры, контролирующие действия, или данные, на основе которых эти действия выполняются. Все программы, написанные на языке высокого уровня (high-level language), таком, как БЕЙСИК или КОБОЛ, должны быть до запуска преобразованы при помощи компилятора (compiler) в машинный язык (или же выполняться с использованием интерпретатора (interpreter), который делает аналогичную операцию).
Бизнес. Толковый словарь. — М.: «ИНФРА-М», Издательство «Весь Мир». Грэхэм Бетс, Барри Брайндли, С. Уильямс и др. Общая редакция: д.э.н. Осадчая И.М. . 1998 .
- МАТРИЧНЫЙ ПРИНТЕР
- МАЯЧНЫЙ СБОР
Смотреть что такое «МАШИННЫЙ КОД/ЯЗЫК» в других словарях:
- Машинный код — Эта статья о системе команд в целом; об инструкциях см.: Код операции. Машинный код (платформенно ориентированный код), машинный язык система команд (набор кодов операций) конкретной вычислительной машины, которая интерпретируется… … Википедия
- Язык программирования — Язык программирования формальная знаковая система, предназначенная для записи компьютерных программ. Язык программирования определяет набор лексических, синтаксических и семантических правил, задающих внешний вид программы и действия,… … Википедия
- Машинный язык — Эта статья о системе команд в целом; об инструкциях см.: Код операции (информатика). Машинный код (также употребляются термины собственный код, или платформенно ориентированный код, или родной код, или нативный код от англ. native code) система… … Википедия
- Код операции — Эта статья об инструкциях; о системе команд в целом см.: Машинный код. Код операции, операционный код, опкод часть машинного языка, называемая инструкцией и определяющая операцию, которая должна быть выполнена. Определение и формат кодов… … Википедия
- Язык сценариев — Скриптовый язык (англ. scripting language, в русскоязычной литературе принято название язык сценариев) язык программирования, разработанный для записи «сценариев», последовательностей операций, которые пользователь может выполнять на компьютере … Википедия
- Язык ассемблера — Листинг программы на языке ассемблера Motorola MC6800 (слева идут адреса и машинные коды в шестнадцатеричной системе, вычисленные и сгенерированн … Википедия
- Код операции (информатика) — Эта статья об инструкциях; о системе команд в целом см.: Машинный код. В комьютерной отрасли под кодом операции (также операционный код, опкод англ. operation code) понимают часть машинного языка, называемую инструкцией, определяющую операцию,… … Википедия
- Язык операций 1 — (англ. Transaction Language 1, сокр. TL1) широко используемый в телекоммуникациях протокол. Это общий для производителей, технологий человеко машинный язык, широко использующийся для управления инфраструктурой оптического (SONET) и… … Википедия
- Код — I (франц. code, от лат. codex свод законов) система условных знаков (символов) для передачи, обработки и хранения (запоминания) различной информации. Конечная последовательность кодовых знаков называется словом. Число различных символов,… … Большая советская энциклопедия
- Форт (язык программирования) — У этого термина существуют и другие значения, см. Форт (значения). Forth Семантика: императивный Тип исполнения: интерпретатор/компилятор Появился в: 1971 Автор(ы): Чарльз Х. Мур Основные реализации … Википедия
Как написать «Hello World» на машинном коде?
Недавно наткнулся на видео, где некий сумасшедший написал программу, которая выводит в консоль слова «Hello World» на бинарном/машинном коде (если честно я не уверен что это именно).
Расскажите пожалуйста, как можно повторить результат (не советуйте скопировать код из видео, хочу именно понимать как такое сделать)? Может какая-то литература по этому поводу?
- Вопрос задан более трёх лет назад
- 32512 просмотров
Комментировать
Решения вопроса 1
Вам достаточно изучить ассемблер и всё станет понятно.
Каждая команда ассемблера транслируется «дословно» в машинный код.
Т.е. например команда pushl %edx превратится в один байт 82
Например программа на ассемблере:
push %ebp mov %esp,%ebp call 0x8048298 cmp $0x41,%eax jne 0x80483ce push $0x80484b0 call 0x80482c8 add $0x4,%esp mov $0x0,%eax mov %ebp,%esp pop %ebp ret
превратится в машинный код:
0x55 0x89 0xe5 0xe8 0xfc 0xff 0xff 0xff 0x83 0xf8 0x41 0x75 0x0d 0x68 0x00 0x00 0x00 0x00 0xe8 0xfc 0xff 0xff 0xff 0x83 0xc4 0x04 0xb8 0x00 0x00 0x00 0x00 0x89 0xec 0x5d 0xc3
Почитать можно здесь и здесь . В целом подойдет любая книга по ассемблеру.
Ответ написан более трёх лет назад
Во времена MSDOS было бы понятно — int 21h, и вывод на консоль в кармане. Можно даже структуры exe-файла не знать, писать сразу в com. А сейчас что делать? Поможет ли ассемблер?
Mrrl: Не понял ваш вопрос. На чистом асме писать нет смысла — только для общего развития или для векторизации SIMD инструкций и для реверс инжиниринга. Если нужен асм, то самый простой способ — делать вставки в код на С/С++. А трансляцией в машинный код должен заниматься компилятор
asd111: Я так понял, что вопрос — как написать программу полностью. Желательно, в 16-ричном редакторе. Любая программа, использующая C/C++ займёт огромный объём, без ошибок вручную его не сгенерируешь и не введёшь. Для com-файла в MSDOS такие трюки были вполне реальны, но как это сделать в современных операционных системах?
Mrrl: В современных системах даже если писать всё вручную, меньше чем код на С в любом случае не получится, т.к. необходимо сохранить формат исполняемого файла т.е. для Linux например нужно будет прописать все заголовки ELF файла в то время как С — по сути дела высокоуровневый ассемблер, т.е. код на С практически дословно транслируется в код на ассемблере + готовые заголовки под нужную ОС + оптимизации компилятора.
asd111: Не забывайте, что если вы пишете на С, то вам будет необходимо иметь правильную версию C-библиотеки, а она тоже занимает место (и в какой-нибудь Embedded XP её может сразу не оказаться). Либо использовать статическую линковку, что очень резко увеличит размер кода. Системные вызовы в этом смысле экономнее. Судя по кодам для Linux, у них есть команда syscall (тоже какое-то прерывание?), которая позволяет написать совсем короткую программу. Про ELF-файл пока не скажу, с исполняемыми файлами для Linux мне разбираться пока не пришлось.