Разновидность программы в машинных кодах какой файл

Обновлено: 04.07.2024

Машинный язык , как он используется в машинный код или машинный код , является языком программирования , в котором инструкции , которые должны быть выполнены с помощью процессора определяются как формальных элементов языка. Из - за своей близости к аппаратной , также обычно называют в «Язык программирования компьютера». Объем и синтаксис машинных команд определены в наборе команд и зависят от типа процессора. Машинный язык в основном представлен в виде двоичного кода или упрощен с использованием шестнадцатеричных чисел .

Машина команда является инструкцией к процессору для выполнения операции, например , добавления или сравнения значений. Таким образом, каждое функциональное достижение процессора является результатом выполнения машинного кода, программы на машинном языке.

Программы на машинном языке обычно не создаются непосредственно программистом , а с использованием языка программирования высокого уровня или ассемблера , а машинный код создается только с помощью компилятора или ассемблера . Когда говорят о «программировании на машинном языке», это иногда неправильно относится к программированию на ассемблере. С другой стороны, в случае выполнения интерпретатором машинные команды генерируются при запуске программы или во время выполнения.

Иногда выражения, такие как «машинный код, машинный язык, двоичный код, машинный код, программный код», используются как взаимозаменяемые. Однако они могут иметь два разных значения:

  • Для типизирующего обозначения кода используется как определение синтаксиса. Пример: «Исходный код (для языка программирования XYZ)»
  • Для программного кода конкретной программы. Пример «двоичный код (для программы ABC)»

Оглавление

Машинная программа


«Машинная программа», контексты терминов и синонимов, встречающиеся в лингвистическом употреблении.

Машинные программы используются во всех устройствах с процессором , то есть от мэйнфреймов до персональных компьютеров и смартфонов до встроенных систем в современных стиральных машинах, радиоприемниках или средствах управления в транспортных средствах для ABS или подушек безопасности . На ПК они обычно содержатся в исполняемых файлах .

В Windows исполняемые файлы можно найти в файлах с расширением «.exe» . Во многих других операционных системах исполняемые файлы также управляются без расширения файла и в других форматах. Иногда их называют по-разному, например Б. под z / OS в качестве загрузочного модуля . Во многих встроенных системах или микроконтроллерах определенные машинные программы постоянно находятся в ПЗУ, например Б. загрузчик

Машинные программы могут просматриваться, теоретически также создаваться и изменяться людьми с помощью шестнадцатеричного редактора . Однако на практике машинная программа создается с помощью ассемблера или компилятора с использованием исходного текста соответствующего языка программирования . Машинный код можно преобразовать обратно в формат ассемблера с помощью дизассемблера , но преобразование в язык программирования высокого уровня с помощью декомпилятора имеет серьезные ограничения.

Отличия от языка ассемблера

Программа в машинном коде состоит из последовательности байтов, которые представляют как команды, так и данные. Поскольку этот код трудно читать людям, команды на языке ассемблера представлены более понятными сокращениями, так называемыми мнемониками . Код операции, исходное и целевое поля, а также другая информация в командах может быть отмечена символическими идентификаторами (такими как MOVE, ZIP, LENGTH), возможно, дополненными числовыми значениями, например Б. для индивидуальной спецификации длины, номеров регистров и т. Д.

Формат файла Как это обычно бывает с исходными текстами , программа на ассемблере обычно доступна в виде текстового файла , а машинная программа обычно сохраняется в виде двоичного файла. инструкции Программирование в текстовом формате с последующим переводом в машинный код ассемблером позволяет программисту создавать программы намного быстрее и проще, чем кодирование в машинном коде. Как правило, инструкция ассемблера соответствует ровно одной инструкции в машинном коде, за исключением макроассемблеров , которые могут генерировать несколько машинных инструкций из одной инструкции. Форматы символов Общие ассемблеры позволяют программисту кодировать символы и числа в различных форматах кода (текстовый, десятичный, шестнадцатеричный, восьмеричный, двоичный) и устанавливать их в машинной инструкции в формате, соответствующем инструкции. Пример: спецификации исходного текста 'A' или 'X'C1' 'или' B'11000001 '' (в коде EBCDIC ) означают одно и то же и становятся X'C1 'в машинном коде, что для команд для двойных операций имеет значение +193, соответствует букве «А» для символьных операций. Объявление данных Ассемблер позволяет программисту идентифицировать и называть поля данных как таковые, объявлять их в различных форматах и ​​давать им символические имена. В сгенерированном машинном коде пространство памяти резервируется в соответствии с этой информацией и (в случае констант ) предварительно назначается содержимым. В сгенерированных машинных командах символический адрес заменяется числовым адресом и используется длина определенных полей. обращаясь Ассемблер позволяет именовать места хранения данных и команд символически, так что программисту не нужно знать их числовые адреса. Адреса памяти указываются непосредственно на машинном языке. Даже при небольшом изменении программы адреса всех последующих частей программы будут смещены, что (при программировании на машинном языке) потребует адаптации всех этих адресов. Символьная адресация означает, что подпрограммы также могут вызываться на языке ассемблера , фактический адрес которого используется только в машинном коде ассемблером или компоновщиком . Объем программы Программа на ассемблере обычно связана с одной (1) определенной задачей и не зависит от других программ во время сборки. Используя такие методы, как «связывание» , в зависимости от платформы разработки, результаты нескольких сборок (например, называемых объектными модулями ) могут быть «объединены», что в целом приводит к машинной программе. документация Ассемблер позволяет добавлять к программе комментарии и дополнительную документацию. Как правило, эти части исходного кода не передаются в машинную программу.

