71493

Визуализация работы программного стека при помощи Ogre3D

Лабораторная работа

Информатика, кибернетика и программирование

Целью данной работы является изучение принципа работы программного стека, а также реализация визуализации работы программного стека при помощи графического движка Ogre3D. Задачи В данной работе необходимо выполнить следующие задачи: Разработать программу на движке Ogre3D, которая визуализирует работу программного стэка.

Русский

2014-11-07

231.78 KB

24 чел.

9

Министерство образования и науки Российской Федерации

Санкт-Петербургский государственный политехнический университет

Институт информационных технологий и управления

Кафедра «Информационная безопасность компьютерных систем»

ЛАБОРАТОРНАЯ РАБОТА № 3

Визуализация работы программного стека при помощи Ogre3D

по дисциплине «Теоретико-числовые методы в криптографии»

Выполнил

студент гр. 33508/1  А.В. Лашевский

 <подпись>

Руководитель

ст.преподаватель   А.Ю. Чернов

 <подпись>

Санкт-Петербург

2013

ПОСТАНОВКА ЗАДАЧИ

Цель работы

Целью данной работы является изучение принципа работы программного стека, а также реализация визуализации работы программного стека при помощи графического движка Ogre3D.

Задачи

В данной работе необходимо выполнить следующие задачи:

Разработать программу на движке Ogre3D, которая визуализирует работу программного стэка. Программа должна отображать область памяти стэка с адресами и значениями в этой области памяти, указатель ESP, EBP, значение регистра EAX, область памяти с программным кодом, указатель EIP. Программа должна на входе читать файл с командами на выполнение в формате XML (можно использовать любую готовую библиотеку парсер XML).

Требования

Данную работу необходимо выполнить с учетом следующих требований:

  1. Минимально поддерживаемые команды:
  2. mov eax, число
  3. mov esp, число
  4. push число
  5.  pop eax
  6.  mov esp, ebp
  7.  mov ebp, esp
  8.  push esp
  9.  push ebp
  10.  push eax
  11.  pop ebp
  12.  pop esp
  13.  call eax
  14.  call число
  15.  jmp eax
  16.  jmp число
  17. Программа должна по событию (например, нажатие на пробел) переходить от текущей инструкции к следующей с учетом всех команд, в стэке значения должны меняться, значение EAX так же должно меняться, ESP, EBP, EIP должны двигаться указывая на определенные места в памяти.
  18.  В отчете должно присутствовать описание работы программного стэка, описание работы каждой поддерживаемой инструкции, описание формата входного файла, описание работы программы, скриншот программы.

ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ

Описание работы каждой поддерживаемой инструкции:

  1.  Команда MOV

Эта команда используется для копирования значения из одного места в другое. Источником может быть регистр, ячейка памяти или непосредственное значение (только как исходное значение). Синтаксис команды:

 mov приемник, источник

  1.  Стековые операции - PUSH, POP

Есть две команды, для размещения значения в стеке и извлечения его из стека: PUSH и POP. Команда PUSH размещает значение в стеке, т.е. помещает значение в ячейку памяти, на которую указывает регистр ESP, после этого значение регистра ESP увеличивается на 1. Команда POP извлекает значение из стека, т.е. извлекает значение из ячейки памяти, на которую указывает регистр ESP, после этого уменьшает значение регистра ESP на 1. Значение, помещенное в стек последним, извлекается первым.

  1.  Команда JMP 

Команда безусловно передает управление адресату. Команда JMP является однонаправленной командой передачи управления; она не сохраняет адрес возврата в стеке. Команда JMP передает управление из текущей процедуры в другую процедуру. Адрес процедуры указывается непосредственно в команде, в регистре или в ячейке памяти. Местоположение адреса определяет, интерпретируется ли адрес как относительный адрес или как абсолютный адрес. Относительный адрес.

  1.  Команда RET

Возврат из процедуры завершает выполнение процедуры и передает управление команде, следующей за командой CALL, которая вызвала данную процедуру. Команда RET восстанавливает содержимое регистра EIP, которое было сохранено в стеке при вызове процедуры. Команда RET имеет необязательный операнд непосредственного значения. Когда операнд имеется, эта константа прибавляется к содержимому регистра ESP, что имеет эффект удаления всех параметров, сохраненных в стеке перед вызовом процедуры. 

  1.  Команда CALL 

Вызов процедуры передает управление и сохраняет адрес команды, следующей за командой CALL, для дальнейшего использования командой RET (Возврат). CALL сохраняет текущее содержимое регистра EIP в стеке. Команда RET в вызванной процедуре использует этот адрес в стеке для передачи управления назад в вызывающую программу.

Стек играет важнейшую роль в процедурном программировании. Процедурное

Программирование подразумевает использование функций. Функции позволяют выделить часто используемые фрагменты кода в отдельные блоки и повторно использовать их из любой точки программы, тем самым повышая эффективность разработки. При использовании функций линейный (последовательный) ход выполнения программы нарушается - в любой момент мы можем передать управление на функцию. Для этого используется инструкция процессора call. Адрес функции передается как параметр этой

команды:

           call < адрес функции >

Перед вызовом функции её параметры помещаются в стек при помощи инструкции push. В языке Си первый параметр загружается в стек последним, последний параметр - первым. Получив управление, функция считывает из стека параметры вызова, и выполняет свою работу. Парметры остаются в стеке, благодаря чему их можно использовать как переменные в ходе выполнения функции. Завершается функция инструкцией ret. После этого управление передается на команду, следующую за инструкцией call. Чтобы такая схема работала, необходимо запомнить адрес возврата из функции, т.е. адрес следующей за call команды. Этот адрес сохраняет в стеке команда call, т.е. сразу после вызова команды call в стеке будет сохранен адрес возврата – адрес следующей за call инструкции, и ESP будет указывать на этот адрес. [http://www.programmersclub.ru/]

ВЫПОЛНЕННАЯ РАБОТА

Данная работа состоит из нескольких этапов:

  1.  Изучение принципа работы программного стека;
  2.  Изучение и использование готового парсера библиотеки tinyXML, создание необходимого XML файла с командами;
  3.  Реализация визуализации работы программного стека.

Для данной работы был выбран готовый парсер библиотека tinyXML. Ассемблерные команды читаются из файла формата XML с помощью данного парсера. Загружаем файл, используя команду:

TiXmlDocument document("С:\\test.xml")

В самом файле команды хранятся в следующем формате:

<entity command = «команда» par1 = «параметр1» par2 = «параметр2» />

Под командой подразумевается одна из функций: push, pop, mov, call, jmp. Параметры  могут содержать любой из поддерживаемых программой регистров по заданию (EBP, ESP, EAX, EBX, ECX, EDX), а так же целочисленное значение. Параметр 2 может быть опущен.

Программа считывает каждую команду функцией ReadCommand из файла XML по нажатию клавиши пробел данным образом:

Получаем указатель на первый дочерний элемент объекта document, затем получаем указатель на первый элемент объекта xml_level.

 xml_level = document.FirstChildElement("level");

xml_entity = xml_level->FirstChildElement("entity");

При помощи следующей команды, будем получать указатель на каждый следующий элемент типа xml_level.

xml_entity = xml_entity->NextSiblingElement("entity");

Получать значения будем при помощи команд:
xml_entity->Attribute("command ");

xml_entity->Attribute("param1");

xml_entity->Attribute("param2");

Графический движок Ogre3D позволяет работать не только с 3D объектами, но и с 2D посредствам оверлеев. Оверлеи – это некоторый графический объект, который выводится поверх сцены. Класс OverlayElement содержит подробную информация о 2D-элементах, которые добавляются на оверлей. Все элементы, которые могут быть добавлены к оверлею, наследуются от этого класса. 

Важным встроенным подклассом класса OverlayElement является класс OverlayContainer. OverlayContainer ведет себя как OverlayElement, за исключением того, что он может содержать другие экземпляры OverlayElement, группируя их (что позволяет им, например, вместе перемещаться) и предоставляя им локальный центр координат для более легкого позиционирования элементов.

Третьим важным классом является класс OverlayManager. Всякий раз, когда приложение хочет создать 2D-элемент, чтобы добавить его к оверлею, оно должно вызывать метод OverlayManager::createOverlayElement. Например, чтобы создать панель (прямоугольник) можно вызвать метод:

OverlayManager::getSingleton().createOverlayElement("Panel", "myNewPanel");

Теперь необходимо понять, как создавать текст при помощи оверлеев. Сначала нам необходимо создать оверлей.

overlay = overlayManager.create("OverlayName");

После чего, необходимо создать панель, для которой можем задать размер, цвет, положение. Затем создадим текст - объект типа OverlayElement с указанием нужных параметров.

Для того, чтобы все отображалось текст нужно привязать к панели, а панель к оверлею используя функции addChild и add2D соответственно.

panel = static_cast<Ogre::OverlayContainer*>(overlayManager.createOverlayElement("Panel", "PanelName"));

panel->setMetricsMode(Ogre::GMM_PIXELS);

panel->setPosition(50, 10);

panel->setMaterialName( "BaseWhite" );

panel->setDimensions(100, 40);

overlay->add2D(panel);

Для того чтобы задавать параметры в пикселях, а не относительных единицах, мы вызвали метод setMetricsMode. Здесь создали панель, указали где она размещается (setPosition), из какой текстуры состоит – будем создавать простую панель белого цвета (setMaterialName), задали ее размеры (setDimensions). И добавили к overlay.

textBox = static_cast<Ogre::TextAreaOverlayElement*>(overlayManager.createOverlayElement("TextArea", "txtGreeting"));

textBox->setMetricsMode(Ogre::GMM_PIXELS);

textBox->setPosition(5, 12);

textBox->setDimensions(100, 20);

textBox->setParameter("font_name", "MyFont");

textBox->setParameter("char_height", "20");

textBox->setColour(Ogre::ColourValue::Blue);    

textBox->setCaption("EAX");

panel->addChild(textBox);

Здесь аналогичным образом указываются те же параметры, что и для панели, однако добавляются setParameter для указания типа и размера используемого шрифта, setColour для цвета текста и setCaption для самого текста. После присоединяем текст к панели при помощи addChild.

ВЫВОДЫ

В ходе данной работы были изучены принципы работы программного стека. Была реализована визуализация работы программного стека посредством графического движка Ogre3D. Результаты работы реализованной программы представлены в приложении A (Рисунок 1). Содержание файла test.xml представлено в приложении A (Рисунок 2).

ПРИЛОЖЕНИЕ  А

Рисунок 1 – Результат работы программы

<?xml version="1.0"?><level>

<entity command="push" par1="65535" par2=""/>

<entity command="push" par1="6553" par2=""/>

<entity command="push" par1="655" par2=""/>

<entity command="push" par1="65" par2=""/>

<entity command="push" par1="6" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EBX" par2=""/>

<entity command="pop" par1="ECX" par2=""/>

<entity command="pop" par1="EDX" par2=""/>

<entity command="push" par1="777" par2=""/>

<entity command="pop" par1="EBP" par2=""/>

<entity command="push" par1="ESP" par2=""/>

<entity command="push" par1="ESP" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="push" par1="EAX" par2=""/>

<entity command="push" par1="EBX" par2=""/>

<entity command="push" par1="ECX" par2=""/>

<entity command="push" par1="EDX" par2=""/>

<entity command="push" par1="EDX" par2=""/>

<entity command="push" par1="EBP" par2=""/>

<entity command="push" par1="ESP" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="mov" par1="EAX" par2="1"/>

<entity command="mov" par1="EBX" par2="2"/>

<entity command="mov" par1="ECX" par2="3"/>

<entity command="mov" par1="EDX" par2="4"/>

<entity command="mov" par1="EBP" par2="ESP"/>

<entity command="mov" par1="EBP" par2="ESP"/>

<entity command="mov" par1="EBP" par2="ESP"/>

<entity command="push" par1="ESP" par2=""/>

<entity command="push" par1="ESP" par2=""/>

<entity command="push" par1="ESP" par2=""/>

<entity command="pop" par1="EBP" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EBX" par2=""/>

<entity command="pop" par1="ECX" par2=""/>

<entity command="pop" par1="EDX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="call" par1="0" par2=""/>

<entity command="push" par1="1" par2=""/>

<entity command="push" par1="2" par2=""/>

<entity command="push" par1="3" par2=""/>

<entity command="push" par1="4" par2=""/>

<entity command="push" par1="5" par2=""/>

<entity command="push" par1="65535" par2=""/>

<entity command="pop" par1="EBX" par2=""/>

<entity command="push" par1="10" par2=""/>

<entity command="push" par1="9" par2=""/>

<entity command="jmp" par1="57" par2=""/>

<entity command="push" par1="8" par2=""/>

<entity command="push" par1="7" par2=""/>

<entity command="push" par1="6" par2=""/>

<entity command="push" par1="5" par2=""/>

<entity command="push" par1="4" par2=""/>

<entity command="push" par1="3" par2=""/>

<entity command="push" par1="2" par2=""/>

<entity command="push" par1="1" par2=""/>

<entity command="push" par1="0" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

<entity command="pop" par1="EAX" par2=""/>

</level>

Рисунок 2 – Содержание файла test.xml