Дизассемблиры

Автор: Пользователь скрыл имя, 19 Октября 2011 в 15:00, реферат

Краткое описание

Дизассемблирование (От англ. disassemble - разбирать, демонтировать) – это процесс или способ получения исходного текста программы на ассемблере из программы в машинных кодах. Полезен при определении степени оптимальности транслятора и при генерации кодов собственной программы. Позволяет понять алгоритм или метод построения программ, у которых отсутствуют исходные тексты. Существуют специальные программы дизассемблеры, которые выполняют этот процесс.

Оглавление

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

Файлы: 1 файл

kyrsovaya0002.doc

— 391.00 Кб (Скачать)

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

образовательное учреждение

высшего профессионального  образования

Казанский национальный исследовательский институт

им.А.Н.Туполева-КАИ

Елабужский  филиал.

Курсовая  работа по дисциплине

“Системное  программное обеспечение”

на тему:

«Дизассемблиры»

                                                            Выполнила: студентка 5 курса

22575 группы

Борисова  Татьяна Игоревна

E-mail:Lisicia@mail.ru

Проверил: Конюхов Михаил Иванович

E-mail:kai_kdtu@rambler.ru

Елабуга 2011 

     Оглавление

Введение

     Дизассемблирование (От англ. disassemble - разбирать, демонтировать) – это процесс или способ получения исходного текста программы на ассемблере из программы в машинных кодах. Полезен при определении степени оптимальности транслятора и при генерации кодов собственной программы. Позволяет понять алгоритм или метод построения программ, у которых отсутствуют исходные тексты. Существуют специальные программы дизассемблеры, которые выполняют этот процесс.

     Одним из передовых продуктов для дизассемблирования программ является пакет программ от CSO Computer Services - IDA (Interactive Disassembler). IDA не является автоматическим дизассемблером. Это означает, что IDA выполняет дизассемблирование лишь тех участков программного кода, на которые имеются явные ссылки. При этом IDA старается извлечь из кода максимум информации, не делая никаких излишних предположений. После завершения предварительного анализа программы, когда все обнаруженные явные ссылки исчерпаны, IDA останавливается и ждет вмешательства; просмотрев готовые участки текста, можно как бы подсказать ей, что нужно делать дальше. После каждого вмешательства снова запускается автоматический анализатор IDA, который на основе полученных сведений пытается продолжить дизассемблирование.

     IDA является не только дизассемблером, но и одним из самых мощных  средств исследования программ. Это возможно благодаря наличию  развитой навигационной системы,  позволяющей быстро перемещаться между различными точками программы, объектами и ссылками на них, отыскивать неявные ссылки и т.д. Исследование даже больших и сложных программ в IDA занимает в десятки и сотни раз меньше времени, чем путем просмотра текста, полученного обычным дизассемблером.

     Целью, данной работы, является задача дизассемблирования программ написанных на языке программирования C/C++ и скомпилированных на компиляторах Microsoft Visual C++ 6.0, Borland C++ 5.0 и WATCOM.

     В процесс дизассемблирования входит:

     1) идентификация математических операций таких как: сложение, вычитание, деление, операция вычисления остатка, умножение и определения комплексных операций;

     2)  Идентификация операторов SWITCH - CASE – BREAK.

     В ходе работы будет проведен анализ по качеству оптимизации, сгенерированных приведенными выше компиляторами программ, что позволит сравнить их и определить каким из них необходимо воспользоваться для получения наиболее оптимального и быстрого кода в программировании.

Глава1. Идентификация математических операторов

 

§1.1 Идентификация оператора "+" 

       В общем случае оператор "+" транслируется либо в машинную  инструкцию ADD, "перемалывающую" целочисленные  операнды, либо в инструкцию FADDx, обрабатывающую вещественные значения. Оптимизирующие компиляторы могут заменять "ADD xxx, 1" более компактной командой "INC xxx", а конструкцию "c = a + b + const" транслировать в машинную инструкцию "LEA c, [a + b + const]". Такой трюк позволяет одним махом складывать несколько переменных, возвратив полученную сумму в любом регистре общего назначения, - не обязательно в левом слагаемом как это требует мнемоника команды ADD. Однако, "LEA" не может быть непосредственно декомпилирована в оператор "+", поскольку она используется не только для оптимизированного сложения (что, в общем-то, побочный продукт ее деятельности), но и по своему непосредственному назначению - вычислению эффективного смещения. Рассмотрим следующий пример:  

main()

{

int a, b,c;

c = a + b;

printf("%x\n",c);

c=c+1;

printf("%x\n",c); 

}

Демонстрация  оператора "+"  

     Результат его компиляции компилятором Microsoft Visual C++ 6.0 с настройками по умолчанию  должен выглядеть так:  