Большинство вышеупомянутых аспектов языка ассемблера также применимы аналогичным образом к языкам программирования более высокого уровня, хотя они отличаются от языка ассемблера дополнительными (производительными) функциями.

Создание программы

Внутри каждая команда на машинном языке кодируется с использованием одного или нескольких числовых значений. Эти числовые значения состоят из кода операции , который определяет тип команды, за которым, возможно, следуют один или несколько байтов данных, относящихся к этой команде. Таким образом, программа формирует значимую последовательность таких числовых кодов, хранящихся в основной памяти или в виде файла. Создавать такие программы можно разными способами:

пример

Язык программирования C

В следующем исходном коде на языке программирования более высокого уровня C вычисляется сумма чисел 2 и 3 и возвращается результат:

Такая программа, если бы она была скомпилирована для процессора x86 , могла бы привести к следующему машинному коду:

mov edx , DWORD PTR [ rbp-4 ]
add eax , edx
mov DWORD PTR [ rbp-12 ], eax

int c = a + b ; Установите регистр EAX на значение переменной b .

Установите регистр EDX на значение переменной a .
Добавьте значение EDX к значению EAX.
Установите для переменной c, адресованной RBP, значение EAX.

> Верните RBP к исходному значению.

Вернитесь туда, где был вызван main . Регистр EAX содержит возвращаемое значение.

Компилятор может сгенерировать из этого исполняемый файл вместе с другой необходимой информацией . Для исполнения машинный код загружается в основную память загрузчиком операционной системы. Затем среда выполнения вызывает функцию main (), и ЦП начинает обрабатывать машинные команды.

Машинный код на компьютерах IBM на примере OS / 390

Машинный код создается при сборке или компиляции файлов исходного кода и предоставляется «Редактором связей» , возможно, с добавлением дополнительных модулей , как исполняемая программа в программной библиотеке . Эта программа загружается в основную память для выполнения. Машинный код этих программ содержит смесь команд и данных - как это возможно в компьютерах с архитектурой фон Неймана (в отличие, например, от архитектуры Гарварда ).

Данных создается в соответствии с заданным форматом хранения. Значение «12» может, например, B. иметь следующий вид (шестнадцатеричное представление минимальной длины):

F1F2 Текст или номер без упаковки 012C упакованный позитив, хранение одного полубайта на число, в конце знаковый полубайт. 012D упакованный негатив (dto) 0C двоичный положительный, соответствует B'00001100 '

В случае более длинных полей данных также могут быть начальные нули или, в случае текста, последующие пробелы. Для каждого предоставленного поля данных определяется «адрес», с которого он начинается и где он хранится в соответствии с его длиной и форматом.

Эти команды состоят из кода команды и - в зависимости от команды - параметры различных структур. Следующие примеры показаны в шестнадцатеричном формате . Примеры команд:

C5.1C.92A4.8C2B (точки разделения вставлены только для лучшей читаемости):

C5 = Код команды для CLC = Логический символ сравнения; Сравнение персонажей 1C = длина минус 1 сравниваемых полей (с 00 сравнивается 1 байт и т. Д., Здесь 29 байтов) 92A4 = адрес первого операнда: 9 = базовый регистр, 2A4 = расстояние до регистра 8C2B = адрес второго операнда: 8 = базовый регистр, C2B = расстояние до регистра

47 = Код команды для BC = Переход по условию: Команда перехода, если выполняется условие (из предыдущей команды) 8 = состояние; здесь: если 'равно', мнемонический ассемблерный код BE (ветвление при равенстве) 0 = необязательный регистр, содержимое которого добавляется к адресу перехода; не на "0" B = адрес назначения (базовый регистр) 654 = адрес назначения (расстояние); с содержимым B = 6C4410 произойдет переход к адресу 6C4A64.

В коде ассемблера это кодирование могло бы, например, Б. выглядят так:

CLC FELDA (29), FIELDB БЫТЬ ХХХ

В отличие от этого , исходный код , сгенерированный с помощью высокого уровня языка может быть:

ЕСЛИ Field_A = Field_B, то НАЙТИ XXX.

Если условие выполнено, выполняется переход к XXX (= реальный адрес 6C4A64), в противном случае машинный код <usw> продолжается с . Языки высокого уровня часто генерируют дополнительные команды, например Б. для выравнивания длин полей или форматов данных, загрузка регистров или вычисление адресов в массивах .

Видно, что команды имеют разную длину . Блок управления компьютера распознает длину по первым двум битам кода команды и соответственно переключает регистр подсчета команд . Программа продолжается именно в этой точке - если не нужно выполнять команду перехода.

Адреса памяти всегда представлены в машинном коде одной (или двумя) регистрационной информацией и, необязательно, «расстоянием», указанным в команде. При запуске программы операционная система загружает определенный регистр с адресом, по которому программа была загружена в память. Начиная с этого значения, базовые регистры загружаются в программный код (запрограммированный с помощью ASS, сгенерированный с помощью языков высокого уровня), посредством чего команды, снабженные относительными адресами, адресуют фактические ячейки памяти.

