- •Высшая школа интеллектуальных систем и суперкомпьютерных технологий лабораторная работа №6 «Команды и способы адресации для x86 в 32-битном режиме»
- •Void main() {
- •2: Unsigned long I;
- •3: Void main() {
- •8: Else
- •00D8178b 83 3d 4c a1 d8 00 03 cmp dword ptr [I (0d8a14Ch)],3
- •00D81794 83 3d 4c a1 d8 00 05 cmp dword ptr [I (0d8a14Ch)],5
Санкт-Петербургский политехнический университет Петра Великого
Институт компьютерных наук и технологий
Высшая школа интеллектуальных систем и суперкомпьютерных технологий лабораторная работа №6 «Команды и способы адресации для x86 в 32-битном режиме»
по дисциплине «Архитектура вычислительных систем»
Выполнил
студент гр. 3530903/80001 А. В. Шильникова
Руководитель Н. М. Вербова
«___» __________ 2020 г.
Санкт-Петербург
2020
Цель работы: познакомиться с системой процессорных команд и способами использования этих команд.
Задачи:
• взять фрагмент программы на языке Си, заданный преподавателем, или написать такой фрагмент самостоятельно по заданной спецификации;
• оттранслировать программу, содержащую этот фрагмент;
• перейти в режим отладки и изучить дизассемблированный код фрагмента;
• самостоятельно заменить обращение к элементам массива через индекс на обращение через указатель, перетранслировать программу;
• проанализировать и прокомментировать (описать), как компилятор реализовал обращение через указатель.
Вариант 6
1-6.
short Mas[10];
unsigned long i;
void main() {
i = 9;
while (i > 0) {
if ((i >= 3) && (i != 5))
Mas[i] = (3 * i) ^ 0x18;
else
Mas[i] = (27 * i) / 8;
i--;
}
}
Дизассемблированный код с комментариями:
1: short Mas[10];
2: unsigned long i;
3: void main() { //вызов функции main()
00D81750 55 push ebp //сохраняем значение регистра ebp в стек, чтобы после выполнения программы или подпрограммы frame pointer можно было вернуть в состояние до вызова функции. Тип адресации - неявная
00D81751 8B EC mov ebp,esp //в регистр ebp копируется значение из регистра esp. Тип адресации - регистровая
00D81753 81 EC C0 00 00 00 sub esp,0C0h //отнимаем от esp OCOh и сохраняем результат в esp. Выделяем память для переменных. Тип адресации источника – непосредственная, приемника - регистровая
00D81759 53 push ebx
00D8175A 56 push esi
00D8175B 57 push edi //сохраняем в стек значения регистров ebx, esi, edi. Тип адресации - неявная
00D8175C 8D BD 40 FF FF FF lea edi,[ebp-0C0h] //сохраняем в edi значение ebp-OCOh. Тип адресации источника – косвенно-регистровая со смещением (-OCOh), приемника – регистровая.
00D81762 B9 30 00 00 00 mov ecx,30h //записываем в регистр ecx значение 30h. Регистр ecx применяют для организации циклов. Перед началом цикла в него помещают количество итераций. Каждая команда loop уменьшает значение этого регистра. Тип адресации источника – непосредственная, приемника – регистровая.
00D81767 B8 CC CC CC CC mov eax,0CCCCCCCCh //записываем в регистр eax значение 0CCCCCCCCh, которое означает, что оно не инициализировано. Тип адресации источника – непосредственная, приемника – регистровая.
00D8176C F3 AB rep stos dword ptr es:[edi] //rep – префикс, позволяющий выполнить команду stos определенное количество раз, указанных в ecx. Происходит циклический повтор инициализации массива (выполнение команды по адресу es:[edi]
4: i = 9;
00D81778 C7 05 4C A1 D8 00 09 00 00 00 mov dword ptr [i (0D8A14Ch)],9 //записываем в переменную i по адресу 0D8A14Ch значение 9. dword ptr означает, что размер i составляет 32 бита, что соответствует размеру, занимаемому в памяти переменной типа long. Тип адресации источника – непосредственная, приемника - абсолютная
5: while (i > 0) {
00D81782 83 3D 4C A1 D8 00 00 cmp dword ptr [i (0D8A14Ch)],0 //сравниваем значение счетчика i по адресу 0D8A14Ch со значением 0, то есть проверяем условие цикла while. dword ptr означает, что размер i составляет 32 бита, что соответствует размеру, занимаемому в памяти переменной типа long. Тип адресации источника – непосредственная, приемника - абсолютная
00D81789 76 53 jbe main+8Eh (0D817DEh) //обрабатываем эту строку, когда в результат выставляются флаги, гарантирующие заход в jbe, т.е. когда i будет меньше или равен нулю. В этом случае выходим из цикла (совершается jmp в адрес 0D817DEh, который указывает на первую из команд для выхода из подпрограммы). Тип адресации – абсолютная, путем смещения относительно процедуры main.
6: if ((i >= 3) && (i != 5))
00D8178B 83 3D 4C A1 D8 00 03 cmp dword ptr [i (0D8A14Ch)],3
00D81792 72 23 jb main+67h (0D817B7h) //сравниваем значение счетчика i по адресу 0D8A14Ch со значением 3, если i больше 3 (jb), то происходит jmp на строку с адресом 0D817B7h, которая соответствует выполнению действия else. Тип адресации источника – непосредственная, приемника – абсолютная. Во второй строке тип адресации – абсолютная, путем смещения относительно процедуры main
00D81794 83 3D 4C A1 D8 00 05 cmp dword ptr [i (0D8A14Ch)],5
00D8179B 74 1A je main+67h (0D817B7h) //сравниваем значение счетчика i по адресу 0D8A14Ch со значением 5, на неравенство (je). Тип адресации источника – непосредственная, приемника – абсолютная. Во второй строке тип адресации – абсолютная, путем смещения относительно процедуры main
7: Mas[i] = (3 * i) ^ 0x18;
00D8179D 6B 05 4C A1 D8 00 03 imul eax,dword ptr [i (0D8A14Ch)],3 //Если оба условия выполнились выполняем действие. Умножаем значение счетчика i на 3 и записываем результат в регистр eax. imul – перемножение знаковых чисел. Тип адресации источник 1 – непосредственная, источник2 – абсолютная, приемник - регистровая
00D817A4 83 F0 18 xor eax,18h //производим поразрядное исключающее «или» eax с константой 0x18 и записываем в регистр eax. Тип адресации источника – непосредственная, приемник - регистровая
00D817A7 8B 0D 4C A1 D8 00 mov ecx,dword ptr [i (0D8A14Ch)] //загружаем в ecx значение переменной i. Тип адресации источника – абсолютная, приемника - регистровая
00D817AD 66 89 04 4D 38 A1 D8 00 mov word ptr Mas (0D8A138h)[ecx*2],ax //записываем в ячейку массива Mas с индексом ecx (значение i). Нужная ячейка выбирается сдвигом на i*2 байт. Тип адресации источника – регистровая, приемника – регистровая.
00D817B5 EB 18 jmp main+7Fh (0D817CFh) //переход на строку с адресом 0D817CFh. Тип адресации – абсолютная, путем смещения относительно процедуры main
8: else
9: Mas[i] = (27 * i) / 8;
00D817B7 6B 05 4C A1 D8 00 1B imul eax,dword ptr [i (0D8A14Ch)],1Bh //если хотя бы одно из условий в if не выполнилось, то выполняем это действие. Умножаем значение счетчика i на 27 и записываем результат в регистр eax. Тип адресации источника 18h – непосредственная, источника i – абсолютная, приемника - регистровая
00D817BE C1 E8 03 shr eax,3 //Логический сдвиг вправо eax на 3
00D817C1 8B 0D 4C A1 D8 00 mov ecx,dword ptr [i (0D8A14Ch)] //Записываем в переменную ecx значение i. Тип адресации источника – абсолютная, приемника – регистровая.
00D817C7 66 89 04 4D 38 A1 D8 00 mov word ptr Mas (0D8A138h)[ecx*2],ax //заносим в память младшие два байта результата Mas[i] = ax. Тип адресации источника – абсолютная, приемника – регистровая.
10: i--;
00D817CF A1 4C A1 D8 00 mov eax,dword ptr [i (0D8A14Ch)] //заносим в eax значение адреса переменной i. Тип адресации источника – абсолютная, приемника - регистровая
00D817D4 83 E8 01 sub eax,1 //вычитаем из eax единицу. Тип адресации источника – непосредственная, приемника - регистровая
00D817D7 A3 4C A1 D8 00 mov dword ptr [i (0D8A14Ch)],eax //записываем в переменную i значение eax. Тип адресации источника – регистровая, приемника - абсолютная
11: }
00D817DC EB A4 jmp main+32h (0D81782h) //возвращаемся к началу цикла и проверяем условие захода в него. Тип адресации – абсолютная, путем смещения относительно процедуры main
12: }
00D817DE 33 C0 xor eax,eax //обнуляем значение eax. Тип адресации - регистровая
00D817E0 5F pop edi //тип адресации - регистровая
00D817E1 5E pop esi //тип адресации - регистровая
00D817E2 5B pop ebx //тип адресации - регистровая
00D817E3 81 C4 C0 00 00 00 add esp,0C0h //тип адресации источника – непосредственная, приемника - регистровая
00D817E9 3B EC cmp ebp,esp //тип адресации - регистровая
00D817EB E8 40 FA FF FF call __RTC_CheckEsp (0D81230h)
00D817F0 8B E5 mov esp,ebp //тип адресации - регистровая
00D817F2 5D pop ebp //возвращаем значения переменных edi, esi, ebx, esp, ebp до момента начала выполнения программы
00D817F3 C3 ret //завершение выполнение программы
Адреса переменных в памяти:
i |
0D8A14Ch |
Mac[0] |
0D8A138h |
Mac[1] |
0D8A13Ch |
Mac[2] |
0D8A140h |
Mac[3] |
0D8A144h |
Mac[4] |
0D8A148h |
Mac[5] |
OD8A14Ch |
Mac[6] |
0D8A150h |
Mac[7] |
0D8A154h |
Mac[8] |
0D8A158h |
Mac[9] |
0D8A15Ch |
Программа с доступом к элементам массива через указатели:
short *Mas[10];
unsigned long i;