- •Системное программирование на макроассемблере 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
- •Неразрешённые внешние ссылки
- •Выполнение работы
- •Программные инструменты для работы
- •Изготовление файлов для сравнений
- •Восстановление структуры двоичного представления объектного файла
- •Анализ неразрешенных внешних ссылок в объектном файле
- •Состав отчета по работе
- •Исполнение программы под отладчиком
- •Оперативная память «физическая» и виртуальная
- •Выполнение работы
- •Подготовка текстовых файлов для работы
- •Исследование структуры ехе-файла
- •Исследование выполнения программы под отладчиком
- •Карта размещения программы в виртуальной оперативной памяти
- •Действительные ссылки, бывшие раньше неразрешенными
- •Состав отчета по работе
- •Вопросы для самопроверки
- •Рекомендованная литература
Внутренние переменные в процедурах
Из общего курса программирования вы знаете, что процедуры часто используют для работы внутренние переменные. Например:
void proc56(int par1, int par2){
int x, y;
float *z;
// . . . код процедуры
}
Переменные x,y,zсоздаются в памяти в момент вызова процедурыproc56, живут, пока она выполняется, затем уничтожаются.
Как это практически реализуется? Ведь мы здесь рассматриваем самые реальные физические механизмы работы процессора, выполняющего программу. И на каком бы языке программирования высокого уровня ни была изначально написана программа, в машинных кодах она организована и исполняется всё равно по правилам ассемблера.
Внутренние переменные также размещаются в стеке. Для их размещения резервируются ячейки стека, размещенные ниже базы. Сколько переменных – столько ячеек стека, как правило, по 4 байта.
Само резервирование выполняется предельно просто. Нужно просто сместить указатель стека ESPна нужное количество байт ниже базы. Если нужны три ячейки для трех переменных, то в процедуре после пролога достаточно выполнить
Sub ESP, 12 ; это ESP = ESP – 12;
и резервирование выполнено.
Рассмотрим пример. Предположим, описана процедура
Proc56 PROC num1:DWORD, num2:DWORD
; нужны три внутренних переменных x:DWORD, y:DWORD, z:DWORD
PUSH EBP ; пролог
MOV EBP, ESP
SUB ESP, 12 ; резервирование места под x, y, z
;--------------- Момент А. ----------------
; код процедуры
; . . .
MOV ESB, EBP ; эпилог
POP EBP
RET 8 ; очистить 8 байт стека (параметры) при возврате
Proc56 ENDP
Если изобразить состояние стека в момент А после вызова этой процедуры, то получится картинка как на рис. 7.6.
Рисунок 7.6– Стековый кадр процедурыProc56 в момент А. Видны поля трех внутренних переменныхx,y,z, каждая размером 4 байта (DWORD).
Символическими именами внутренних переменных при исполнении Proc56 будут:
для x – [EBP-4];
для у - [EBP-8];
для z-[EBP-12].
Как компилятор ml.ExEпомогает организовать работу с процедурами
Из рассказанного выше мы могли ясно видеть, что организация правильного вызова процедуры с параметрами и прочими нужностями типа внутренних переменных, а также корректного возврата в основную программу с очисткой стека требуют аккуратности и учета множества деталей.
Отсюда вполне понятно стремление разработчиков пакета MASM32 облегчить практическим программистам работу с процедурами. Хотелось бы сделать так, чтобы программист мог сосредоточиться на смысле решаемой процедурой задачи, а техническое оформление вызовов-возвратов можно было бы возложить на какого-нибудь программного помощника. В качестве такого помощника наилучшим образом выступает компиляторML.EXE. Расскажем, как он нам помогает с процедурами.
Автоматическое создание пролога и эпилога
Предположим, вы описываете в исходном тексте процедуру (для конкретности, пусть ее имя SpendTime, и у неё два параметра, каждый в двойное слово, т.е. оп 4 байта). Список формальних параметров с указанием их типа (т.е. размера) следует помещать в строку заголовка, а в необходимых местах записать команду RET, безо всяких операндов:
SpendTime PROC W:DWORD, S:DWORD
; . . .
; код процедуры
; . . .
RET
SpendTime ENDP
Макрогенератор превратит ваше описание процедуры в следующее:
0000001B SpendTime PROC W:DWORD, S:DWORD
0000001B 55 * push ebp
0000001C 8B EC * mov ebp, esp
; . . .
; код процедуры
; . . .
0000002C C9 * leave
0000002D C2 0008 * ret 00008h
00000030 SpendTime ENDP
Звездочками отмечены строки, которые в текст вставил макрогенератор. Как видим, по смещениям 1Bи 1С записан пролог. По смещению 2Cдобавлена командаleave, которая в точности делаетMOV ESB, EBP /
POP EBP, но одной командой, а не двумя; это – эпилог. Ну, и у командыretпоявился операнд 8, это очищение стека от восьми байт, в которых сидели дваDWORD-параметра.