Для выполнения системных функций (таких как команды ввода / вывода , запрос даты / времени, ввод с клавиатуры, загрузка подпрограмм и т. Д.) Все, что требуется, - это системный вызов с командой 'SVC' (вызов супервизора) в машинной программе. . Выполняемая функция указывается во втором байте (см. Каталог); Дальнейшие параметры функции передаются через интерфейс данных, который определен в ее структуре и адрес которого указывается неявно согласованным регистром (не указанным в команде). Пример: X'05 08 '= ЗАГРУЗИТЬ, параметр = Pgm-Name и т. Д. Команды, выполняющие вызываемые функции, являются машинным кодом операционной системы. Они выполняются там, а затем возвращаются к команде, следующей за SVC.

Обзор типичных функций машинного языка

Набор инструкций

Следующие мнемоники (сокращения команд) были выбраны в качестве примера и зависят от языка ассемблера.

Адресация и отображение результатов: Почти все команды адресуют соответствующие позиции памяти (часто источник / цель, значение для сравнения / сравнения и т. Д.) Через определенные регистры . Процессор также возвращает свои результаты и соответствующую дополнительную информацию через определенные регистры и / или через флаги в регистре состояния . Это дает возможность оценить эту информацию и отреагировать на нее в дальнейшем ходе программы. Длина инструкций и размер операндов источника и назначения могут варьироваться в зависимости от архитектуры.

Пример: команда сложения, такая как ADC (сложение с переносом), сигнализирует следующей программной последовательности, что допустимый диапазон значений был превышен за пределы установки флагов переноса и переполнения.

Различия: Набор команд отдельных процессоров отличается. Не все команды доступны для каждого типа процессора и в каждом поколении процессоров.

Пример: простая базовая команда, такая как SHL / SHR , которая сдвигает значение регистра на определенное количество разрядов влево или вправо, уже доступна в 8086. Более мощный вариант SHLD / SHRD , который также заполняет результирующие пробелы из другого целочисленного значения, реализован только с 80386 и далее.

Мощность: набор команд процессора предоставляет команды с разной функциональностью. Помимо простых, одноэтапных базовых операций, также доступны команды, объединяющие несколько операций в одной команде.

Примеры: Команда CMP (сравнение) позволяет сравнивать два значения для <,>, =. Команда XCHG (обмен) меняет местами два операнда. Команда CMPXCHG (сравнение и обмен) объединяет эти две команды и включает условный обмен данными в одной команде. В то время как команда BT (битовый тест) проверяет состояние только одного бита в целочисленном значении, команды BTC, BTR и BTS также позволяют установить проверяемый бит в зависимости от результата теста (BTS) , чтобы очистить его (BTR) или инвертировать (BTC) .

Общее различие делается между процессорами с набором команд RISC - ( компьютер с сокращенным набором команд ) или CISC - ( компьютер со сложным набором команд). Первые имеют значительно менее мощный набор инструкций, но обычно могут обрабатывать каждую отдельную инструкцию за один такт. Современные процессоры с набором инструкций CISC (которые сегодня почти полностью включают x86- совместимые процессоры) декодируют сложные инструкции CISC для более быстрой внутренней обработки на языке RISC-подобного микроконтроллера.

Производительность: каждая команда обрабатывается за определенное количество тактов процессора, указанное в таблицах данных . Знание этого позволяет программисту (в чрезвычайно критичных по времени приложениях), например, заменять команды с большим количеством тактовых циклов несколькими, но в целом более эффективными командами.

Категоризация команд

Базовые машинные команды можно разделить на следующие категории:

  • Арифметические операции: выполнение вычислений (ADD, ADC, SUB, SBB, DIV, MUL, INC, DEC)
  • Логические операции: логически связать битовые поля друг с другом ( AND , OR , XOR , NOT )
  • Бит-ориентированные операции: с их помощью можно адресовать отдельные биты в битовом поле, прочитать (BSF, BSR) , сдвинуть (SHL, SHR, RCL, RCR, ROL, ROR) или манипулировать (BT, BTC, BTR).
  • Операции с памятью: передача данных между регистрами процессора (MOV, MOVSX, MOVZX, XCHG) внутри регистра (BSWAP) , а также между регистрами и памятью
  • Операции сравнения: сравнение значений с использованием <,> и = (CMP, TEST)
  • Комбинированные команды из операций сравнения, арифметических операций и обмена данными (XADD, CMPXCHG)
  • Управляющие операции: ветви, влияющие на ход программы.
  • Преобразование данных: эти команды преобразуют значения из одного представления в другое, возможно, с убытком. Например: байт в слове (CBW) , длинное целое число в байте ( CVTLB ) или двойное точное число с плавающей запятой в целом числе ( CVTSD2SI ).

Во многих современных процессорах инструкции машинного языка, по крайней мере, более сложные, реализуются внутри микропрограммами . Это особенно верно в случае архитектуры CISC .

литература

  • Ассемблер - программирование на уровне машины с самого начала . Ророро в мягкой обложке № 61224 (2003), ISBN 3-499-61224-0 .

веб ссылки

Викисловарь: машинный язык - объяснение значений, происхождение слов, синонимы, переводы 35672 = 3*10<sup>4</sup> + 5*10<sup>3</sup> + 6*10<sup>2</sup> + 7*10<sup>1</sup> + 2*10<sup>0</sup> (1)

