- •Системное программирование на макроассемблере 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
- •Неразрешённые внешние ссылки
- •Выполнение работы
- •Программные инструменты для работы
- •Изготовление файлов для сравнений
- •Восстановление структуры двоичного представления объектного файла
- •Анализ неразрешенных внешних ссылок в объектном файле
- •Состав отчета по работе
- •Исполнение программы под отладчиком
- •Оперативная память «физическая» и виртуальная
- •Выполнение работы
- •Подготовка текстовых файлов для работы
- •Исследование структуры ехе-файла
- •Исследование выполнения программы под отладчиком
- •Карта размещения программы в виртуальной оперативной памяти
- •Действительные ссылки, бывшие раньше неразрешенными
- •Состав отчета по работе
- •Вопросы для самопроверки
- •Рекомендованная литература
Макроконстанты
Макроконстанта определяется с помощью ключевого слова EQU(от слова equivalence – равносильно). Например
Oneequ2*3
Usernameequ1024/8
Понимать это нужно так: макрогенератор строку «One» везде заменит на результат вычисления выражения 2*3, а строку «Username» - на результат вычисления выражения 1024/8. Единожды определив такие числовые макроконстанты, переопределить их потом нельзя. Замены имён макроконстант на строки-значения производятся в исходном тексте в строках, расположенных ниже определения. Поэтому макроконстанты нужно определять в самом начале asm-файлов.
Макропеременные и макровычисления
Макропеременные могут быть только целочисленными. Они создаются на период компиляции с помощью операции = (знак равенства). Значение константы в процессе компиляции можно переопределять сколько угодно раз. Например
MyVar = 10
Это переменные, с которыми работает компилятор ML как любое приложение работает со своими переменными. Компилятор может в процессе трансляциивыполнять много вычислительных операций. В том числе можно программировать циклы, проверки условий. Рассмотрим некоторые примеры.
Создание в секции данных описания числового массива из десяти квадратов первых десяти целых чисел.
.data
A=1
Massiv Label Word
Repeat 10
Dw A*A
A = A+1
Endm
Макрогенератор создаст следующее:
.data
A=1
Massiv Label Word
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Dw A*A
A = A+1
Вы спросите – а где же тут обещанные вычисления?! А они выполнятся в период трансляции. Здесь же мы наблюдаем работу только макрогенератора, а он, как говорилось выше, манипулирует только текстами.
В макроязыке описано много разных типов операторов периода компиляции, здесь нет ни места, ни особой необходимости описывать их все, при необходимости найдете необходимое в учебнике В.Юрова [1], либо спросите у Гугла. Последний пример – записать через цикл операторы сохранения в стек регистров, чьи имена заканчиваются на X:
irpc rg, ABCD
push rg&X
endm
Как именно работает этот пример, рассмотрим в разделе 3.3.
Увидеть работу макрогенератора
Если обработать исходный asm-файл вызовом компилятора ML с ключом /EP, то компилятор собственно трансляцию в машинные коды проводить не станет, выполнится только работа макрогенератора (препроцессора). Изменённый макрогенератором исходник компилятор ML будет выводить на стандартный вывод, т.е. на экран консоли. Читать можно, но неудобно. Мы же вполне можем его перенаправить в файл командой > наш_файл.какое_хотим_расширение. Потом этот файл тихо-спокойно откроем в редакторе и будем читать, сколько захочется. Получится консольная команда вроде такой:
ML /ep myfile.asm > myfile.LST
Здесь выводному файлу мы заказали расширение LST («листинг»). Можно какое хотите, но это всё равно будет текстовый файл.
Расширенный листинг
Существует и другой способ увидеть «развёрнутые» макросы – это создать при компиляции (параллельно с ней) так называемый расширенный листинг программы. Для этого в вызове компилятора следует дополнительно задать ключи /Fl[имя_файла_листинга] /Sa.
Компилятор строит расширенный листинг (назовем его для краткости ELST – “extended listing”) так. Он просматривает исходный текст сверху вниз. Каждая строка исходного текста переносится в ELST «как есть». Если эта строка является макровызовом, то ниже вставляются строки макрорасширения. Они метятся слева числом – уровнем вложенности макрорасширения.
Если строка исходника или вставленная строка макрорасширения является командой, то она компилируется. Что положено - пишется в объектный файл.obj. В ELST откомпилированная строка записывается в формате
Расширенный листинг, в принципе, дает полное представление о результатах работы компилятора. Для более полного представления приведем еще один фрагмент расширенного листинга.
1 2 3
---------┴----------------┴--------------------------
00000000 A1 00000000 R Mov EAX, Num1 ; 11223344
00000005 8A 15 0000001A R Mov dl, [Str2 + 3] ; J
macrodef EAX, EDX, Num1
1 LOCAL M3
0000000B 8B D0 1 mov EDX, EAX;обычная команда
1 ;с обычным комментарием
0000000D 1 ??0019:
0000000D FF 35 00000000 R 1 push Num1
Обратите внимание на колонку 2. Она содержит объектный код, который впоследствии реально попадает в готовую программу. Строчки, в которых колонка 2 пустая, не порождают объктного кода и служат только пользователю для лучшего понимания программы.
Файл листинга очень информативен, поэтому есть практический смысл хорошенько разобраться с его структурой и содержанием. В «Выполнении работы» этому будет посвящен отдельный пункт.