введение в машинный код

Введение в машинный код

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

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

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

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

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

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

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

Источник

Национальная библиотека им. Н. Э. Баумана
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. Отдельные инструкции выделены цветом:

Источник

Введение в машинный код

Рустэм Галеев aka Roustem

Содержание

1. Введение в машинные коды для Win32

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

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

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

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

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

На рисунке показано взаимоотношение адресуемых частей для регистра EAX; регистры ECX, EDX и EBX имеют подобную же схему. Регистры ESP, EBP, ESI и EDI «включают» в свой состав лишь 16-разрядные SP, BP, SI, DI и не допускают обращения к отдельным байтам.

Как же узнать, к какой именно части регистра происходит обращение, тем более, если коды регистров одни и те же (как в случае EAX, AX и AL)? Эта информация заложена в саму инструкцию. Многие опкоды имеют так называемый бит w, который указывает на размер используемого регистра (или операнда в целом): если он равен 0, это байт, если 1, «полный» регистр. В 16-разрядном режиме бит w обозначает размер операнда 8 или 16 бит. Но современная Windows работает в 32-разрядном режиме, и состояние бита w обозначает размер операнда 8 или 32 бита. Обращение к 16 младшим битам регистра тоже возможно, но для этого используется другая схема с применением префиксов (об этом поговорим в другой раз).

Есть еще два регистра, с которыми придется иметь дело: это регистр флагов EFLAGS и указатель инструкций EIP. Состояние регистра флагов может меняться после каждой инструкции в зависимости от полученного результата; подробнее об этом поговорим в другой раз. Регистр EIP содержит адрес начала следующей инструкции в памяти. Его значение увеличивается каждый раз, когда из памяти извлекается для исполнения очередная инструкция, на величину размера этой инструкции.

Обрабатываемые инструкцией данные могут находиться не только в регистре, но и в памяти, а также входить в состав самой инструкции. При обращении к памяти в инструкции указывается адрес, по которому расположены данные. Рассмотрим различные способы доступа к данным на примере инструкции (а вернее, группы инструкций) перемещения данных, которыми мы будем очень активно пользоваться. На ассемблере группа данных инструкций обозначается мнемоникой MOV.

Начнем с команды, которая перемещает непосредственное значение (являющееся частью самой инструкции) в регистр общего назначения. Формат команды следующий:

Теперь эту же единицу загрузим в старший байт регистра AX (2-й байт EAX): тоже один байт (w=0), но код регистра AH уже другой (100):

Удовольствие составления различных инструкций с данным опкодом оставим вам для самостоятельных упражнений и перейдем к другой команде, которая перемещает данные между памятью и регистром EAX (AX, AL):

А теперь то же значение загрузим в регистр AL (w=0, d=0):

Архитектура IA-32 предоставляет очень богатый набор способов адресации памяти. Сейчас отметим лишь, что возможна еще и косвенная адресация, когда адрес операнда в памяти находится в регистре, а инструкция ссылается на соответствующий регистр. Для работы с такими случаями, а также для перемещения данных между регистрами используется так называемый байт способа адресации (ModR/M). Этот байт следует непосредственно за опкодом, который предполагает его использование, и содержит следующие поля:

Байт ModR/M предполагает, что имеются два операнда, причем один из них всегда находится в регистре (код которого содержится в поле REG), а второй может находиться (в зависимости от значения поля MOD) либо тоже в регистре (при MOD = 11; при этом поле R/M содержит код регистра), либо в памяти (R/M=»register or memory»). В последнем случае адрес памяти, по которому находится операнд, вычисляется следующим образом (см. табл.):

R/MMOD=00MOD=01MOD=10
000[EAX][EAX] + 1 байт смещения[EAX] + 4 байта смещения
001[ECX][ECX] + 1 байт смещения[ECX] + 4 байта смещения
010[EDX][EDX] + 1 байт смещения[EDX] + 4 байта смещения
011[EBX][EBX] + 1 байт смещения[EBX] + 4 байта смещения
100SIBSIB + 1 байт смещенияSIB + 4 байта смещения
1014 байта смещения[EBP] + 1 байт смещения[EBP] + 4 байта смещения
110[ESI][ESI] + 1 байт смещения[ESI] + 4 байта смещения
111[EDI][EDI] + 1 байт смещения[EDI] + 4 байта смещения

Если MOD=01, за байтом ModR/M следует байт, значение которого добавляется к значению соответствующего регистра и таким образом вычисляется адрес операнда. При MOD=10 за ModR/M следуют уже 4 байта; значение этого числа тоже суммируются со значением соответствующего регистра для вычисления адреса.

Присутствие байта ModR/M обычно требует также наличия битов d и w. Рассмотрим еще одну команду:

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

Только не надо пугаться и думать, что при программировании в машинных кодах все время придется делать выбор из сотен возможных вариантов. На самом деле в Win32-программировании постоянно будут встречаться одни и те же инструкции, так что мы их помимо своей воли выучим наизусть. Хотя в этой статье оказалось много разнообразного материала, вы можете считать его одой свободе и богатству выбора, которую несут с собой машинные коды. В будущих статьях мы непременно сможем убедиться, насколько простым может быть программирование под Windows в машинных кодах, особенно если вы сумели уловить логику построения инструкций.

Источник

Введение в машинный код

Вы читали «Хроники Амбера» Роджера Желязны? Там есть такой эпизод:
Главный герой находится в заточении. В абсолютной тьме. У него были выколоты глаза, но за год они регенерировали, и зрение постепенно к нему возвращается.
И однажды каким-то чудом в одной камере с ним оказывается загадочный Дворкин — создатель Лабиринта. Именно «чудом» — он просто появился неизвестно откуда. Он тоже находится «в заключении», но, в отличие от Корвина (главного героя), может спокойно ходить через каменные стены.
Удивленный Корвин спрашивает его:
— Как ты оказался в моей камере? Ведь здесь нет дверей.
Дворкин отвечает:
— Двери есть везде. Просто нужно знать, как в них войти.
Будем считать это эпиграфом.

1.1. Система счисления

#4. Очень наглядно это отображают обыкновенные счеты. Набранное на них число 35672 будет выглядеть. см. рисунок слева в общем.

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

#5. Пальцев на руках у человека 10, поэтому и считать мы привыкли в системе счисления с основанием 10, то есть в десятичной. Если вы хорошо представляете себе счеты и немного поупражнялись в разложении чисел аналогично выражению 1, то перейти на систему счисления с основанием, отличным от привычной, особого труда для вас не составит. Нужно всего лишь представить себе счеты, на каждый прут которых нанизано не привычные 10 костяшек, а. скажем, 9 или 8, или 16, или 32, или 2 и. попробовать мысленно считать на них.

#6. Для обозначения десятичных чисел мы используем цифры от 0 до 9, для обозначения чисел в системах счисления с основанием менее 10 мы используем те же цифры:

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

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

#7. Числа в любой системе счисления строятся аналогично десятичной. Только на «счетах» не с 10, а с другим количеством костяшек.
Например, когда мы пишем десятичное число 123, то имеем в виду следующее:

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

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

#8. Трудность у вас может возникнуть при использовании символов A, B, C и т. д. Чтобы решить эту проблему раз и навсегда, необходимо назубок вызубрить ма-а-аленькую табличку «соответствия» между употребляемыми в «компьютерном деле» систем счисления:

radix 100123456789101112131415
radix 160123456789ABCDEF
radix 201101110010111011110001001101010111100110111101111

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

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

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

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

#12. Теперь самая интересная часть Марлезонского балета.
Компьютер, как известно, считает только в двоичной системе счисления. Человеку привычна десятичная. Так нахрена еще и шестнадцатеричную какую-то знать нужно?
Все очень просто. В умных книжках пишут, что «шестнадцатеричная нотация является удобной формой представления двоичных чисел». Что это значит?
Переведите число A23F из шестнадцатеричной «нотации» в двоичную. (Один из возможных алгоритм приведен в п.10.). В результате длительных манипуляций у вас должно получиться 1010001000111111.
А теперь еще раз посмотрите на таблицу в п. 8. (которую вы как бы уже и выучили) и попробуйте то же самое сделать в уме :

#13. Кстати (наверняка вы это уже знаете):

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

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

А сейчас мы поближе посмотрим на эти «рабочие лошадки» микропроцессора.

Не правда ли, весьма похоже на то, что показывают в художественных фильмах про хакеров?

Природа не терпит пустоты. Писателей приводит в ужас чистый лист бумаги.

Весьма скоро и вы при виде «пустых» регистров будете испытывать непреодолимое наркотическое желание чем-нибудь их заполнить.

Однако прежде чем мы сделаем это в первый раз, давайте уточним тип этих «переменных».

В общем, в умных книжках рисуют вот такую вот «нездоровую» схемку 3 :

А означает она следующее.

Очевидно, что присвоить AX значение, например, 72F9h, мы можем следующими способами:

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

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

Тех, кого смущают числа с буквами, мы со зловредной ухмылкой отсылаем к 1.1. Система счисления :-]

AX2F4D
AHAL2F4D
Значение бита0010111101001101
Номер бита1514131211109876543210
ТетрадыСтаршая AHМладшая AHСтаршая ALМладшая AL

#4. «Принудительно» присвоить регистру значение можно при помощи той же команды «R», только с параметром «имя собственное регистра».

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

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

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

4). «Первый справа» бит мы будем называть «нулевым». Однако нам попадались руководства, в которых это же бит обозван как «первый». Можно долго обсуждать тонкости русского языка (которые, к сожалению, не всегда понимает переводчик), однако это выходит за рамки данной книги. Просто имейте это ввиду, что можете с этим столкнуться, и будьте бдительнее, читая документацию.

Например, команда (параметр L8 означает «вывести 8 байтов»):

покажет вам системную дату в правом столбце дампа.

Итак, у нас есть оперативная память, в которую загружается программа перед ее выполнением (сразу же по нажатию на Enter из Norton Commander). Операционная система, которая, собственно, и загружает программу, сообщает процессору, что надо начать обрабатывать команды, которые в памяти начинаются с такого-то адреса. И здесь первый подводный камень, вернее скала, которую трудно не заметить.

Каким образом? А очень легко! Компьютер «распознает» как выход из программы специальную последовательность байтов. Например, для исполнимых файлов типа com (именно с этим типом файлов мы будем работать на начальном этапе) достаточно последовательности CD и 20.

Пробуем-проверяем? Ну конечно же! Только для этого вам понадобится какой-нибудь шестнадцатеричный редактор, например, HexWorkshop.

Запускать это ваше первое творение лучше из Norton или Volcov Commander (все же это пока что DOS’овская программулька).

Последнее и является единственным, что она пока что может делать (корректно выгружаться из памяти).

Вот и давайте создадим еще одну программу типа com со следующим «шестнадцатеричным содержимым»:

На высоком уровне это делает операционная система. Например, она не пытается загрузить в память для выполнения файлы с расширениями, отличными от COM, EXE и BAT (последний вообще не из этой оперы, но принцип сохраняется).

Почти такой же эффект, но с потенциально большей разрушительной силой может получиться, если управление получит ИСПОРЧЕННЫЙ код, который вроде бы «в основном» правильный, но часть его вместо инициализации переменных и прочих подготовительных действий в лучшем случае ничего не делает, а в худшем портит другой код и данные.

#4. Еще немного идеологии. О программе, которая выполняется в памяти.

Соответственно, и программа состоит из трех частей (сегментов): сегмента данных (data), сегмента кода (code) и сегмента стека (stack).

Оставим пока что «гнилой базар» про смысл словосочетаний «реентерабельный/рекурсивный код» и «адрес возврата». Чтобы не затруднять себе понимание происходящего, мы попытаемся абстрагироваться от всех этих ужасающих вещей и для начала заняться только кодом.

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

В этом вы можете убедиться, загрузив вашу программу myprg_1.com в debug (например, командной строкой

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

#7. Вот что вы должны увидеть:

Возвратившись к #2, перенесем сюда «описание» машинных команд.

Соответственно, вместо шестнадцатеричных кодов мы легко могли вводить эти команды при помощи команды «A» (однако этим мы займемся позже).

Итак, вводим «T» и жмем на Enter!

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

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

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

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

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

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

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

«Очистка AX»? И точно: AX=0000!

Вводим команду «T» снова. И ГРОМКО РУГАЕМСЯ!!

Для тех, кому лень продолжать жать на букву «T», введите для разнообразия команду «G» (от английского GO). На монитор должна вывалиться надпись «Нормальное завершение работы программы».

#9. Только непонятно вот, почему вдруг между int 20 (CD 20) и надписью «Нормальное завершение работы программы» куча всяких «левых» непонятных команд (в том случае, если вы и дальше производили тарассировку, а не воспользовались «халявной» командой «G»)?

А потому, дорогие наши, что вы имели счастье нарваться на прерывание (interrupt)!

Ну, посудите сами, должна же операционная система ну хоть что-нибудь делать!!

Итак, я достаю свой толстый талмуд с описанием прерываний и выбираю, каким бы это прерыванием вас занять на ближайшие 1/2 часа ;).

Ну, например, вот одно симпатичное, под названием «прокрутить вверх активную страницу».

Внимательно читаем описание (и наши комментарии):

Далее представим входные параметры в виде таблички: (_7)

AH06hALЧисло строк
BHАтрибутBLНе имеет значения
CHСтрока (верх)CLСтолбец (верх)
DHСтрока (низ)DLСтолбец (низ)

Плюс подробнейшее толкование, что подразумевается под словом «атрибут» (регистр BH):

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *