Автор: Пользователь скрыл имя, 19 Октября 2011 в 15:00, реферат
Дизассемблирование (От англ. disassemble - разбирать, демонтировать) – это процесс или способ получения исходного текста программы на ассемблере из программы в машинных кодах. Полезен при определении степени оптимальности транслятора и при генерации кодов собственной программы. Позволяет понять алгоритм или метод построения программ, у которых отсутствуют исходные тексты. Существуют специальные программы дизассемблеры, которые выполняют этот процесс.
Введение.
Структура природы человека.
Биологическое и социальное в человеке.
Роль биологических и географических факторов в формировании социальной жизни.
Социальная жизнь.
Министерство образования РФ государственное
образовательное учреждение
высшего профессионального образования
Казанский национальный исследовательский институт
им.А.Н.Туполева-КАИ
Елабужский филиал.
Курсовая работа по дисциплине
“Системное программное обеспечение”
на тему:
«Дизассемблиры»
Оглавление
§1.1
Идентификация оператора "+"
В общем случае оператор "+"
транслируется либо в машинную
инструкцию ADD, "перемалывающую" целочисленные
операнды, либо в инструкцию FADDx,
обрабатывающую вещественные
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