Чтобы набрать число 35672 мы должны передвинуть влево две "костяшки" на первом "прутике", 7 на втором, 6 на третьем, 5 на четвертом и 3 на пятом. (У нас ведь 1 "костяшка" на втором - это то же самое, что и 10 "костяшек" на первом, а одна на третьем равна десяти на втором, и так далее. ) Пронумеруем наши "прутики" снизу вверх - да так, чтобы номером первого был "0". И снова посмотрим на наши выражения:

Это (если сверху вниз считать) сколько на каждом "прутике" "костяшек" влево отодвинуто.

Это номер прутика (самый нижний - 0), на котором отодвинуто определенное число костяшек.

Это на каждом прутике - по 10 костяшек нанизано, не все влево отодвинуты, но всего-то их - 10!
Кстати, красненькое 10 в последнем выражении соответствует основанию (radix) системы счисления (number system).

Если же основание системы счисления больше десяти, то есть больше, чем десять привычных нам чисел, то начинают использоваться буквы английского алфавита. Например, для обозначения чисел в системе счисления с основанием 11 "как цифра" будет использоваться буква А:

В системе счисления с основанием 16 - буквы от A до F:

Правда, при определенном основании (при каком?) буквы аглицкого алфавита закончатся.
Но нам это, пока что, глубоко фиолетово, так как работать мы будем только с тремя radix-ами: 10 (ну естественно), 16 и 2. Правда, если кто на ДВК поизучать это дело собирается, тому еще и radix 8 понадобится.

Если же мы используем символы 123 для представления, например, шестнадцатеричного числа, то подразумеваем следующее:

Короче - полный беспредел. Говорим одно, а подразумеваем другое. И последнее не для красного словца сказано. А потому, что так оно и есть.

Истина где-то рядом.

radix 10 0123456789101112131415
radix 16 0123456789ABCDEF
radix 2 0 1 10 11 100 101 110 111 1000 1001 1010 1011 1100 1101 1110 1111

Следуя этой таблице, число 5BC в шестнадцатеричном формате "строится" так:

+ 11 раз 16 (10 - потому что по таблице B как бы равно 11)

А теперь, если пораскинуть мозгами, с легкостью переведем 5BC из шестнадцатеричной в десятичную систему счисления:

Вот и объединили цифры с буквами. Пространство со временем поучимся объединять немного позже - если не испугаетесь сложностей низкоуровневого программирования.
В общем-то решать вам. В Delphi тоже много чего объединять можно.

А вот и обратный процесс - перевод из HEX в DEC числа A7B8h:

Или использовать родные цифры в десятичной системе счисления, но по другому "вектору упорядоченных цифр" - 1324890576:

Правда, этим немножко затрудняется понимание происходящего? А ведь тоже десятичная система! И рисунок цифр как бы знакомый ))
Или вообще считать в 256-ричной системе счисления, используя в качестве "рисунка цифр" таблицу ASCII-символов! (По сравнению с вами, извращенцами, любой Биллгейтс будет девственником казаться!!).

Каждой шестнадцатеричной цифре соответствует тетрада (4 штуки) ноликов и единичек. Все, что потом нужно сделать - "состыковать" эти тетрады. Круто? Вас еще не то ждет!

. но это так. кстати.

AX=0000 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=18B2 ES=18B2 SS=18B2 CS=18B2 IP=0100 NV UP EI PL NZ NA PO NC

Точно так же присвоить значение 78h регистру AH можно двумя способами:

То же самое, но для регистра AL:

выбросит вам на монитор

Введите после двоеточия, например, число 123 и снова нажмите на Enter:

На дисплее опять появится приглашение "-", на которое мы отвечаем командой "R" без параметров и таким образом вновь просматриваем значения наших регистров:

