- •Системное программирование на макроассемблере 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
- •Неразрешённые внешние ссылки
- •Выполнение работы
- •Программные инструменты для работы
- •Изготовление файлов для сравнений
- •Восстановление структуры двоичного представления объектного файла
- •Анализ неразрешенных внешних ссылок в объектном файле
- •Состав отчета по работе
- •Исполнение программы под отладчиком
- •Оперативная память «физическая» и виртуальная
- •Выполнение работы
- •Подготовка текстовых файлов для работы
- •Исследование структуры ехе-файла
- •Исследование выполнения программы под отладчиком
- •Карта размещения программы в виртуальной оперативной памяти
- •Действительные ссылки, бывшие раньше неразрешенными
- •Состав отчета по работе
- •Вопросы для самопроверки
- •Рекомендованная литература
Вывод и ввод в консольных приложениях
Консольный режим работы приложения характеризуется несколькими особенностями. Во-первых, вывод и ввод имеют исключительно символьный характер (это означает, что нельзя, к примеру, ввести в программу число 94, это будет воспринято как строка «94»). Во-вторых, вывод производится в текущую позицию экрана текстового экрана консоли, с которым в памяти связан экранный буфер консоли. В-третьих, ввод связывается с клавиатурой или, в случае перенаправления, с текстовым файлом.
При консольном выводе прямо или косвенно используется функция WinAPI WriteFile. Вот её формальная спецификация из MSDN:
BOOL WriteFile(
HANDLE hFile, // манипулятор файла
LPCVOID lpBuffer, // указатель на буфер данных
DWORD nNumberOfBytesToWrite, // число байтов для записи
LPDWORD lpNumberOfBytesWritten, //указатель на ячейку для хранения числа
// фактически записанных байтов
LPOVERLAPPED lpOverlapped // указатель на асинхронный буфер,
// обычно это NULL
);
описание которой находится по адресу http://msdn.microsoft.com/en-us/library/ms892380.aspx.
Пример применения этой процедуры для вывода.
.data ; сегмент данных
ZapisanoByte dd 0 ; сколько байт фактически выведено ФРАГМЕНТ 1
AnyString db "Строка для вывода.”,0
DlinaStroki dd 18
PotokStdOut dd ? ; Для записи манипулятора Стд Потока Вывода
.code ; сегмент кода
;Запросить у Windows манипулятор выводного потока ФРАГМЕНТ 2
Invoke GetStdHandle,std_output_handle ; манипулятор возвращен в еах, ...
mov PotokStdOut, eax ; ... и переписан в переменную PotokStdOut
invoke WriteFile, PotokStdOut, ADDR AnyString, DlinaStroki, ADDR ZapisanoByte, NULL
В этом примитивном примере длина строки просто задана значением переменной DlinaStroki. Лучшим решением является ее программное определение. Если строка заканчивается нуль-байтом (строка типа «string-zero»,sz), то схема действий (на псевдокоде) может быть такая:
Установить указатель (например, ЕВХ) на начало строки.
Начальное значение счетчика_символов задать равным 0.
Метка1:
Байт [EBX] равен нуль-байту?
Если да, перейти на метку2. Алгоритм 1.
Увеличить счетчик_символов на 1.
Указатель EBX перенести на следующий символ строки.
Перейти на метку1.
Метка2:
На выходе из этого цикла счетчик_символов содержит длину строки.
При консольном вводе прямо или косвенно используется WinAPI-шная функция ReadFile
BOOL WINAPI ReadFile(
__in HANDLE hFile, // манипуляторвводногопотока
__out LPVOID lpBuffer, // указатель на буфер ввода
__in DWORD nNumberOfBytesToRead, // максимальное количество читаемых байтов
__out_opt LPDWORD lpNumberOfBytesRead, // указатель на переменную,
// куда будет записано количество фактически прочитанных байтов
__inout_opt LPOVERLAPPED lpOverlapped // для ввода с консоли NULL
);
описание которой находится по адресу http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467%28v=vs.85%29.aspx/
Эта функция вводит символы в буфер ввода. Ввод оканчивается нажатием Enter, которое в буфере ввода добавляет в конец введенной строки символыCRиLF(0D0A). Именно поэтому параметр nNumberOfBytesToRead не должен превышать (длину_вводного_буфера – 2), иначе введенная строка с завершающими символами может выйти за пределы буфера.
Заметьте, что получившаяся строка НЕ является sz-строкой. Для превращения ее в таковую (если требуется) символLF(0D) надо обнулить.
Пример применения этой процедуры для ввода.
.data ; сегмент данных