Семинары по курсу «Архитектура ЭВМ и язык ассемблера» учебно-методическое пособие. Часть 1. - Е.А. Кузьменкова_ В.С. Махнычев_ В.А. Падарян (1110587), страница 7
Текст из файла (страница 7)
Массив занимает 40байт, элементы массива расположены непрерывно, каждый элемент занимает 4байта.Обращение к 8-му элементу означает выборку данных по адресу p+32, далеепроисходит разыменование, т.е. значение этого элемента трактуется как адрес, покоторому лежит требуемое число. После того, как это число извлечено из памяти кнему прибавляется 1, результат сложения записывается в память по адресу х.movmovaddmoveax, dword [p + 32]eax, dword [eax]eax, 1dword [x], eaxЗадачиЗадача 3-1 Восстановление Си-кодаФункция, имеющая следующий прототипvoid decode2(int *xp, int *yp, int *zp)была скомпилирована в ассемблерный код. Тело функции выглядит следующимобразом.42movmovmovmovmovmovaddmovmovmovmovmovmoveax, dword [ebp +edi, dword [eax]eax, dword [ebp +edx, dword [eax]eax, dword [ebp +eax, dword [eax]edx, eaxeax, dword [ebp +dword [eax], edxeax, dword [ebp +dword [eax], edxeax, dword [ebp +dword [eax], edi12]8]16]12]8]16]Параметры xp, yp и zp находятся в памяти по смещениям 8, 12 и 16 относительноадреса, содержащегося в регистре ebp.
Напишите код тела функции decode2 наязыке Си, который был бы эквивалентен представленному ассемблерному коду.Задача 3-2 Побочный эффектНаписать фрагмент ассемблерного кода, эквивалентный данному фрагменту наязыке Си.// aint x, *px;*px++ = x -10;// bshort x, *px;x = *(--px + 4);Задача 3-3 Среднее арифметическоеДан массив из 100 целых чисел. Написать фрагмент ассемблерного кода, которыйпомещает в регистр eax среднее арифметическое первого и последнего элементовмассива при условии, что элементы массива имеют тип:a) char,b) short,c) int.Задача 3-4 Разность указателейДля приведенного фрагмента Си-кода написать соответствующий фрагментассемблерной программы.43static int a[50];static int *p, *q;static int n;p = &a[10];q = &a[25];n = q - p;Задача 3-5 Реализовать Си-кодДля приведенного фрагмента Си-кода написать соответствующий фрагментассемблерной программы.// ashort **p;++*(*(p+=3) -= 2);// bchar **q, **r, **t;r = q++;*t = (*r)++;**q = (**t)++;444.Операции над битовыми векторамиПоразрядные (побитовые) операцииНабор команд IA-32 поддерживает поразрядные команды, работающие свекторами битов: NOT, AND, XOR, OR.
Помимо получения результата, командыформируют флаги, наибольший интерес среди которых обычно представляет флагZF.Приведенные команды естественным образом реализуют побитовые логическиеоперации языка Си над целыми числами, тогда как работу с логическимивеличинами необходимо реализовывать другими способами.Команда TEST работает аналогично команде AND с той лишь разницей, чторезультат выполнения команды никуда не заносится и, следовательно, значениепервого операнда не изменяется. Обычно команда TEST применяется дляпроверки на 0 отдельных битов первого операнда. Например, проверка начетность содержимого регистра eax выглядит следующим образом:testjzeax, 1.even;Переходим на метку, если eax четноПриведем еще два распространенных примера использования побитовыхопераций:xortesteax, eax; Обнуление регистра (вместоmoveax, 0)eax, eax ; Проверка на 0 содержимого регистра; (вместо cmp eax, 0)Заметим, что в силу специфики выполнения побитовых операций команды вприведенных примерах выполняются быстрее, чем аналогичные действия,выполненные без использования побитовых операций.Пример 4-1 Логические операции над битовыми векторамиДаны четыре статические переменные целого типа a, b, c, d.
Написать фрагменткода на языке ассемблера, вычисляющий значение переменной a.45static int a, b, c, d;a = ~(a & b) | ((~c & d) | (c & ~d));РешениеПеременные a, b, c и d размещаем в статической памяти, в сегменте .bss. Привычислении будем следовать заданному порядку вычисления выражения, хотяиспользуемые в выражении операции позволяют этот порядок менять.Следует заметить, что при вычислении подвыражения (~c & d) | (c & ~d)необходимо пользоваться регистрами для выполнения побитового отрицания, т.к.непосредственное выполнение этой операции над ячейками памяти «испортит»значение переменной, расположенное в этих ячейках.section .bssa resd 1b resd 1c resd 1d resd 1sectionmovmovmovnotandnotandormovandnotormov.texteax, dwordedx, dwordecx, eaxeaxeax, edxedxecx, edxeax, ecxedx, dwordedx, dwordedxeax, edxdword [a],[c][d][a][b]eax;;;;;;;;;;;;;eax ← cedx ← dсоздаем копию переменной c в ecxeax ← ~ceax ← ~c & dedx ← ~decx ← c & ~deax ← (~c & d) | (c & ~d)edx ← aedx ← a & bedx ← ~(a & b)eax ← ~(a & b) | ((~c & d) | (c & ~d))a ← ~(a & b) | ((~c & d) | (c & ~d))Сдвиги и вращенияК побитовым операциям относятся также команды сдвигов.
Основные видысдвигов реализуются командами SHR, SHL, SAR, SAL, ROR, ROL, RCR, RCL.С помощью сдвигов можно реализовать быстрое умножение и деление на 2n (см.таблицу 5).46Все указанные команды выполняются значительно быстрее традиционных командумножения и деления (MUL, IMUL, DIV, IDIV), поэтому целесообразно использоватьименно их для реализации соответствующих операций при вычисленииарифметических выражений.Таблица 5. Реализация быстрого умножения и деления на степени 2.Выражениеop *= 2nop /= 2nop %= 2n, op >= 0КомандаSHL op, nчисла без знака:AND op, 2n-1SHR op, nчисла со знаком:SAR op, nПример 4-2 Двигаем и вращаемДаны две статические переменные a и b размером 2 байта.
Требуется регистр EAXзаполнить следующим образом: верхние 2 байта должны содержать значениепеременной a, а нижние 2 байта – значение переменной b, циклически сдвинутоена 5 бит вправо.Решениеsection .bssa resw 1b resw 1section .textmov ax, word [a]shl eax, 16mov ax, word [b]ror ax, 5;;;;;;;помещаем значение переменной a в младшие16 разрядоврегистра EAXсдвигаем это значение в верхние байтыпомещаем значение переменной b восвободившиеся разряды регистра EAX и …… выполняем над ними циклический сдвигПример 4-3 Реализация умножения регистра на константу черезсложения и сдвигиРеализовать умножение значения, лежащего в регистре eax на 6, используя толькооперации логического сдвига и сложения.
Результат поместить в eax.47Решениеmov ebx, eax ; копируем значение в регистр ebxshl ebx, 2; сдвигаем значение ebx влево на 2 бита; (эквивалентно умножению на 4)shl eax,1; сдвигаем значение eax влево на 1 бит; (эквивалентно умножению на 2)add eax, ebx ; складываем получившиеся значения,; результат в регистре eaxПример 4-4 Восстановление выраженияДан код на языке Си, в котором пропущены выражения, присваивающие значениялокальным переменным.int arith(int x, int y, int z) {int t1 = _________;int t2 = _________;int t3 = _________;int t4 = _________;return t4;}Дан ассемблерный код, который был сгенерирован компилятором. Параметрырасположены следующим образом: x лежит по адресу [ebp + 8], y – по адресу[ebp + 12], z – по адресу [ebp + 16].movxorsarnotsubeax,eax,eax,eaxeax,dword [ebp + 12]dword [ebp + 8]3dword [ebp + 16];;;;;(1)(2)(3)(4)(5)Требуется восстановить пропущенные выражения.РешениеИнструкция в первой строке ассемблерного кода выполняет пересылку значенияпеременной-параметра y на регистр eax.
Остальные четыре инструкциипреобразуют данные, распределим эти операции по выражениям в Си-программе.Во второй строке выполняется операция xor над значениями переменных y и x.Полученный результат сохраняется в регистре eax. Далее (строка №3) это значение48было сдвинуто вправо на 3 разряда. Причем сдвиг арифметический, не логический,что согласуется со знаковым типом сдвигаемой переменной. В четвертой строкевыполняется побитовое отрицание, в последней, строке №5, из этого значения былвычтен параметр z.Следует отметить, что все результаты вычислений не записывается в память, апродолжают сохраняться на одном и том же регистре eax. Все автоматическиелокальные переменные не были размещены в памяти, что позволяет характервыполняемых вычислений – никаких действий с адресами этих переменных непроисходило.int arith(int x, int y, int z) {int t1 = y ^ x;int t2 = t1 >> 3;int t3 = ~t2;int t4 = t3 - z;return t4;}Возвращаемое значение в данной функции – переменная t4, после выполненияинструкции в строке №5 ее значение уже расположено в регистре EAX, которыйиспользуется для передачи возвращаемого функцией значения.Пример 4-5 Обращение операцийПосле выполнения последовательности команд в регистре EAX было полученонекоторое значение.
Восстановите содержимое ячеек памяти.x db _____________________movsx eax, word [x]roreax, 4; EAX = 0xfffffbeeРешениеПервое необходимое действие – определить значение EAX перед командой ror.Поскольку вращение циклически сдвинуло содержимое регистра на 4 разряда всешестнадцатеричные цифры остались неизменны, но последняя оказалась крайнейслева. Таким образом, значение EAX перед вращением – 0xffffbeef.Выполнение команды movxs привело к заполнению двух старших байтов врегистре EAX единицами, что согласуется с содержимым младших байтов: припереводе старшей шестнадцатеричной цифры в числе0xbeefвпоследовательность бит получаем старший (знаковый) бит – 1.