AX=0123 BX=0000 CX=0000 DX=0000 SP=FFEE BP=0000 SI=0000 DI=0000 DS=18B2 ES=18B2 SS=18B2 CS=18B2 IP=0100 NV UP EI PL NZ NA PO NC 18B2:0100 6A 00 68 4B 01 66 83 7E-E0 00 74 05 B8 4C 01 EB j.hK.f. 18B2:0110 03 B8 4A 01 2B D2 52 50-57 FF 36 C4 34 00 A1 18 ..J.+.RPW.6.4. 18B2:0120 F7 7F 83 C4 12 56 9A 16-44 F7 7F FF 76 FE 9A 59 . V..D. v..Y 18B2:0130 04 8F 17 B8 FE FF 1F 5E-5F C9 CA 06 00 90 C8 54 . ^_. T 18B2:0140 04 00 57 56 8B 76 04 33-C0 89 46 D6 B9 0B 00 8D ..WV.v.3..F. 18B2:0150 7E D8 16 07 F3 AB 89 46-BC B9 0C 00 8D 7E BE F3 18B2:0160 AB 9A 21 9C 8F 17 89 46-FA A1 08 01 8E 46 06 26 . F. F.& 18B2:0170 39 44 02 0F 84 55 01 C7-46 BC 1A 00 C4 5E 0C 26 9D. U..F. ^.&
  • 0:417 - два байта разрядов состояния клавиатуры. Они активно используются ROM-BIOS для управления интерпретаций действий клавиатуры. Изменение этих байтов изменяет значение нажатых клавиш (например, верхний или нижний регистр).
  • 0:41A - cлово по этому адресу указывает на начало буфера BIOS для ввода с клавиатуры, расположенного начиная с адреса 41E. В этом буфере хранятся и ждут обработки результаты нажатия на клавиши. Конец буфера - слово по адресу 41C.
  • 0:43E - байт указывает, необходима ли проверка дискеты перед подводом головки на дорожку. Разряды 0. 3 соответствуют дисководам 0. 3. Если разряд установлен в 0, то необходима проверка дискеты. Как правило, вы можете обнаружить, что разряд установлен в 0, если при предыдущем обращении к дисководу имели место какие-либо проблемы. Например, разряд проверки будет равен 0, если вы попытаетесь запросить каталог на дисководе, на котором нет дискеты, и затем на запрос, появившийся на экране дисплея: "Not ready reading drive B: Abort, Retry, Ignore?" вы ответите: "A".
  • 0:44C (2 байта) - длина регенерации экрана. Это число байтов, используемых для страницы экрана. Зависит от режима.
  • 0:44E (2 байта) - смещение для адреса начала текущей страницы в памяти дисплея. Этот адрес указывает, какая страница в данный момент используется (маленькая, но неприятная подробность - это смещение внутри текущего сегмента видеопамяти, без учета самого сегмента. Например, для нулевой страницы смещение всегда будет равно нулю.)
  • 0:460 (2 байта) - размер курсора, представленный в виде диапазона строк развертки. Первый байт задает конечную, а второй - начальную строку развертки.
  • 0:449 - значение этого байта определяет текущий видеорежим. Для расшифровки требуется целая таблица. Например, 3 - 80-колонный текст, 16 цветов; 13h (19) - 256-цветный графический режим 320x200 и т. д.
  • это - программа;
  • эта программа - программа с корректным выходом.
  • B82301 - внести значение 0123h в AX;
  • 052500 - прибавить значение 0025h к AX;
  • 8BD8 - переслать содержимое AX в BX;
  • 03D8 - прибавить содержимое AX к BX;
  • 8BCB - переслать содержимое BX в CX;
  • 31C0 - очистка AX;
  • CD20 - конец программы. Передача управления операционной системе.
  1. Он пытается интерпретировать данные как код. Соответственно, в процессор "попадает" всякая ерунда.
  2. Вряд ли он натолкнется на последовательность CD 20 вашем тексте . Даже в том случае, если этот код выполнится "успешно" - ваша программа не возвратит управление операционной системе, а пойдет выполняться хлам, содержащийся в оперативной памяти. Как-то - остатки ранее выполненных программ, куски чьих-то данных, интерпретированные как код. и прочая многочисленная ерунда.
  • кодом (т.е. что компьютеру нужно делать) - последовательностью инструкций;
  • данными (т.е. с чем компьютеру нужно выполнять ту или иную работу). Именно данные являются исходной "задачей" и конечным результатом работы процессора.
  • стеком - это область памяти, позволяющая писать реентерабельный/рекурсивный код и служащая для хранения адресов возврата и локальных данных и передачи параметров.
11B7:0100 B82301 MOV AX,0123 ; Внести значение 0123h в AX 11B7:0103 052500 ADD AX,0025 ; Прибавить значение 0025h к AX 11B7:0106 8BD8 MOV BX,AX ; Переслать содержимое AX в BX 11B7:0108 03D8 ADD BX,AX ; Прибавить содержимое AX к BX 11B7:010A 8BCB MOV CX,BX ; Переслать содержимое BX в CX AX=0123 BX=0000 CX=0010 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=0103 NV UP EI PL NZ NA PO NC

Смотрим на значение AX и вспоминаем предыдущую инструкцию - "внести значение 0123h в AX". Внесли? И правда! А в самом низу - код и мнемоника команды, которая будет выполняться следующей.

Вводим команду "T" снова:.

AX=0148 BX=0000 CX=0010 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=0106 NV UP EI PL NZ NA PE NC

AX=0148 - "прибавить значение 0025h к AX". Сделали? Сделали!!

Вводим команду "T" снова:.

AX=0148 BX=0148 CX=0010 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=0108 NV UP EI PL NZ NA PE NC

AX=0148=BX - "переслать содержимое AX в BX". Сделали? Сделали!!

Вводим команду "T" снова:

AX=0148 BX=0290 CX=0010 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=010A NV UP EI PL NZ AC PE NC

"Прибавить содержимое AX к BX". Оно? А то!

Вводим команду "T" снова:

AX=0148 BX=0290 CX=0290 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=010C NV UP EI PL NZ AC PE NC

"Переслать содержимое BX в CX". Сделано!

Вводим команду "T" снова:

