Вы пишете в отдельное место назначения, поэтому нет никаких совпадений между чтением и письмом. Это делает его довольно простым: вы выполняете цикл от первого до последнего одного массива и начинаете с середины другого массива с переносом.
например, начинаете с первого элемента места назначения и используете ветвь для условновычтите длину (в байтах) из указателя src. (Разветвление - хороший выбор по сравнению с cmov, потому что оно будет истинным только один раз; каждый раз, когда вы просто зацикливаетесь в обычном режиме.)src до конца, затем от начала до середины.
Вы можете даже использовать для этого rep movsd
дважды вместо циклов, оставляя edi
неизменным, чтобы продолжать добавлять пункт назначения, но сбрасывая esi
вчитать с начала источника. (Если вы не собираетесь использовать векторы SIMD, rep movsd
быстрее, чем цикл копирования 4 байта за раз, вероятно, для 10 элементов или более. Или с инструкцией slow-on-Intel loop
точка безубыточности еще ниже.)
Для задачи фиксированного размера вы, конечно, можете просто загрузить все это в 4 регистра или использовать SSE2 movdqu
-load / pshufd
/movdqu
- хранить, чтобы перетасовать куски меча 16-байтового вектора SIMD.
Если вам нужно было выполнить это вращение на месте (обновление одного массива вместо создания модифицированной копии), вы можете жестко закодироватьчасть «поворот на 2 позиции» по переменной длине, использующая пару чистых регистров для обработки перекрытия между записью и чтением.
Я не собираюсь публиковать код, потому что это выглядит как домашняя работа, и яне показывать пример, не просто решив его.
Но arrayType DWORD TYPE array
выглядит как плохая идея. TYPE array
- постоянная времени сборки;Вы не хотите хранить его в памяти и загружать как данные, просто используйте его как непосредственный, как вы делаете с ADD ESI, TYPE array
lastElement DWORD ?
также не используется, и опять же, это хорошо,Используйте регистры (до тех пор, пока вы не закончите) для кусков с одним мечом в царапинах.