Арифметические операции с 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]
- Объявлена функция с именем round, которая принимает один аргумент типа double.
- Используется атрибут __declspec(naked), который указывает компилятору, что функция не имеет тела и необходимо сгенерировать тело функции на ассемблере.
- Используется атрибут __stdcall, который указывает, что функция вызывается стандартным способом (через стек вызовов).
- Используется инструкция __asm, которая позволяет вставить ассемблерный код в тело функции.
- Используется инструкция fld, которая загружает значение из памяти в регистр x87 для выполнения операций с плавающей запятой.
- Используется инструкция fistp, которая сохраняет значение из регистра x87 в памяти.
- Используется инструкция mov, которая перемещает значение из регистра eax в память по адресу [esp+4].
- Используется инструкция ret, которая возвращает управление в вызывающую функцию и передает возвращаемое значение в eax.
- В качестве аргумента для функции round используется переменная d, которая содержит значение типа double.
- Используется адрес [esp+4] для хранения результата операции.
- Используется адрес [esp+4] для передачи аргумента функции round.
- Используется адрес [esp+4] для сохранения результата операции.
- Используется адрес [esp+4] для загрузки значения из памяти.
- Используется адрес [esp+4] для передачи значения в инструкцию fld.
- Используется адрес [esp+4] для передачи значения в инструкцию fistp.
- Используется адрес [esp+4] для передачи значения в инструкцию mov.
- Используется адрес [esp+4] для передачи значения в инструкцию ret.
- Используется значение 8 в инструкции ret, чтобы указать, что функция должна вернуть 8 байт.
- Используется значение 0x8 для передачи в инструкцию ret.
- Используется значение 0x8 для передачи в инструкцию ret.
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д