Семинары по курсу «Архитектура ЭВМ и язык ассемблера» учебно-методическое пособие. Часть 2. - Е.А. Кузьменкова_ В.А. Падарян_ М.А. Соловьев (1110589), страница 12
Текст из файла (страница 12)
Команда сравнивает ST0 с явно заданным операндомрегистром и сразу же помещает результаты в ZF и CF. Неудобство вызывает то, чтонет возможности сразу очистить оба сравниваемых регистра. Ниже приведено решение на основе второго способа.section .textcmp:pushebpmovebp, espxorfldfldfucomieax, eaxqword [ebp+16]qword [ebp+8]st1;;;;;;al.1al, 0xff; Если a больше b, помещаем в al 1; Только если a меньше b …; … помещаем в al -1eax, al; Расширяем al до всего регистра eaxfinitsetbjbemov.1:movsxpopret; Стандартный пролог для соглашения cdeclПредварительно обнуляем возвращаемое значениеПомещаем на стек второй параметр bПомещаем на стек первый параметр aСравниваем st0|a vs. st1|bРезультаты сравнения сразу попадают в ZF и CFЧерез инициализацию очищаем стек регистровebpПример 5-6 Вычисление площади треугольникаРеализовать функцию double herons(double a, doubleплощадь треугольника по формуле Герона.b, double c),вычисляющуюРешениеУсловие задачи требует реализации вычисления по формулегде s s(s a)(s b)(s c) ,abc.
Сначала вычислим полупериметр s, а затем будем использовать2это значение для вычисления остальных подкоренных множителей. Согласно требованиям соглашения cdecl, возвращаемое значение должно остаться в ST0, остальные регистры данных x87 должны быть свободными.79section .rodatafloat_two dd 2.0section .textherons:pushebpmovebp, espsubesp, 8fldfldfldfaddpfaddpfldfdivpfstfldfldfsubpfldfldfsubpfldfldfsubpfmulpfmulpfmulpfsqrtaddpopretqword [ebp+8]qword [ebp+16]qword [ebp+24]; 2.0 потребуется для вычисления полупериметра; Стандартный пролог для соглашения cdecl; Выделяем место для хранения полупериметра; Загрузили на стек регистров все три параметра;dword [float_two];qword [esp];;;qword [esp];qword [ebp+8];;qword [esp]qword [ebp+16];qword [esp]qword [ebp+24];Сложили параметры и получили периметрПоделили на 2.0 – получили полупериметр sСохранили полупериметр в памяти, не освобождаярегистр st0 – он будет использоваться привычислении подкоренного произведенияЗагрузили sЗагрузили aВычислили второй множитель (s-a)Вычислили третий множитель (s-b)Вычислили четвертый множитель (s-c); Все перемножили и …; … взяли корень.
Результат остался в st0,; все остальные регистры данных x87 свободны.esp, 8ebpЗадачиЗадача 5-1 Перевод числа в модельную кодировкуИспользуется 9-битный формат, удовлетворяющий требованиям стандартаIEEE 754: знаковый бит, 4 бита – порядок, 4 бита - мантисса. Требуется представитьв данном формате числа ⅚ и -89.Задача 5-2 Вычисление длины окружностиНа стандартный вход подается число в экспоненциальной форме записи, задающеедлину радиуса окружности.
Требуется вычислить длину окружности и напечататьее на стандартный вывод с точностью три десятичных знака после запятой.Замечание: допустимо оформлять программу в виде отдельной функции, выполняющейся на уже выровненном стеке.80Задача 5-3 Приближение ЧебышеваТребуется вычислить расстояние между двумя точками на плоскости, используяприближение Чебышева вместо дорогостоящей операции взятия квадратного корня.sqrt(dx^2 + dy^2) = max(|dx|, |dy|) + 0.35 * min(|dx|, |dy|)Ответ напечатайте на стандартный вывод, входом программ являются непосредственно dx и dy.Задача 5-4 Теорема синусовТребуется рассчитать длину одной из сторон треугольника по длине другой стороsin sin ны и синусам противолежащих углов:.abНиже дан фрагмент программы, которая выполняет ввод данных, требуемые вычисления и вывод результата.Дополните приведенный текст:1) реализуйте функцию lawOfSin,2) обеспечьте ее вызов из функции CMAIN.Дополнительные требования к реализации:1.
Функция lawOfSin соответствует объявлениюvoid lawOfSin(float a, float alpha, float beta).2. Печатается результат вычислений с одинарной точностью.3. Для печати используется функция printf, что дополнительно требует должного выравнивания стека.81%include "io.inc"section .rodatafmt1 db 'a=%f alpha=%f beta=%f', 0CEXTERN scanfsection .textglobal CMAINCMAIN:push ebpmov ecx, espand esp, 0xfffffff0sub esp, 32mov [esp+28], ecxmov dword [esp], fmt1lea eax, [esp+24] ; &amov [esp+4], eaxlea eax, [esp+20] ; &alphamov [esp+8], eaxlea eax, [esp+16] ; &betamov [esp+12], eaxcall scanf; подготовка фактических аргументов; ...call lawOfSinmovmovpopxorretecx, [esp+28]esp, ecxebpeax, eaxlawOfSin:; тело функцииretЗадача 5-5 Из полярных – в декартовыДаны полярные координаты точки на плоскости, требуется перевести их в декартовы координаты.
Реализуйте преобразование в виде функции, удовлетворяющейследующему объявлению на языке Си и гибридному соглашению вызова cdeclкомпилятора GCC.typedef struct {double x;double y;} 2DPoint;typedef 2DPoint C_Point;typedef 2DPoint P_Point;D_Point fromPolarToCartesian(C_Point);82Более сложная версия этой задачи – обратное преобразование, из декартовых вполярные координаты.Задача 5-6 Параллельное соединениеn сопротивлений подключены параллельно в электрическую цепь. Требуется рассчитать их суммарное сопротивление R по формуле1 111. ... R R1 R2RnРеализуйте вычисление в виде функции, удовлетворяющей следующему объявлению на языке Си.double parallelCircuitResistor(int n, double resistors[n]);Задача 5-7Пусть задан массив вещественных чисел с плавающей точкой, которые необходимо просуммировать.
Зависит ли получаемый результат от порядка суммирования?Если да, то какой порядок суммирования позволяет получить наиболее точный результат?Задача 5-8Реализуйте функцию, вычисляющую скалярное произведение двух векторов, удовлетворяющую следующему объявлению на языке Си.double dot(int n, double v[n], double u[n]);Задача 5-9Реализуйте функцию, вычисляющую результат перемножения двух матриц, удовлетворяющую следующему объявлению на языке Си.void mult(int n, int m, int k, double a[n][m], double b[m][k], double r[n][k]);Задача 5-10Даны следующие определения переменных на языке Си.short s;int i;long long ll;Какие из последующих выражений верны при любых начальных значениях переменных?1)2)3)s == (short) (float) s,s == (short) (double) s,i == (int) (float) i,834)5)6)84i == (int) (double) i,ll == (long long) (float) ll,ll == (long long) (double) ll.Ответы и решенияЗадача 1-1Приведенные ниже и в задаче 1-2 решения используют строковые инструкции IA32.
В данном пособии они не рассматриваются, ознакомиться с этой группой инструкций можно, например, в работе [6].cld; просмотр в прямом порядкеmovmovesi, Aedi, B; загружаем адрес массива A; загружаем адрес массива Bmovecx, 100; устанавливаем число повторовeax, ax; теперь в ax очередное слово из a; расширение (альтернатива: cwde); записываем двойное слово в b.1; продолжаем цикл.1:lodswmovsxstosdloopЗадача 1-2stdmovleaecx, dword [N]esi, [A + 2 * ecx - 2]leaedi, [A + 4 * ecx - 4]jecxz .2.1:lodswmovsx eax, axstosdloop .1.2:;;;;;;;просмотр в обратном порядкесчитываем количество элементовуказатель на последний элемент типасловоуказатель на последний элемент типадвойное словопропускаем цикл, если элементов нет;;;;теперь в ax очередное слово из aрасширение (альтернатива: cwde)записываем двойное словопродолжаем цикл85Задача 1-3section .bssN equ …a resd Nsection .textCMAIN:mov eax, 0mov ecx, 0mov ebx, 4 * (N - 1).loop:mov edx, dword [a + ebx]cmp edx, dword [a + ecx]je .l1mov eax, 1jmp .lool_end.l1:add ecx, 4sub ebx, 4cmp ecx, ebxjl .loop.loop_end:ret; (1); (2); (3);;;;;(4)(5)(6)(7)(8);;;;(9)(10)(11)(12); (13)Задача 1-10movmovimuladdmov86eax,ebx,ecx,ecx,edx,dword [i] ; Можно считать, что i и j из Си-программы соответствуютdword [j] ; статические переменные, расположенные в секции .dataeax, Mebxdword [A + 4 * ecx]Задача 1-11%include 'io.inc'section .bssN equ ...
; Вместо многоточия некоторая константаA resd N * Nsection .textglobal CMAINCMAIN:; этот блок кода с инициализацией матрицы необязателенmov ecx, N * N.init:mov dword [A + 4 * ecx - 4], ecxloop .initxorxor.loop:cmpjgeimuleax, eaxecx, ecxecx, N.exitebx, ecx, N + 1 ;;;mov edx, dword [A + 4test edx, 1jz.evenadd eax, edx.even:inc ecxjmp .loop.exit:PRINT_DEC 4, eaxNEWLINExor eax, eaxretэто вместоimul ebx, ecx, Nadd ebx, ecx* ebx]87Задача 3-3%include 'io.inc'section .textglobal CMAINCMAIN:push ebpmov ebp, espsub esp, 8GET_DEC 4, [esp] ; input aGET_DEC 4, [esp + 4] ; input bcall maxPRINT_DEC 4, eaxNEWLINExor eax, eaxadd esp, 8pop ebpretmax:push ebpmov ebp, espmov eax, dword [ebp + 8] ; get acmp eax, dword [ebp + 12] ; a vs.
bcmovl eax, dword [ebp + 12] ; if a < b eax = bpop ebpretДругой вариант функции max – без создания нового фрейма:max:mov eax, dword [esp + 4]; Извлекаем acmp eax, dword [esp + 8]; a vs. bcmovl eax, dword [esp + 8] ; if a < b eax = bretЗадача 3-4В предложенном ниже решении используются инструкции PUSH/POP для пересылкиданных.88%include 'io.inc'section .textglobal CMAINCMAIN:push ebpmov ebp, espsub esp, 16GET_DEC 4, [esp + 8];GET_DEC 4, [esp + 12];lea eax, [esp + 8]mov dword [esp], eaxlea eax, [esp + 12];mov dword [esp + 4], eaxcall swapPRINT_DEC 4, [esp + 8] ;NEWLINEPRINT_DEC 4, [esp + 12] ;NEWLINExor eax, eaxadd esp, 16pop ebpretinput ainput badd eax, 4print aprint bswap:push ebpmov ebp, espmov eax, dword [ebp + 8] ; get amov edx, dword [ebp + 12] ; get bpush dword [eax]; push *apush dword [edx]; push *bpop dword [eax]; *a <- *bpop dword [edx]; *b <- *apop ebpretЗадача 3-5int f(signed char a, signed char d, int *p, int x);89Задача 3-8%include 'io.inc'section .textglobal CMAINCMAIN:sub esp, 4GET_DEC 4, [esp]call factPRINT_DEC 4, eaxNEWLINExor eax, eaxadd esp, 4retfact:push ebpmov ebp, espsub esp, 4mov edx, dword [ebp + 8]cmp edx, 1jg .L1mov eax, 1jmp .L2.L1:dec edxmov dword [esp], edxcall factimul eax, dword [ebp + 8].L2:add esp, 4pop ebpretДопустимо слегка усложнить задачу, потребовав проверку на переполнение.
Вэтом случае программа может выглядеть следующим образом.90%include 'io.inc'section .bssoverflow resd 1section .textglobal CMAINCMAIN:sub esp, 4GET_DEC 4, [esp]call factcmp dword [overflow], 0jne .L1PRINT_DEC 4, eaxjmp .L2.L1:PRINT_STRING "overflow detected".L2:NEWLINExor eax, eaxadd esp, 4retfact:push ebpmov ebp, espsub esp, 4mov edx, dword [ebp + 8]cmp edx, 1jg .L1mov eax, 1jmp .L2.L1:dec edxmov dword [esp], edxcall factimul eax, dword [ebp + 8]jno .L2mov dword [overflow], 1.L2:add esp, 4pop ebpretОднако в этом случае более интересным вариантом было бы вычислить факториал«в обратную сторону», т.