Skip to content

GoPavel/assembler-course

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Small tasks

  • arctg -- Вычисляет сумму k слагаемых ряда Тейлора арктангенса, учитывая, что формула имеет смысл, только при |x| <= 1.
float __cdecl arctan(float x, uint k);
  • arctg_scalar -- скалярная версия на xmm
  • arctg_vector -- векторная версия на xmm

Big tasks

Task 1

Написать функцию, выполняющую преобразование числа из шестнадцатеричной записи в десятичную отформатированную.

Прототип функции:

void print(char *out_buf, const char *format, const char *hex_number);

Входное шестнадцатеричное число 128-битное, со знаком в двоичном дополнительном коде. Перед числом может быть символ '-', который следует интерпретировать строго как "инвертировать все биты входного числа и добавить 1", что полезно для ввода отрицательных чисел. Буквы могут быть любого регистра.

Строка формата подобна формату функции sprintf, но необходимо реализовать только небольшое подмножество: флаги '-', '+', ' ', '0' и поле ширины (width).

В выходной буфер должна быть записана ноль-терминированная строка результата без переводов строки или ещё каких-либо лишних символов.

Конвенция вызова: cdecl. Название функции в .asm файле: _print. Не забывайте сохранять нужные регистры, если вы их изменяете. Функция должна быть реализована в одном .asm файле и не использовать каких-либо внешних функций, один только .asm файл должен быть приложен к письму.

Пример входных данных: "-5", "10". Результат: "16 ". Для проверки на небольших числах можете использовать следующий код на C:

    int x;
    sscanf("<hex_number>", "%x", &x);
    printf("%<format>i", x);

Мир: x86

Task 2

Преобразование Фурье -- вещь, которая позволяет перейти из частотной в импульсную форму. Оно часто применяется для обработки звука и изображения. А также важно, что его можно написать быстро.

Задание

Требуется написать 2 функции: выполняющие прямое и обратное DCT преобразование размером 16x16.

Прототипы функций:

void fdct(const float *in, float *out);
void idct(const float *in, float *out);

in - указатель на входные данные, out - указатель на выходные данные.

Можно писать как 32-битный, так и 64-битный код. 32-битный код: конвенция вызова cdecl, к именам нужно добавлять символ _ , то есть называться они у вас будут _fdct и _idct. 64-битный код: конвенция вызова fastcall64, к именам не нужно добавлять символ _ , то есть называться они у вас будут fdct и idct.

Обе функции должны быть реализованы в одном .asm файле и не использовать каких-либо внешних функций. Из SIMD расширений разрешается использовать всё вплоть до SSE4.2 включительно.

Входные и выходные данные в памяти не пересекаются и их начала выравнены на границу, кратную 16.

Оцениваться будет как правильность реализации, так и скорость работы.

Функции будут вызываться много раз, так что если вам требуется какая-то начальная инициализация - позаботьтесь, чтобы она не повторялась при каждом вызове.

Написать прямое и обратное преобразование Фурье (двухмерное 16x16) DCT2, DCT3

Заметки:

  • Не нужно писать перемножение матриц, можно сделать это быстрее или удобнее.
  • Есть быстрое преобразование.
  • Нужно попасть с нормировкой.
  • Лучше всего начать с написания кода на C. Тогда можно сравниться с ним по скорости.
  • Не нужно делить ответ на 4, т. к. преобразование линейное можно просто домножить коэффициентны
  • Примеры входных и выходных данных: input_fdct.txt, output_fdct.txt.

Task 3

Задание:

Требуется написать функцию, выполняющую преобразование числа в формате double precision в текстовую десятичную запись.

Прототип функции:

void dbl2str(const double *in, char *out_buf);

В результате выполнения функции в буфере должно быть записано текстовое 0-терминированное представление числа в виде: +0.12345e5 То есть: знак числа, затем "0.", 1+ знаков мантиссы, "e", значение экспоненты (0 для нуля). Должны также поддерживаться денормализованные и не-числа, которые выводятся в виде: +Inf, -Inf, NaN.

Полученная запись должна удовлетворять требованию корректности: обратное преобразование должно дать исходное число при округлении к ближайшему чётному. А также требованию минимальной длины мантиссы. В случае нескольких минимальных вариантов - выбрать ближайший к центру диапазона. Лишние нули и знак "+" в экспоненте выводить не следует.

Конвенция вызова: fastcall64. Не забывайте сохранять нужные регистры, если вы их изменяете. Функция должна быть реализована в одном .asm файле и не использовать каких-либо внешних функций, .asm файл должен быть приложен к письму. Использовать FPU запрещается (не заморачивайтесь - он там совсем не нужен). В буфер должно быть записано не больше 32 байт.

Оцениваться будет как правильность реализации (в частности, допускается несоответствие требованию минимальной длины для небольшого процента чисел), так и скорость работы.

На вход подается вещественное число с плавающей точной двойной точности. Известно, что оно задает диапазон чисел. Из этого диапазон нужно найти число, которое записывается кратчайшим способом в десятичной системе.

Вопросы к экзамену

  1. Регистры общего назначения, сегментные, FPU, MMX, SSE, арифметические и логические команды (сложение, xor, сдвиги...), управляющие структуры (if, циклы, switch).
  2. Команды передачи управления (переходы, вызов функций, возврат), стандартные конвенции вызова функций (cdecl, stdcall, pascal, fastcall, thiscall, fastcall64, unix64).
  3. Команды пересылки данных, система адресации в командах.
  4. Режимы работы процессора. Защищённый режим и страничная адресация, их применение.
  5. SIMD расширения набора команд x86 (MMX и типы данных всех подробно; SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, SSE4A, AVX, AVX2, AVX512, FMA, AES-NI, BMI - обзорно).
  6. Новое и изменения в архитектуре x64 относительно x86.

Все вопросы подразумевают не только архитектуру x86, но и x64.

Кроме теоретического ответа я могу попросить вас написать небольшую программу, особенно в вопросе 5.