- •Системное программирование на макроассемблере 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
- •Неразрешённые внешние ссылки
- •Выполнение работы
- •Программные инструменты для работы
- •Изготовление файлов для сравнений
- •Восстановление структуры двоичного представления объектного файла
- •Анализ неразрешенных внешних ссылок в объектном файле
- •Состав отчета по работе
- •Исполнение программы под отладчиком
- •Оперативная память «физическая» и виртуальная
- •Выполнение работы
- •Подготовка текстовых файлов для работы
- •Исследование структуры ехе-файла
- •Исследование выполнения программы под отладчиком
- •Карта размещения программы в виртуальной оперативной памяти
- •Действительные ссылки, бывшие раньше неразрешенными
- •Состав отчета по работе
- •Вопросы для самопроверки
- •Рекомендованная литература
Call метка_процедуры
Она выполняется в два микрошага: первый заносит в стек текущее EIP, а второй передает управление на метку-операнд процедуры.
Никаких проблем с учетом дополнительного смещения тут не имеется. Когда команда CALLвыполняется,EIPуже «стоит» на начале следующей за CALLкомандой. А это и есть команда продолжения основной процедуры после возврата из процедуры. Полный порядок.
Раз EIPвозврата заносится в стек, то для возврата из процедуры как нельзя лучше подходит рассмотренная выше командаRET.
На рис.7.3 показана картинка, подобная рис.7.2, но приведенная в полное соответствие с порядком вызова процедур через CALLи возврата из них черезRET.
На рис. 7.3 показан момент времени, когда только-только произошел переход в процедуруи процессор сейчас начнет читать из памяти команду к31.
Под линейным образом памяти (а) снизу изображена область системного стека программы (б). Пусть вас не смущает то, что стек изображен «вертикально», в то время как память (а) показана «горизонтально». Это разные участки одного и того же виртуального адресного пространства программы и, вообще говоря, физически в нем никаких направлений нет, а имеется только одно логическое направление возрастания адресов. Так что не придавайте направлениям на картинках особого значения, мы должны проявлять способность абстрагироваться от них.
Рисунок 7.3- Состояние памяти и стека непосредственно после перехода в процедуру. Указатель стекаESPуказывает на только что занесенное в стек командойCALLзначение 142, это адрес возврата на продолжение основной программы.
Обратим внимание на то, что заполнение стека производится в направлении убыванияадресов.
Когда происходит выполнение процедуры, есть полная свобода использовать стек – в него можно сколько угодно раз заносить данные и извлекать их из стека. Условие корректного возврата – нужно, чтобы при выполнении RETрегистр-указательESPимел значение 048, то есть указывал бы на ячейку стека с адресом 142.
Этого можно добиться по-разному. Например, контролировать число команд PUSH и POPв процедуре. Если их поровну, то условиеESP=048 будет выполнено. Но такой прием применим лишь для простых процедур. Для сложных процедур это, если честно, не всегда выполнимо. Поэтому применяют другой способ – запомнить адрес адреса возврата (это не тавтология; то есть адрес 048, по которому записан адрес 142) в специально имеющемся для таких целей регистреEBP(ExtendedBasePointer), называемом «указатель базы». Это решение более правильное и применимое всегда.
Чтобы реализовать его, придется в код процедуры внести пару небольших изменений. Теперь первой выполняемой командой процедуры должна быть не к31, а вставлення перед нею команда-пролог
Mov EBP, ESP ; запоминаем адрес адреса возврата
После этого можно «гулять» по стеку куда угодно и сколько угодно. Но перед выполнением RETнужно выполнить команду-эпилог
Mov ESP, EBP ; восстанавливаем адрес адреса возврата.
И возврат на команду к5 произойдет точно.
Запишем всё это уже текстом псевдокода. Картинок нарисовано достаточно, и вы уже, надеемся, разобрались в сказанном.
Итак, вызов процедуры с прологом и эпилогом:
; основная программа.
. . .
К1
К2
К3
К4
Call P55
K5
. . .
; Код процедуры Р55
P55 proc ; заголовок процедуры играет роль метки входа в неё
Mov EBP, ESP ; пролог - запоминаем адрес адреса возврата
К31
К32
К33
К34
Mov ESP, EBP ;эпилог-восстанавливаем адрес адреса возврата.
RET
P55 endp ; завершитель описания процедуры
. . .