AX=0000 BX=0290 CX=0290 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=010E NV UP EI PL ZR NA PE NC
  1. Многочисленными "схемами" компьютера, его устройствами. Например, соответствующее прерывание генерируется при нажатии клавиши на клавиатуре.
  2. Также прерывания генерируются как "побочный продукт" при некоторых "необычных" ситуациях (например, при делении на "букву О"), из которых компьютеру хочешь, не хочешь, но приходится как-то выкручиваться.
  3. Наконец, прерывания могут преднамеренно генерироваться программой, для того чтобы произвести то или иное "низкоуровневое" действие.
  • AH=06h; (_3)
  • AL - число строк прокрутки (0…25) (AL=0 означает гашение всего окна); (_4)
  • BH - атрибут, использованный в пустых строках (00h…FFh); (_5)
  • CH - строка прокрутки - верхний левый угол; (_6)
  • CL - столбец прокрутки - верхний левый угол;
  • DH - строка прокрутки - нижний правый угол;
  • DL - столбец прокрутки - нижний правый угол;
  • выполнив команду INT 10h, мы ВЫПОЛНЯЕМ одну из "функций видео";
  • так как функций видео - много, необходимо УКАЗАТЬ, КАКУЮ именно ФУНКЦИЮ из МНОЖЕСТВА мы хотим ВЫПОЛНИТЬ.
119A:0104 mov ch,10 ;четыре координаты прямоугольника :0100 XOR AL,AL ;ПРИМЕЧАНИЕ: с целью экономии пространства и :0102 MOV BH,10 ;времени мы немножко сократили наш DEBUG-й :0106 MOV CL,10 ;машинные коды, соответствующие мнемоническим :010A MOV DL,3E ;А так, конечно, в оригинале первая строка вот <p>&nbsp; Правда, красивые циферки-буковки? Набиваем-набиваем! Если сейчас к вам подойдут недZенствующие приятели/коллеги и посмотрят, что вы тут колупаете, то ни черта не поймут и покрутят пальцем у виска. Привыкайте к этому. Только не говорите им, что пытаетесь сейчас получить Матрицу, ПОТОМУ ЧТО это неправда. А неправда это потому, что сейчас Матрица в очередной раз обманула вас! <p>&nbsp; У вас только первое окно прорисуется, сразу же после чего программа натолкнется на INT 20h и благополучно завершится! А следовательно, и все, что после первого CD 20 написано будет - останется проигнорированным! Исправляйте! (Т.е. уберите все INT 20 КРОМЕ ПОСЛЕДНЕГО). <p>&nbsp; Второй момент. ВОЗВРАЩАЕТ ЛИ это прерывание ЧТО-НИБУДЬ В РЕГИСТР AX? Смотрите описание. Ничего? Ну так какого черта тогда по новой вводить XOR AL,AL и MOV AH,06 и переприсваивать AH значение 6h, если и без того AH = 6h? Один раз ввести - более чем достаточно! <p>&nbsp; Скажите, какая мелочь- байтом больше, байтом меньше! А я скажу вот что - на то он и assembler, <p>&nbsp; - <i>По-новому?</i> - возмутимся мы в свою очередь! - <i>Зачем по-новому? Вы что, с ума сошли?</i> <p>&nbsp; 1. Что вам мешает после команды "a" указать адрес, который вы желаете переассемблировать? И <p>&nbsp; - <i>А что делать, если не переассемблировать нужно, а вообще удалить?</i> <p>&nbsp; 2. Существует куча способов, что вы в самом-то деле! Например, в HEX Workshop с блоками шестнадцатеричных цифр запросто можно работать. Да и в других программах это можно делать - например, в <p>&nbsp; Кстати, если процессор встретит команду NOP, то он просто побездельничает некоторое очень <p>&nbsp; ПРОБУЙТЕ!! В конце концов, ваша прога должна принять такой вот вид: AX=0000 BX=0000 CX=0043 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=0102 NV UP EI PL ZR NA PE NC

Состояние: обнулился регистр AX (первую команду MOV AL,AL мы не видим). Процессор готовится выполнить команду MOV BH,10. Дадим ему это сделать!

AX=0000 BX=1000 CX=0043 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=0104 NV UP EI PL ZR NA PE NC

Состояние - в BX уже внесен код синего цвета, который нам по условию необходимо заменить на красный (т. е. заменить значение регистра BX с 1000h на 4000h).

Вот теперь-то мы и делаем это "на лету":

А действительно ли сделали? Проверим!

AX=0000 BX=4000 CX=0043 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=11B7 ES=11B7 SS=11B7 CS=11B7 IP=0104 NV UP EI PL ZR NA PE NC

Состояние? BH теперь равно 40h! Мы "вклинились" между строчками:

Ну а как делать то же самое с остальными регистрами вы, наверняка, уже и сами догадались.

Очень важно помнить, каким "нездоровым" образом в стеке реализована ОЧЕРЕДЬ -поместить/извлечь. Помните, мы вас предупреждали, что нам нельзя верить на слово? Не верьте! А посему - обязательно убедитесь в истинности/ложности нашего голословного утверждения при помощи следующей программульки:

С очередностью заполнения стека, наверное, все понятно . Я много про абстрактные "блины" загружал. А вот с адреса 114 начинается извлечение из стека. В какой последовательности это делается, вы можете увидеть сами, произведя трассировку этой небольшой проги.

AX=0000 BX=0000 CX=001B DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0100 NV UP EI PL NZ NA PO NC

Анализируем. Прога еще не начала работать, готовится выполниться команда по адресу 100. Делаем ШАГ!

AX=0001 BX=0000 CX=001B DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0103 NV UP EI PL NZ NA PO NC

Анализируем. AX=0001 - значит, команда выполнилась правильно . Следующая команда, по идее, должна поместить 1 в стек.

AX=0001 BX=0000 CX=001B DX=0000 SP=FFFC BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0104 NV UP EI PL NZ NA PO NC

И что? Команда выполнилась, но где мы можем увидеть, что в стек действительно "ушла" единица? Увы, но здесь это не отображается . Проверим потом. Ведь логично предположить, что если эти значения действительно сохранились в стеке, то мы их потом без проблем оттуда извлечем, т.е. если найдем "там" наши 1, 2, 3, 4, 5 - значит все Ок.

А поэтому - дадим программе работать дальше до адреса 114 (не включительно), не вдаваясь в подробный анализ. Что тут анализировать? Если значение регистра AX последовательно меняется от 1 до 5 - значит, команда mov работает. А стек (команда push) проверим потом, как и договорились.

Проехали до адреса 114.

AX=0005 BX=0000 CX=001B DX=0000 SP=FFF4 BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0114 NV UP EI PL NZ NA PO NC

А вот теперь снова анализируем . При следующем шаге выполнится команда, извлекающая некогда "запомненное" значение AX из стека.

Обратите внимание, регистр IP указывает на адрес (114) выполняемой команды. Мы с вами это уже проходили, не так ли?

Поехали дальше!!

AX=0005 BX=0000 CX=001B DX=0000 SP=FFF6 BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0115 NV UP EI PL NZ NA PO NC

Выполнился первый POP. Готовится выполниться второй. AX=5. Т.е., по сравнению с предыдущим шагом, вроде ничего не изменилось. Но на самом деле это не так. AX=5 - эта пятерка "загрузилась" из стека ). В этом вы легко убедитесь, сделав следующий шаг трассировки.

AX=0004 BX=0000 CX=001B DX=0000 SP=FFF8 BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0116 NV UP EI PL NZ NA PO NC

Ууупс. AX=4 . А команда, вроде, та же - POP AX

AX=0003 BX=0000 CX=001B DX=0000 SP=FFFA BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0117 NV UP EI PL NZ NA PO NC AX=0002 BX=0000 CX=001B DX=0000 SP=FFFC BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0118 NV UP EI PL NZ NA PO NC AX=0001 BX=0000 CX=001B DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 DS=14DC ES=14DC SS=14DC CS=14DC IP=0119 NV UP EI PL NZ NA PO NC :0102 MOV CX,0005 ; нижеследующий до команды LOOP кусок повторить CX раз :0105 ADD AX,0001 ; AX=AX+1 (у нас же значение AX на 1 увеличивается. ) :0109 LOOP 0105 ; конец цикла; инициируем повторение; CX уменьшается на 1

Многие любители не испытывают серьезных трудностей в овладении БЕЙСИКом. Для этого достаточно немного практики. Но рано или поздно они приходят к барьеру «машинного кода». Как это ни печально, но некоторые так перед ним и останавливаются. Это ни в коей мере не связано с отсутствием желания или способностей, просто многие не знают, с чего начать. Если в БЕЙСИКе можно начинать с чего угодно (при ошибке компьютер сам Вас поправит), то здесь Вы оказываетесь с процессором один на один, и такой метод проб и ошибок не срабатывает.

Одним словом, есть некий психологический барьер, который бывает трудно преодолеть в одиночку. Известно, что для того, чтобы научиться программировать, надо взять и начать программировать. «ИНФОРКОМ» предлагает Вам следующий компромиссный подход - сначала в рамках этой главы мы, беря «быка за рога», просто начнем программировать, а затем посвятим оставшуюся часть книги систематическому изложению материала.

Итак, давайте напишем первую программу в машинном коде. Прежде всего, выделим для нее область памяти. Если Вы читали нашу книгу "Большие возможности Вашего «ZX-Spectrum`а», то знаете, что для БЕЙСИКа в оперативной памяти компьютера отведена область памяти, начинающаяся с адреса, на который указывает системная переменная PROG и заканчивается адресом, на который указывает системная переменная RAMTOP. Предположим, что Вы хотите записать программу в машинных кодах, начиная с адреса 30000. Дайте команду CLEAR 29999. Эта команда установит RAMTOP в 29999 и Ваша программа будет защищена от возможной порчи из БЕЙСИКа. Даже если Вы дадите команду NEW, области памяти, находящиеся выше RAMTOP, не будут поражены.

Теперь дайте две прямые команды одну за другой:

Мы сейчас записали два числа в нужные нам адреса. Они образуют простейшую программу. Выполнить ее можно командой RANDOMIZE USR 30000. Попробуйте сами. Вам покажется, что ничего не произошло, но это не так. Сначала процессор обратился по адресу 30000 и нашел там число 0, которое обозначает машинный код операции NOP. Операция NOP ( no operation - нет операции) дает команду процессору, что ничего делать не надо. В течение 0,0000014 сек. он действительно ничего не делает, а затем переходит к следующему адресу, где находит число 201.

Если все, что Вы здесь прочитали, Вам понятно, то Вы уже поняли, как составляются программы в машинных кодах. Можно, конечно, возразить, что пользы от такой программы не очень много, но сейчас не в этом суть. Важно, чтобы Вы поняли, что некая последовательность чисел может быть последовательностью команд для процессора Z-80.

