GameHackLab[RU]
    • Категории
    • Последние
    • Метки
    • Популярные
    • Пользователи
    • Группы
    • Зарегистрироваться
    • Войти

    Инструкции ассемблера и регистры процессора

    Запланировано Прикреплена Закрыта Перенесена Базовая информация
    assemblerрегистрыинструкции
    1 Сообщения 1 Posters 599 Просмотры
    Загружаем больше сообщений
    • Сначала старые
    • Сначала новые
    • По количеству голосов
    Ответить
    • Ответить, создав новую тему
    Авторизуйтесь, чтобы ответить
    Эта тема была удалена. Только пользователи с правом управления темами могут её видеть.
    • PromisingP
      Promising
      отредактировано Promising

      В теме рассматриваются простые команды ассемблера, принцип работы и основные регистры процессора


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

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

      Регистры:
      Регистры процессора представляют собой временное хранилище данных для быстрой обработки и вычислений, вычисления большинства команд могут производиться только с регистрами, то есть выражение должно включать в себя регистр. Регистры состоят из частей, например регистр eax вмещает в себя 4 байта, 32 бита и состоит из нескольких частей:

      eb6efdde-8fd7-49ce-bbf0-4ef1392f82bd-изображение.png

      Как показано на этой картинке, регистр eax состоит из первой части, где 16 бит не обозначены отдельным подрегистром, и регистра AX, размером 16 бит, как вы помните (2 байта), который в свою очередь состоит из двух частей по 8 бит (1 байт) AH и Al.
      Данная информация нужна для понимания если вам нужно работать с разноразмерными значениями, но в основном вам будут встречаться значения размером 4 и 8 байт, rax это 64 битная версия регистра eax которая вмещает 8 байт и бывает в 64 битных приложениях.

      Основные регистры следующие, с указанием размера в байтах:

      8   4   2  1  1
      RAX EAX AX AH AL
      RBX EBX BX BH BL
      RCX ECX CX CH CL
      RDX EDX DX DH DL
      RSI ESI SI
      RDI EDI DI
      RBP EBP BP
      RSP ESP SP
      

      В дальнейшем использовать для временного хранения данных вам следует все кроме ebp и esp, так как эти регистры могут использоваться для взаимодействия со стеком, о котором будет рассказано позже.
      Помните что использовать 8 байтовые регистры можно только в приложениях 64 бит. Регистры имеют осмысленные названия, например ESP - Extended Stack Pointer (Расширенный указатель на стек). Расширенный он, грубо описывая, потому что архитектура эволюционировала постепенно, было 16 бит, существовал только SP, разработали 32 бит, добавили ещё 2 байта вперёд и так далее.
      Подробнее про эти регистры можно почитать на английском тут.

      Команды ассемблера:
      Команды ассемблера используются для операций со значениями расположенными в регистрах и памяти приложения.
      Основные команды с синтаксисом Cheat Engine autoassembler которые пригодятся для понимания следующих статей, с примерами:

      mov - переместить (скопировать) данные

      mov eax, A //Поменстить в eax число 10 (A - шестнадцатиричная система)
      mov eax, #10 //Поместить в eax число 10 (#10 - десятичная система)
      mov eax, [адрес] //Переместить значение по адресу 4 байта в регистр eax
      mov [адрес], eax //Переместить значение из регистра eax 4 байта по адресу
      mov ecx, eax //Переместить значение из регистра eax в регистр ecx
      mov [адрес], al ///Переместить значение из регистра al 1 байт по адресу
      
      mov [адрес], [адрес] //Не правильно и работать НЕ БУДЕТ, все двойные операции только с регистрами.
      

      add - добавить

      mov eax, 5
      mov ecx, 4
      add eax, ecx //Добавить ecx к eax, после этого eax = 9
      add [адрес], eax //Добавить к значению по адресу eax 4 байта
      

      sub - вычесть

      mov eax, 5
      mov ecx, 4
      sub eax, ecx //Вычесть из eax ecx, после этого eax = 1
      sub [адрес], eax //Вычесть из значения по адресу eax 4 байта
      

      inc - увеличить на 1
      dec - уменьшить на 1

      inc [адрес] //Увеличить значение по адресу на 1
      dec eax //Уменьшить eax на 1
      

      mul - умножить, использует регистры и операнд. Регистр eax умножается на операнд и результат помещается в eax, остаток помещается в edx

      mov eax, 5
      mov ecx, 4
      mul ecx //Результат, eax = 20, edx = 0
      

      div - разделить, использует регистры и операнд. Значение из двух частей в eax:edx (записывайте edx 0 если хотите делить значение в рамках размерности 4 байт) делится на операнд и результат помещается в eax, остаток помещается в edx

      mov eax, 8
      mov edx, 0
      mov ecx, 4
      div ecx //Результат eax = 2, edx = 0
      
      mov eax, #10
      mov edx, 0
      mov [адрес], 5
      div [адрес] //Результат eax = 2, edx = 0
      

      xor - побитовое исключающее ИЛИ, но для начала достаточно знать что это команда часто используется для обнуления регистров компиляторами, сравнивая их самих с собой, так как она обычно занимает меньше байткода чем например mov eax, 0

      mov eax, 5
      xor eax, eax //eax = 0
      
      mov rax, 8
      xor rax, rax //rax = 0
      

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

      //Допустим адрес = A040D8, значение по адресу 5
      mov eax, [адрес] //eax = 5
      lea eax, [адрес] //eax = A040D8
      

      nop - ничего не делающая инструкция, занимает место 1 байт, или столько, сколько указано, эта инструкция может быть использована для замены на неё других инструкций, что бы отключить их выполнение, в следующих статьях есть примеры.

      nop //Ничего не произошло, занимает 1 байт
      nop 5 //Ничего не произошло, занимает 5 байт
      

      Справочник со всеми командами на английском

      Структура выполнения кода:
      Байткод выполняется последовательно, ассемблерные инструкции тоже. Поток проходит по порядку с инструкции на инструкцию и выполняет их. Его положение может быть изменено с помощью некоторых команд, специальный регистр EIP отображает положение потока, текущий адрес на котором он находится:

      aa3b6288-bc38-4b8c-ab6c-cff0d9e0c83e-изображение.png

      Скриншот из отладчика Cheat Engine. В этом примере можно заметить, слева адрес инструкции, дальше байты инструкции (байткод), а справа интерпретация в виде ассемблерного кода который можно прочитать.
      Инструкция jmp позволяет перемещать поток на определённое количество байт вперёд, или назад. Cheat Engine сам посчитает байты, вам нужно только указать адрес:

      2f6a2069-bde2-424f-b8fc-d600b0c820af-изображение.png

      В этом примере инструкция add eax, ecx выполняться не будет, вместо этого сразу будет выполняться sub eax, ecx.

      Другой пример:

      06ef3446-86fe-46a6-a5aa-8f8c07cce0ec-изображение.png

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

      1 ответ Последний ответ Ответить Цитировать 1
      • Первое сообщение
        Последнее сообщение