Арифметические операции с double - Assembler

Узнай цену своей работы

Формулировка задачи:

Здравствуйте, я пишу небольшую DLL на C++, но при большом объёме входных данных, она очень сильно загружает процессор, вероятно из-за большого количества обращений к структурам. В ходе оптимизации кода, некоторые структуры пришлось упразднить, заменяя их массивами, а большинство обращений удалось избежать путём копирования данных в локальные переменные. После чего код стал работать в двенадцать раз быстрее, чего-то я вероятно не знаю. Суть проблемы заключается в том, что функция round, очень загружает процессор, в теории можно прибавлять к числу 0.5, а после приводить их к типу int. Мой вопрос, будет ли это оптимальным решением или же лучше сделать вставку на assembler'е? Если да, то как это можно реализовать?
Отступление:
У меня очень много вопросов связанных с программированием, получить образование я не могу, нет, в теории могу, но... Сейчас учусь на автомеханика, до этого пол года проучился в БГТУ, на специальность "мехатроника и робототехника", так вроде называлась. Я попал на первый набор по этой специальности и у меня попался очень хороший куратор. Вышло вообще всё очень забавно, заявляюсь я к нему в кабинет и говорю что не хочу учиться, и тут слово за слово он предложил мне поучаствовать в проекте, нужно было написать программу для контроллера и для компьютера, чтобы последний мог с ним взаимодействовать, посылать команды, получать данные. Так как я был ещё только на первом семестре обучения, у меня были лишь, если так можно выразиться, основы C++, которые небольшими усилиями, пребегая к методу научного тыка, я освоил. Но дабы я глубже понял как работает контроллер, он предложил писать мне его на assembler'е, мне на тот момент было всё равно на чём писать, однако именно этот язык даёт почувствовать код и уверенность в его точности. Когда пишешь на более высокоуровневых языках, нужно иметь большой набор специфических знаний, чтобы понимать как оно работает, коего у меня нет, но очень хотелось бы приобрести. Писать под контроллер было очень интересно и весело, у меня была "небольшая" инструкция, по его работе, в ней описывалась работа всех интерфейсов, регистров и много всего интересного, а самое главное, и почти единственное чем я пользовался, так это список всех доступных команд, всего их было около сотни или чуть больше, но так или иначе, благодаря усилиям куратора и моему энтузиазму, серьёзного непонимания в устройстве контроллера у меня не возникало. В итоге программы были написаны, только лишь передачу данных с контроллера на компьютер я освоить не смог, я тогда был жутко не опытным, а для решения данной проблемы, требовалось освоение WINAPI. Может быть я написал всё это не в том месте где надо, но так или иначе я написал всё это с одной целью, попросить содействия с изучением программирования, любая литература, желательно чего-нибудь по лаконичнее, или же просто помощь, не подумайте что я наглею, я не на чём не настаиваю, вы можете просо проигнорировать эту просьбу. Программированием я занимаюсь как хобби и бросать его не собираюсь, уж больно хорошо меня понимает компьютер, возможно оно когда нибудь перерастёт в профессиональную деятельность, на что я очень надеюсь, но не хорошо загадывать на перёд. Спасибо всем кто потратил своё время на прочтение моей небольшой автобиографии и надеюсь на то, что кто-нибудь отзовётся.

Решение задачи: «Арифметические операции с double»

textual
Листинг программы
__declspec(naked) int __stdcall round(double d)
{   
    __asm fld   qword ptr [esp+4] 
    __asm fistp dword ptr [esp+4] 
    __asm mov eax, [esp+4] 
    __asm ret 8
}

Объяснение кода листинга программы

Ссылка на описание инструкций: [http://www.felixcloutier.info/x86-instruction-reference/][1]

  1. Объявлена функция с именем round, которая принимает один аргумент типа double.
  2. Используется атрибут __declspec(naked), который указывает компилятору, что функция не имеет тела и необходимо сгенерировать тело функции на ассемблере.
  3. Используется атрибут __stdcall, который указывает, что функция вызывается стандартным способом (через стек вызовов).
  4. Используется инструкция __asm, которая позволяет вставить ассемблерный код в тело функции.
  5. Используется инструкция fld, которая загружает значение из памяти в регистр x87 для выполнения операций с плавающей запятой.
  6. Используется инструкция fistp, которая сохраняет значение из регистра x87 в памяти.
  7. Используется инструкция mov, которая перемещает значение из регистра eax в память по адресу [esp+4].
  8. Используется инструкция ret, которая возвращает управление в вызывающую функцию и передает возвращаемое значение в eax.
  9. В качестве аргумента для функции round используется переменная d, которая содержит значение типа double.
  10. Используется адрес [esp+4] для хранения результата операции.
  11. Используется адрес [esp+4] для передачи аргумента функции round.
  12. Используется адрес [esp+4] для сохранения результата операции.
  13. Используется адрес [esp+4] для загрузки значения из памяти.
  14. Используется адрес [esp+4] для передачи значения в инструкцию fld.
  15. Используется адрес [esp+4] для передачи значения в инструкцию fistp.
  16. Используется адрес [esp+4] для передачи значения в инструкцию mov.
  17. Используется адрес [esp+4] для передачи значения в инструкцию ret.
  18. Используется значение 8 в инструкции ret, чтобы указать, что функция должна вернуть 8 байт.
  19. Используется значение 0x8 для передачи в инструкцию ret.
  20. Используется значение 0x8 для передачи в инструкцию ret.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 4.222 из 5
Похожие ответы