- •Системное программирование на макроассемблере 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
- •Неразрешённые внешние ссылки
- •Выполнение работы
- •Программные инструменты для работы
- •Изготовление файлов для сравнений
- •Восстановление структуры двоичного представления объектного файла
- •Анализ неразрешенных внешних ссылок в объектном файле
- •Состав отчета по работе
- •Исполнение программы под отладчиком
- •Оперативная память «физическая» и виртуальная
- •Выполнение работы
- •Подготовка текстовых файлов для работы
- •Исследование структуры ехе-файла
- •Исследование выполнения программы под отладчиком
- •Карта размещения программы в виртуальной оперативной памяти
- •Действительные ссылки, бывшие раньше неразрешенными
- •Состав отчета по работе
- •Вопросы для самопроверки
- •Рекомендованная литература
Эксперимент 4
Целью этого эксперимента будет наблюдение кода символа, введенного при исполнении макроса inkey.
Выполните коррекцию макроса inkey, как описано в Примечании А п.6.2.4.3.
Ниже строки inkey "Нажми пробел..."вставьте строки:print str$(EAX),13,10 inkey "Выскочил код пробела 32?"
Сохранить изменения. Распечатать программу в этом состоянии, включить в отчет.
Создать программу консольным вызовом (можно в TotalCommander)buildc cio
Выполнить cio.exe. После вывода «Нажми пробел…» нажмите именно пробел, мы знаем его код (32), убедиться, что всё работает правильно .
Сделать скриншот выполнения эксперимента для отчета.
Состав отчета по работе
Номер и название работы, фамилия и группа студента.
Цель работы.
Протокол выполнения работы со всеми распечатками, скриншотами, комментариями и наблюдениями согласно разделу «Выполнение работы».
Развернутые выводы по работе.
Вопросы для самопроверки
Каков механизм общения компьютерных программ с внешним миром?
Что такое APIWin32? Какую функцию он выполняет?
Что такое процедурный и функциональный способ вызова макросов?
Какой регистр меняет значение при выполнении макроса print? Как обойти эту особенность его работы?
Какой дефект мы обнаружили и исправили в поставляемом макросе inkey?
МЕХАНИЗМ ИСПОЛЬЗОВАНИЯ ПРОЦЕДУР
Цель работы
Изучить способы вызова процедур, механизмы передачи управления в процедуру, возврата из процедуры, доступа к параметрам, переданным в процедуру. Изучить структуру стекового кадра вызванной процедуры и способы очистки стека после завершения процедуры.
Теоретические сведения
Процедура – это подпрограмма основной программы. Основная программа может вызывать процедуру сколько угодно раз. Для этого нужно при каждом вызове передать управление на «точку входа» в процедуру – то есть ту команду, которая в процедуре будет выполняться первой.
Тут есть две технических проблемы:
как нарушить естественное последовательное выполнение команд основной программы и «перепрыгнуть» в процедуру и
как правильно вернуться к продолжению основной программы после окончания выполнения процедуры.
И то, и другое просто и эффективно решается с помощью специального регистра процессора EIP–ExtendedInstructionPointer. Ну, и, разумеется, соблюдением определенных правил поведения, о чем пойдет речь ниже.
Последовательное выполнение команд
Сначала разберемся, как вообще происходит выполнение процессором цепочек команд.
Для начала напомним общеизвестную истину – процессор способен выполнять машинные команды, находящиеся только и исключительно в оперативной памяти. Не на диске, не на флешке, только в оперативной памяти. Область оперативной памяти, куда записаны машинные команды исполняемой программы, называется ее секцией кода.
Регистр EIPиспользуется процессором для адресации в оперативной памяти очередной машинной команды (что видно и из его названия –pointer, то есть указатель).
Стандартной ситуацией при выполнении программ является последовательное выполнение команд, записанных в памяти одна за другой вплотную. Нарушения этого порядка происходят при:
безусловных и условных переходах в программах (конструкции типа “if–else”, циклы;
вызовах процедур и возвратах из них.
Подобные «нарушения» происходят очень часто, потому что без них реальное программирование попросту невозможно (что же это за программа, в которой нельзя, например, проверить ну хоть какое-то условие и разветвить выполнение?). Но для процессора такие «прыжки» были и остаются особыми действиями, и мы сейчас разберемся, как это организовано.
Для внешнего наблюдателя выполнение процессором любой команды происходит в пять последовательных стадий:
чтениекоманды из оперативной памяти по адресу, который хранится вEIP, в устройство распознавания (оно – функциональная часть процессора);
распознаваниекоманды и построение ее микрокода;
установка адресовчтения операндов команды и (для пятого шага) адреса записи результатов выполнения;
выполнениекоманды (то есть вычисление результата выполнения);
Запись результатавыполнения по сформированному на шаге 3 адресу.
Давайте разберемся, что происходит с регистром EIPпри чтении команды.
Перед началом чтения команды регистр EIPуказывает на первый байт команды, которая будет читаться (08):
Происходит копирование байта 08 в процессор. Что нужно сделать, чтобы в процессор стало возможно прочитать следующий байт ВЕ? Давайте рассмотрим этот вопрос подробно.
Чтение-запись выполняется только по адресу, который выставляется на шине адреса. Это хорошо знакомая вам по общему курсу программирования операция разадресации, когда дан адрес, а читается-пишется данное, расположенное по этому адресу. В компьютере операцию разадресации (чтение-запись по указанному адресу) выполняет аппаратная компонена системный контроллер, он входит в состав микросхемы «Южный мост», которую всегда можно увидеть на материнской плате. Он коммутируется, во-первых, с шиной адреса, на которую выставляется адрес, а во-вторых, с шиной данных, на которую либо передаются прочитанные данные, либо с неё берутся записываемые данные.
Если ничего не менять на шинах, то сколько раз ни подавать на контроллер сигнал чтения, на шину данных всякий раз будет переноситься один и тот же байт – тот, чей адрес выставлен на шине адреса.
Понятно! Чтобы прочитать байт ВЕ, нужно указатель EIPпереставить на него! Как? Очень просто – прибавить кEIPединицу, потому что адреса соседних байтов отличаются ровно на 1. И можно читать.
Теперь мы понимаем: чтение каждого очередного байта команды сразу же увеличивает EIP на 1.
Примечание. Команды в архитектуре х86/IA-32 имеют разную длину – от одного до 7 байт. Откуда процессор «знает», сколько байт нужно прочесть, чтобы получилась полная команда? Ответ – это становится «известным» сразу после чтения первого байта команды, который выполняет роль идентификатора команды. Как только этот байт прочитан, в процессоре внутренний счетчик цикла чтения байтов команды аппаратно устанавливается в значение «сколько дополнительных байтов команды еще нужно прочесть». Что и делается.
Когда команда 08BE1400 полностью прочитана из памяти в процессор, он приступает к ееобработке(шаги 2-5 из приведенной выше последовательности). Там в том числе и шаг 4 «выполнение». Вопрос: а в каком положении при этом находитсяEIP? А вот в каком:
Неожиданное открытие! Выполняется команда 1, а EIPуже указывает на следующую по записи команду 2! И произошло это именно потому, что побайтное чтение команды сдвигаетEIPвперед на 1 после чтения каждого байта. Выходит, что при последовательном выполнении команд адрес следующей (по отношению к выполняемой в данный момент) команды формируется автоматически, просто в силу процесса чтения команд из памяти. Кстати, это есть практическое проявление одного из принципов фон Неймана по правильному построению архитектуры компьютеров.
Теперь рассмотрим особенности передачи управления..