Семинары по курсу «Архитектура ЭВМ и язык ассемблера» учебно-методическое пособие. Часть 2. - Е.А. Кузьменкова_ В.А. Падарян_ М.А. Соловьев, страница 10
Описание файла
PDF-файл из архива "Семинары по курсу «Архитектура ЭВМ и язык ассемблера» учебно-методическое пособие. Часть 2. - Е.А. Кузьменкова_ В.А. Падарян_ М.А. Соловьев", который расположен в категории "". Всё это находится в предмете "архитектура эвм" из 2 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 10 страницы из PDF
Копируем структуру pairв регистры edx, ecxeax указывает на место размещения возвращаемогозначенияПереходим на эпилог; Конец тела функции – эпилог; Восстанавливаем регистр esi и указатель фрейма; Удаляем со стека служебный параметрПример 4-6 Вызов функции с возвращаемой структуройРеализуйте на языке ассемблера заданную функцию. Вызываемая функция f – листовая, выравнивать стек для ее вызова не обязательно. Дополнительное ограничение: при реализации тела функции запрещено использовать команды MOV.typedef struct t_pair {int x;int y;} pair;typedef struct t_link {pair payload;struct t_link *next;} link;pair f(link* p, int tres);void g(link *p) {static const int treshold = 9000;pair v = f(p, treshold);printf("Pair (%d, %d)\n", v.x, v.y);}РешениеВ отсутствии возможности пересылать данные командой MOV, аргументы на стекбудут помещаться естественной в такой ситуации командой PUSH.
Размер фрейма67будет меняться в процессе работы функции g. Другой, более важной особенностьюрассматриваемого далее кода является то, что фактическим первым аргументомвызова функции f будет адрес автоматической локальной переменной v (неявныйаргумент). Для переменной static const int treshold места в памяти не выделяется, в выражении непосредственно используется ее значение. Пространство аргументов совместно используется при вызове функций printf и f. Поскольку для вызова f стек не требуется выравнивать, будем класть на стек аргументы сразу послевыделения 8 байтов памяти для хранения переменной v. Таким образом, фреймфункции g имеет следующую структуру.После возврата из функции f двойное слово с адресом v будет освобождено.
Длятого, что бы функция printf вызывалась на выровненном стеке, освободим ещеодно двойное слово, содержащее значение p. В результате фреймом функции gбудет занято 20 байтов, пять двойных слов: адрес возврата, сохраненный регистрEBP, переменная v, оставшийся на стеке аргумент вызова 9000. Поместив тремя командами PUSH аргументы вызова printf, получим фрейм размером в 32 байта.68section .rodata.LC0 db `Pair (%d, %d)\n`, 0section .textg:pushebpmovebp, espsubesp, 8push9000pushdword [ebp+8]leaeax, [ebp-8]pusheaxcallfaddesp, 4pushdword [ebp-4]pushdword [ebp-8]push.LC0callprintfleaveret; Первые две команды – стандартный пролог;;;;;Выделяем 8 байт для pair vКладем второй аргумент функции f – tresholdКладем первый аргумент функции f - pВычисляем адрес переменной v и кладем его настек в качестве неявного аргумента; Освобождаем одно двойное слово на стеке; Кладем на стек три аргумента вызова printf; ЭпилогЗадачиЗадача 4-1Для работы с однонаправленным списком без заглавного звена используется объявление:typedef struct t_listnode{short key;struct t_listnode *next;} listnode;Учитывая, что для вывода значений, а также для работы с динамической памятьюиспользуются функции стандартной библиотеки языка Си, реализовать следующиефункции:1)void printlist(listnode *p);Печать ключей из звеньев списка p.2)listnode * addhead(listnode *p, short n);Добавление нового звена с ключом n в голову списка p, возвращается указатель на головное звено списка.3)listnode * dellast(listnode *p);Удаление последнего звена из непустого списка p с освобождением занятойим памятью, возвращается указатель на головное звено списка.При реализации рассмотреть два случая:а) реализация удовлетворяет соглашению cdecl;69б) реализация удовлетворяет соглашению fastcall.Задача 4-2Для работы с двоичным деревом используется объявление:typedef struct t_treenode {short key;struct t_treenode *left, *right;} treenode;Учитывая, что для вывода значений, а также для работы с динамической памятьюиспользуются функции стандартной библиотеки языка Си, рекурсивно реализоватьследующие функции:1)int eq(treenode *t1, treenode *t2);Проверка на равенство деревьев t1 и t2, в случае равенства возвращаетсязначение 1, и 0 в противном случае.2)treenode * insert(treenode *t, short n);Вставка новой вершины с ключом n в дерево поиска t, возвращается указатель на корень дерева.3)void deltree(treenode *t);Удаление дерева с освобождением занятой им памятью.При реализации рассмотреть два случая:а) реализация удовлетворяет соглашению cdecl;б) реализация удовлетворяет соглашению fastcall.Задача 4-3Пусть имеются две функции с одинаковыми прототипами:1)2)int wrapper(int a, int b, int c), int actual(int a, int b, int c) ;struct pair wrapper(struct pair *a, int x, int y) , struct pair actual(structpair *a, int x, int y), где struct pair содержитдва поля intn и int m.Реализуйте на языке ассемблера функцию wrapper, которая должна вызвать actual сидентичным собственному набором параметров и вернуть полученное значение.При этом:а) и wrapper, и actual используют соглашение cdecl;б) и wrapper, и actual используют соглашение fastcall;в) и wrapper, и actual используют соглашение stdcall;г) wrapper использует соглашение cdecl, а actual – stdcall;д) wrapper использует соглашение stdcall, а actual – cdecl;70е) то же, что в пункте г), но используется ключ -fomit-frame-pointer;ж) то же, что в пункте д), но используется ключ -fomit-frame-pointer.Задача 4-4Реализуйте следующую функцию на языке ассемблера.
Обратите внимание на то,что возвращаемую структуру можно целиком упаковать в регистр EAX.struct result {short count;short min;};struct result f(short n, short x[n]){struct result ret = { 0, 0 };for (short i = 0; i < n; ++i) {if (ret.min == x[i] && ret.count) {++ret.count;} else if (ret.min > x[i] || !ret.count) {ret.min = x[i];ret.count = 1;}}return ret;}715. Сопроцессор x87 и обработка чисел с плавающейточкойПредставление вещественных чисел – числа с плавающей точкойДля работы с вещественными числами используется представление с плавающейточкой. Число представляется в виде произведения трех множителей (1) S M 2 E .Степень S определяет, является число положительным или отрицательным. Мантисса M – дробное двоичное число в заданном полуинтервале.
В стандарте IEEE 754,задающего правила работы с числами с плавающей точкой, используются полуинтервалы: [1.0, 2.0) для нормализованных чисел и [0.0, 1.0) для денормализованных. Порядок E определяет степень 2 в третьем множителе.Для представления числа в машине необходимо определить правила кодированияэтих трех величин. Стандарт IEEE 754 задает следующий формат:Наибольший значащий бит S непосредственно кодирует знак числа. Поле EXP кодирует порядок числа E. Поле FRAC кодирует мантиссу M.
Количество битов, выделяемых для кодировки мантиссы и порядка, определяют тип данных (Таблица ???) ихарактеризуют точность представления чисел.Таблица 4. Размеры полей для некоторых типов данных .ТипРазмерЗнак SМантисса M Порядок EОдинарная точностьfloat32 бита1238Двойная точностьdouble64 бита1521180 битов16415Расширенная точностьТипы float и double определены в стандарте языка Си, расширенная точность реализована в аппаратуре архитектуры IA-32.Число получает нормализованное представление в заданном типе данных, еслиразмеров полей хватает для кодировки S, M и E по следующим правилам.Пусть для кодировки порядка имеется k битов.
В поле EXP кодируется целое числоE bias , где bias 2k 1 1 . Поле EXP не может содержать одни нули или единицы.При этом мантисса должна принадлежать полуинтервалу [1.0, 2.0). В поле FRACпишется последовательность битов, кодирующая дробную часть мантиссы (т.
е. ве-72дущая 1 отбрасывается). Если мантисса является периодической двоичной дробью,то при выделении битов, помещаемых в поле FRAC, происходит округление.Если число слишком мало (по модулю), оно представляется в денормализованномвиде. Поле EXP заполняется нулями, порядок E принимается равным 1 bias , а мантисса должна в этом случае принадлежать полуинтервалу [0.0, 1.0).
В поле FRACпишется последовательность битов, кодирующая дробную часть мантиссы (т. е. ведущий 0 отбрасывается). При необходимости выполнятся округление.Для подавления ошибок округления стандарт IEEE 754 предлагает округление кближайшему четному числу. В случае если из двоичной дроби отбрасывается однаединица, то округляют к тому числу, у которого наименьшая значащая цифра четная, т. е.
0.Пример 5-1 Перевод числа в модельную кодировкуИспользуется 10-битный формат, удовлетворяющий требованиям стандартаIEEE 754: знаковый бит, 4 бита – порядок, 5 битов – мантисса. Требуется представить в данном формате числа -⅕ и 105.Решение88 1 (1)1 23 , таким образом S = 1, M = , E = -3. Поскольку для кодировки555порядка выделено 4 бита bias 241 1 7 , а EXPПереводим= -3 + bias|7 = 4 = 01002.8в периодическую двоичную дробь разложением по степеням двой5ки.8624 1 20 21 1 20 1 21 22 1 20 1 21 0 22 23 555586 1 20 1 21 0 22 0 23 24 1 20 1 21 0 22 0 23 1 24 25 ...55Собираем коэффициенты перед степенями двоек и получаем периодическуюдробь:8 1.100(1100) 2 .