К сожалению, для нас мало, что говорит простая последовательность чисел вроде таких, как 0 и 201. Держать в памяти коды всех команд процессора (а их около семисот) непросто, но дело упрощается тем, что есть промежуточный язык между процессором и человеком - язык Ассемблера. У каждого кода есть своя мнемоника Ассемблера. Мнемоника - это набор букв, являющихся сокращением английских слов. Для нашего примера программа на Ассемблере выглядит так:

Перевод этих мнемоник в машинные коды тоже можно поручить компьютеру. Для этого существуют специальные программы, которые тоже называют Ассемблерами. Есть и противоположные программы - Дизассемблеры. Они наоборот переводят машинные коды в мнемоники Ассемблера.

И тех программ и других достаточно много. Часто они объединяются в пакеты. Широко распространены пакеты GENS3/MONS3 фирмы HISOFT и EDITAS / MONITOR 16/48 фирмы PICTURESQUE . Здесь GENS 3 и EDITAS - Ассемблеры, а MONS 3, MONITOR 16 и MONITOR 48 - Дизассемблеры.

Теперь давайте вернемся к нашей первой программе и попробуем ее несколько развить, чтобы она все же что-то делала. Процессор Z-80 имеет несколько регистров, у которых есть имена – «А», «В», «С» и т.д. Каждый из них может содержать одно какое-либо целое число от 0 до 255 (т.е. один байт).

Существуют десятки команд процессора, которые позволяют копировать содержимое регистров из одного в другой, а также выполнять связь с внешним миром, в т.ч. и с оперативной памятью.

Так, например, команда Ассемблера LD B,A (машинный код - 71) означает «загрузить содержимое регистра А в регистр В». LD - это сокращение от LOAD (загрузка).

Точно так же LD C,B (машинный код 72) означает «загрузить в регистр С содержимое регистра В». Можно загружать в регистры и целые числа. Например, LD A, n - означает «загрузить в регистр А целое число n », где n может быть числом от 0 до 255. До этого все команды были однобайтными. Эта же команда - двухбайтная. Сначала идет машинный код - 62, а за ним само число - n . Так, например, LD A, 77 (загрузить в регистр А число 77) будет выглядеть так: 62,77. Здесь 62 - код операции, - он сообщает процессору, что надо сделать, а 77 - это операнд. Заметим здесь же, что бывают операции и трехбайтные и четырехбайтные. Первый байт, как правило, - код операции, а следующие за ним - операнды. Мы говорим «как правило» потому, что есть некоторые операции, код которых записывается двумя байтами [прим.1].

Итак, мы уже готовы к тому, чтобы написать программу, которая будет перебрасывать какое-либо число из одного регистра процессора в другой.

Я пытаюсь прочитать машинный код своего консольного Win32 приложения, написанного в MS Visual Studio:

Часть прочитанных строк являются осмысленными, но большая часть - мусор, среди которого, как я понимаю, должен быть и машинный код программы. Как правильно прочитать exe файл, чтобы получить из него машинный код? __________________
Помощь в написании контрольных, курсовых и дипломных работ здесь

Чтение .exe файла в переменную типа
Мне нужно загрузить файл, который указал пользователь с помощью Диалога, в переменную типа.

динамическое выполнение машинного кода
Есть некий набор ассемблерных команд, переведенный уже в машинный код. Нужно загнать его в память в.

Запуск машинного кода из программы
Подскажите,как запустить машинный код из программы в Delphi.Т.е имеется EXE-файл,который нужно.


Перевод из машинного кода в команду
Здравствуйте. Моя задача- перевести из машинного кода в команду. Мой пример- нужно перевести BB.

Откройте программу обычным блокнотом. Это и будет её машинный код представленный последовательностью печатных ASCII символов. Другое дело, что такое невозможно просто так прочитать и осмыслить. И нужно интерпретировать эту последовательность бит файла другим образом. В начале исполняемых файлов Windows идет структура PE, содержащая всю необходимую информацию и смещения для запуска программы, в Linux свой формат этой структуры - ELF. В любом случае это обширная тема, касающаяся дизассемблеров и кодов машинных команд, и нужно начать с этого. Еще очень желательно хорошо знать язык ассемблера. Я попыталься сделать так, как тут указано. Однако, если щелкнуть правой мышкой на екзешник, то там не появляется пункт open with, а только - run as. И это не дает результат. Попробовал то же самое на йсходник, но там выдает код в том виде как я написал( т.е. По символике с++). Может я что то не понял? paata1963, говорят hex редакторы помогают. Открывать ехе можно из самого редактора кнопкой открыть файл. Или убрать разрешение ехе, тогда по даблклику появится окно выбора программы.

За это, спасибо, розумеется. Но чисто человеческим языком сказать лучше, что я хочу узнать. Вот есть какая та программа и мне надо посмотреть его код, и не только посмотреть но что то изменить в нем. Ну к примеру не нравиться мне мой paint или что то другое. Никак не могу добраться до исполняемого файла. Даже самым написанный екзешник не могу посмотреть. Есть конечно исходник, но если программу перенести на другой компьютер, там же не будет исходника. И если тот человек захочет посмотреть, как он должен поступить без всяких hex редакторов. Лежит же все таки где то в памяти это единство единиц и нолей. Наверное это у меня потому пройсходит, что не до конца довел изучение ассемблера.

Добавлено через 3 минуты
И еще; когда я щелкну " открыть файл: просто запускается программа.

Читайте также: