- •Системное программирование на макроассемблере masm32
- •Содержание
- •Вступление
- •Префиксы «венгерской» нотации типов данных в описаниях вызовов функций аpi Win32 (Win64)
- •Работа с консолью
- •Цель работы
- •Теоретические сведения
- •Консоль
- •Начальные настройки
- •Как в cmd.Exe выделять-копировать-вставлять текст
- •История ввода команд
- •Заменяющие символы в шаблонах имён
- •Выполнение работы
- •Навигация по дискам и папкам
- •Поиск файлов и папок по имени или шаблону
- •Копирование, перенос, переименование и удаление файлов
- •Создание и уничтожение папок
- •Создание текстового файла
- •Просмотр содержимого файлов
- •Поиск файлов, содержащих нужную строку
- •Состав отчета по работе
- •Состав пакета масм
- •Последовательность создания исполняемого ехе-модуля на масм
- •Режимы компоновки
- •Выполнение работы
- •Создание консольной программы
- •Создание программы с графическим интерфейсом
- •Использование шаблона простой программы
- •Состав отчета по работе
- •Параметризация макросов
- •Уникальность меток при макрорасширениях
- •Макроконстанты
- •Макропеременные и макровычисления
- •Увидеть работу макрогенератора
- •Расширенный листинг
- •Выполнение работы
- •Макроопределение и макрорасширение
- •Повторение строк repeat
- •Цикл for
- •Анализ расширенного листинга программы
- •Состав отчета по работе
- •Потоки вывода и ввода
- •Вывод и ввод в консольных приложениях
- •Invoke GetStdHandle,std_output_handle ; манипулятор возвращен в еах, ...
- •InputBuffer db 25 dup (0) ; вводной буфер фрагмент 3
- •Высокоуровневый консольный ввод-вывод с использованием макросов
- •Макрос консольного вывода print
- •Макросыконсольного вводаinput и inkey
- •Преобразование строки в число
- •Inkey "Жду кнопочку."
- •Преобразование числа в строку
- •Выполнение работы
- •Invoke ExitProcess,0 ; выход в Windows
- •Эксперимент 1. Ввод-вывод функциями Win32
- •Эксперимент 2
- •Эксперимент 3
- •Эксперимент 4
- •Состав отчета по работе
- •Последовательное выполнение команд
- •Передача управления в другое место кода
- •Возврат управления в основную программу
- •Метка_к5:
- •Jmp Метка_к5
- •Call метка_процедуры
- •Передача параметров в процедуру
- •Внутренние переменные в процедурах
- •Как компилятор ml.ExEпомогает организовать работу с процедурами
- •Автоматическое создание пролога и эпилога
- •Автоматическое размещение внутренних переменных
- •Повышение надежности и облегчение вызовов – макрос invoke
- •Выполнение работы
- •Invoke ExitProcess,0 ; выход в Windows
- •Неразрешённые внешние ссылки
- •Выполнение работы
- •Программные инструменты для работы
- •Изготовление файлов для сравнений
- •Восстановление структуры двоичного представления объектного файла
- •Анализ неразрешенных внешних ссылок в объектном файле
- •Состав отчета по работе
- •Исполнение программы под отладчиком
- •Оперативная память «физическая» и виртуальная
- •Выполнение работы
- •Подготовка текстовых файлов для работы
- •Исследование структуры ехе-файла
- •Исследование выполнения программы под отладчиком
- •Карта размещения программы в виртуальной оперативной памяти
- •Действительные ссылки, бывшие раньше неразрешенными
- •Состав отчета по работе
- •Вопросы для самопроверки
- •Рекомендованная литература
Передача управления в другое место кода
Представим себе, что в памяти размещена основная программа и подпрограмма (рис. 7.1).
Рисунок 7.1- Основная программа и процедура.
В основной программе последовательно выполняются команды к1, к2, к3 и к4. После этого надо перейти к выполнению команды к31 в процедуре, затем команды к32, к33, к34. Потом хотелось бы вернуться в основную программу и продолжить ее с команды к5.
Рассмотрим пока только переход в процедуру. Ну, если совсем точно, то пока – передачу управления после команды к4 на команду к31.
Если вы поняли предыдущий раздел про последовательное выполнение команд, то вам должно быть ясно следующее. После чтения команды к4 в EIPавтоматически сформировалось значение 137 – это адрес команды к5. Но мы не планируем сейчас выполнять команду к5! Нам нужно заставить процессор сначала прочесть, а потом выполнять команду к31, которая расположена по адресу 334.
Решение этой проблемы очевидно. Нужно заменить в регистре EIP значение 137 на 334!Именно этазамена – это и есть передача управления.
Остается выяснить, как это технически сделать.
Первое, что нам интуитивно ясно – что такая замена сама собой не произойдет. Программист должен что-то написать в программе такое, что и выполнит эту работу. Наверное, соответствующую ассемблерную команду. Но, куда ее писать? Места для неё в коде сейчас нет. После команды к4 сразу идет к5, с которой мы должны продолжить выполнение основной программы после возврата из процедуры. Что делать?
Думать, когда пишешь исходный текст. После команды к4 следовало написать команду передачи управления. А потом уже к5. Значит, при правильном написании наш код должен был бы выглядеть не так, как на рис. 7.1, а как на рис. 7.2.
Рисунок 7.2- Вставка в код КПУ – команды передачи управления.
Итак, программист обеспечивает передачу управления вставкой команды передачи управления. Что же это за команды?
Прямо присвоить в нашем примере регистру EIPзначение 334 командой
Mov EIP, 334
запрещает система команд процессора, в ней прямое присвоение значения регистру EIPне допускается.
Но зато есть целая группа команд, которые непрямо меняют значение EIP. И самая простая из них – команда безусловного перехода «JMPметка».
В нашем случае метка входа в процедуру – этоР55 (числовое значение метки 334). Команда безусловного перехода в исходном тексте будет записана так:
JMP P55
Компилятор превратит эту строку в машинный код
E9 192
Здесь операндом команды является число 192 = 334 – 142, называемое «дистанция перехода».
Стало быть, команда jmpвыполняется следующим образом.
Она читается из памяти в процессор и становится EIP= 142. Далее команда прочитана и переходит в фазу исполнения. Процессор читаетEIP, оно 142, прибавляет к нему дистанцию перехода (она содержится прямо в машинном коде команды и равна 192) и получившееся число 334записывает обратно в регистр EIP. Как видим, число 142 вEIPволшебным образом () заменилось на 334 (а это и есть передача управления) и процессору теперь ничего не остается, как приступать к чтению команды к31, ну и далее по программе. Передача управления реализована.
Почему в машинную команду записывается не адрес перехода, а дистанция перехода? Ответ такой. Это делается для того, чтобы загрузка программы в разное место оперативной памяти (с разного начального адреса) не нарушала работоспособности программы. Фактический адрес передачи управления не задается жёстко, а вычисляется в ходе исполнения команды передачи через дистанцию перехода. Дистанция же перехода при любом начальном адресе остается неизменной, что и решает проблему мобильности программы в оперативной памяти: грузи от любого адреса, работать будет в любом случае.