main  proc near  ; CODE XREF: start+AF p 

var_c  = dword ptr -0Ch

var_b  = dword ptr -8

var_a  = dword ptr -4 

push ebp

mov ebp, esp

; Открываем кадр стека 

sub esp, 0Ch

; Резервируем  память для локальных переменных 

mov eax, [ebp+var_a]

; Загружаем  в EAX значение переменной var_a 

add eax, [ebp+var_b]

; Складываем EAX со значением переменной var_b и  записываем результат в EAX 

mov [ebp+var_c], eax

; Копируем  сумму var_a и var_b в переменную var_c, следовательно:

; var_c = var_a + var_b 

mov ecx, [ebp+var_c]

push ecx

push offset asc_406030 ; "%x\n"

call _printf

add esp, 8

; printf("%x\n", var_c) 

mov edx, [ebp+var_c]

; Загружаем  в EDX значение переменной var_c 

add edx, 1

; Складываем EDX со значением 0х1, записывая  результат в EDX 

mov [ebp+var_c], edx

; Обновляем  var_c

; var_c = var_c +1 

mov eax, [ebp+var_c]

push eax

push offset asc_406034 ; "%x\n"

call _printf

add esp, 8

; printf("%\n",var_c) 

mov esp, ebp

pop ebp

; Закрываем  кадр стека 

retn 

main  endp 
 

     Теперь посмотрим, как будет выглядеть тот же самый пример, скомпилированный с ключом "/Ox" (максимальная оптимизация):

main  proc near  ; CODE XREF: start+AF p

push ecx

; Резервируем  место для одной локальной переменной

; (компилятор  посчитал, что три переменные  можно ужать в одну и это  дейст. так) 

mov eax, [esp+0]

; Загружаем  в EAX значение переменной var_a 

mov ecx, [esp+0]

; Загружаем  в EAX значение переменной var_b

; (т.к  .переменная не инициализирована загружать можно откуда угодно) 

push esi

; Сохраняем  регистр ESI в стеке 

lea esi, [ecx+eax]

; Используем LEA для быстрого сложения ECX и EAX с последующей записью суммы

; в регистр  ESI

; "Быстрое  сложение" следует понимать не  в смысле, что команда LEA выполняется

; быстрее  чем ADD, - количество тактов той  и другой одинаково, но LEA

; позволяет  избавиться от создания временной  переменной для сохранения

; промежуточного  результата сложения, сразу направляя  результат в ESI

; Таким  образом, эта команда декомпилируется как

; reg_ESI = var_a + var_b 

push esi

push offset asc_406030 ; "%x\n"

call _printf

; printf("%x\n", reg_ESI) 

inc esi

; Увеличиваем  ESI на единицу

; reg_ESI = reg_ESI + 1 

push esi

push offset asc_406034 ; "%x\n"

call _printf

add esp, 10h

; printf("%x\n", reg_ESI) 

pop esi

pop ecx

retn 

main  endp 

  

     Остальные компиляторы (Borland C++, WATCOM C) генерируют приблизительно идентичный код, поэтому, приводить результаты бессмысленно - никаких новых "изюминок" они  в себе не несут.  
 

§1.2 Идентификация оператора "-" 

     В общем случае оператор "- " транслируется  либо в машинную инструкцию SUB (если операнды - целочисленные значения), либо в инструкцию FSUBx (если операнды - вещественные значения). Оптимизирующие компиляторы могут заменять "SUB xxx, 1" более компактной командой "DEC xxx", а конструкцию "SUB a, const" транслировать в "ADD a, -const", которая ничуть не компактнее и ни сколь не быстрей (и та, и другая укладываться в один так). Рассмотрим это в следующем примере:  

main()

{

int a,b,c; 

c = a - b;

printf("%x\n",c); 

c = c - 10;

printf("%x\n",c); 

}

Демонстрация  идентификации оператора "-"  

     Не  оптимизированный вариант будет  выглядеть приблизительно так:  

main  proc near  ; CODE XREF: start+AF p 

var_c  = dword ptr -0Ch

var_b  = dword ptr -8

var_a  = dword ptr -4 

push ebp

mov ebp, esp

; Открываем  кадр стека 

sub esp, 0Ch

; Резервируем  память под локальные переменные 

mov eax, [ebp+var_a]

; Загружаем  в EAX значение переменной var_a 

sub eax, [ebp+var_b]

; Вычитаем  из var_a значением переменной var_b, записывая результат в EAX 

mov [ebp+var_c], eax

; Записываем  в var_c разность var_a и var_b

; var_c = var_a - var_b 

mov ecx, [ebp+var_c]

push ecx

Информация о работе Дизассемблиры