Я хочу написать следующий цикл с помощью GCC расширенный встроенный ASM:простой, а контур в НКУ инлайн сборки
long* arr = new long[ARR_LEN]();
long* act_ptr = arr;
long* end_ptr = arr + ARR_LEN;
while (act_ptr < end_ptr)
{
*act_ptr = SOME_VALUE;
act_ptr += STEP_SIZE;
}
delete[] arr;
Массив типа long
с длиной ARR_LEN
выделяется и нулевой инициализируется. Цикл проходит через массив с шагом STEP_SIZE
. Каждому касающемуся элементу присваивается значение SOME_VALUE
.
Ну, это была моя первая попытка в ГАС:
long* arr = new long[ARR_LEN]();
asm volatile
(
"loop:"
"movl %[sval], (%[aptr]);"
"leal (%[aptr], %[incr], 4), %[aptr];"
"cmpl %[eptr], %[aptr];"
"jl loop;"
: // no output
: [aptr] "r" (arr),
[eptr] "r" (arr + ARR_LEN),
[incr] "r" (STEP_SIZE),
[sval] "i" (SOME_VALUE)
: "cc", "memory"
);
delete[] arr;
Как уже упоминалось в комментариях, это правда, что этот ассемблер код больше do {...} while
цикла, но это на самом деле делать ту же работу ,
Странная вещь в этом фрагменте кода на самом деле заключается в том, что сначала она работала нормально. Но когда я позже попытался заставить его работать в другом проекте, казалось, что он ничего не сделает. Я даже сделал несколько 1: 1 копий проекта , скомпилированного снова и ... все же результат случайный.
Возможно, я взял неправильные ограничения для входных операндов, но я на самом деле пытался почти все из них к настоящему времени, и у меня нет реальной идеи. Что меня в чем-то вызывает, в частности, то, что он по-прежнему работает в некоторых случаях.
Я не эксперт в ASM вообще, хотя я узнал об этом, когда был еще в университете. Обратите внимание, что я не ищу оптимизации - я просто пытаюсь понять, как работает встроенная сборка. Итак, вот мой вопрос: есть ли что-то принципиально неправильное в моей попытке или я совершил более тонкую ошибку здесь? Заранее спасибо.
(Работа с г ++ MinGW Win32 x86 v.4.8.1)
Update
Я уже опробовал каждый предложение, которое было внесено здесь до сих пор. В частности, я попытался
- с использованием «д» операнд ограничения вместо «г», иногда это работает, иногда нет,
- писать
... : [aptr] "=r" (arr) : "0" (arr) ...
вместо этого, тот же результата, - или даже
... : [aptr] "+r" (arr) : ...
, все такой же.
Между тем я знаю чиновника documentation в значительной степени наизусть, но я все еще не вижу свою ошибку.
'act_ptr + = STEP_SIZE;' может STEP_SZIE evalve указатель arythmetic, который оставляет границы? Даже если это без разбора? – dhein
Вы уже пробовали сеанс отладки gdb? – mvw
В цикле C++ условие цикла проверяется перед выполнением цикла, но в версии ассемблера вы проверяете его после тела (другими словами, ваш код ассемблера является более «do ... while» (. ..) 'loop). Это означает, что вы можете (и, возможно, сделать) выписать за пределы выделенной памяти. –