- •Системное программирование на макроассемблере 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
- •Неразрешённые внешние ссылки
- •Выполнение работы
- •Программные инструменты для работы
- •Изготовление файлов для сравнений
- •Восстановление структуры двоичного представления объектного файла
- •Анализ неразрешенных внешних ссылок в объектном файле
- •Состав отчета по работе
- •Исполнение программы под отладчиком
- •Оперативная память «физическая» и виртуальная
- •Выполнение работы
- •Подготовка текстовых файлов для работы
- •Исследование структуры ехе-файла
- •Исследование выполнения программы под отладчиком
- •Карта размещения программы в виртуальной оперативной памяти
- •Действительные ссылки, бывшие раньше неразрешенными
- •Состав отчета по работе
- •Вопросы для самопроверки
- •Рекомендованная литература
Макросыконсольного вводаinput и inkey
Макрос input()вызываетсяфункционально, в отличие отprint. Практически это означает, что вызовinput()должен быть операндом выражения, в которое он возвращает вычисляемое им значение. Еще одна особенность функционального синтаксиса – перечисление параметров приводится в скобках, а не списком после имени макроса.
Макрос input()получает с клавиатуры текст, пишет его в автоматически создаваемую строковую переменную и возвращает адрес этой переменной.
mov lpstring, input()
Параметром макроса input() может выступать строка-подсказка для ввода. Эта строка может включать список строк в кавычках и байтов, задаваемых числами:
mov lpstring, input("Введите число ",62," ")
Здесь 62 – это код символа «>».
Преобразование строки в число
Как говорилось выше, консольный ввод-вывод осуществляется исключительно как ввод-вывод текстов. Поэтому, если вы вводите с клавиатуры «94», то это строка из символов «9» и «4», а не число 94, представляемое в памяти в двоичном виде. Поэтому, если нам нужно ввести в программу число94, то это придется делать в два шага: 1) Ввести строку «94», 2) Преобразовать строку «94» в число 94. Для этого существует много макросов вmacros.asm, мы рассмотрим только два.
Функционально вызываемый макрос a2ud() читает строку, задаваемую указателем. Алгоритм считает ее десятичной записью числа, и преобразует ее в числовое значение. Это число пишется в автоматически создаваемую переменную типаDWORD(4 байта). Адрес этой переменной и есть значение, возвращаемое этим макросом:
mov EDX, a2ud(lpNumString) ; в EDX - адрес числа
Второй макрос имеет имя h2ud()и отличается отa2ud()только тем, что рассматривает преобразуемую в число строку как запись числа в 16-ричном формате. Всё остальное совпадает.
Еще одна часто встречающаяся задача ввода – получение одиночного символа нажатием клавиши на клавиатуре. Например, чтобы задержать окно консоли для демонстрации результатов работы программы.
Эту задачу рещает процедурно вызываемый макрос inkeyс необязательным параметром (текст в кавычках и/или байты числами), играющим роль приглашения, вроде «Продолжить по кнопке». Примеры вызовов:
inkey
inkey NULL
Inkey "Жду кнопочку."
Просто inkeyпокажет приглашение «по умолчанию», скорее всего это будет "Press a key to continue ...". Вызовinkey NULL ничего не напишет, буде просто мигать курсором и ждать нажатия. Вызовinkey "Жду кнопочку." выведет текст-операнд и будет ждать кнопки.
Примечание А.Код нажатого символа должен, по замыслу авторов макроса, возвращаться в ЕАХ. Увы, ребята пропустили ошибочку. Не возвращает. Правда, ситуацию легко исправить. Откройтеmacros.asmи найдите в нем код макросаinkey(поиском пользоваться не разучились?) В нем передENDMстоит вызов print chr$(13,10), которым авторы желают выполнить перевод курсора на новую строку. Он-то и портит ЕАХ. Закомментируйте его. Теперьinkeyдействительно будет оставлять код введенного символа в ЕАХ.
Преобразование числа в строку
Числа перед выводом нужно преобразовать в символьную строку, иначе байты числа будут трактоваться при выводе как коды символов и DWORD-число 94 (двоичный код 01011110 00000000 000000000 00000000; мы помним, что физически всё хранится «вывернутым наоборот», то есть здесь слева самый младший байт числа, а самый старший справа) следует трактовать как символ «^» с кодом 94, и следующие за ним три ноль-символа (ноль-символ, 255-символ и 32-символ, это пробел не имеют визуального изображения).
Функционально вызываемый макрос str$(число) возвращает адрес строки, в которую преобразуется число-аргумент. Например
Mov EDX, 1234
print "Вывод десятичного представления числа "
print str$(EDX),13,10
Два вызова printприходится писать потому, что указатель выводимой строки (второй вызов) по его спецификации должен быть только первым операндом. Из примера понятно, чтоstr$() формирует строку, которая показывает число в 10-чном формате.
Второй макрос – hex$() – формирует 16-ричное строковое представление числа. В остальном он аналогиченstr$().
Описанных макросов достаточно для ввода-вывода текстовых и целочисленных данных в учебных задачах нашего курса. Если вас интересуют другие макросы, читайте d:\MASM32\macros\macros.asmи d:\MASM32\help\hlhelp.chm.