Можно ли автоматически увеличивать базовый адрес регистра в STR с помощью [ Rn]!
? Я просмотрел документацию, но не смог найти окончательного ответа, в основном потому, что синтаксис команды представлен как для LDR, так и для STR - теоретически он должен работать для обоих, но я не мог не нашел примеров автоинкремента в магазине (загрузка работает нормально).
Я сделал небольшую программу, которая хранит два числа в векторе. Когда это сделано, содержимое out
должно быть {1, 2}
, но хранилище перезаписывает первый байт, как будто автоинкремент не работает.
#include <stdio.h>
int main()
{
int out[]={0, 0};
asm volatile (
"mov r0, #1 \n\t"
"str r0, [%0]! \n\t"
"add r0, r0, #1 \n\t"
"str r0, [%0] \n\t"
:: "r"(out)
: "r0" );
printf("%d %d\n", out[0], out[1]);
return 0;
}
РЕДАКТИРОВАТЬ: Хотя ответ был правильным для обычных загрузок и сохранений, я обнаружил, что оптимизатор портит автоинкремент для векторных инструкций, таких как vldm / vstm.Например, следующая программа
#include <stdio.h>
int main()
{
volatile int *in = new int[16];
volatile int *out = new int[16];
for (int i=0;i<16;i++) in[i] = i;
asm volatile (
"vldm %0!, {d0-d3} \n\t"
"vldm %0, {d4-d7} \n\t"
"vstm %1!, {d0-d3} \n\t"
"vstm %1, {d4-d7} \n\t"
:: "r"(in), "r"(out)
: "memory" );
for (int i=0;i<16;i++) printf("%d\n", out[i]);
return 0;
}
, скомпилированная с помощью
g++ -O2 -march=armv7-a -mfpu=neon main.cpp -o main
, будет выдавать тарабарщину на выходе последних 8 переменных, потому что оптимизатор сохраняет увеличенную переменную и использует ее для printf. Другими словами, out [i]
на самом деле out [i + 8]
, поэтому первые 8 выводимых значений - это последние 8 из вектора, а остальные - области памяти вне границы.
Я пробовал использовать различные комбинации ключевого слова volatile
во всем коде, но поведение меняется только при компиляции с флагом -O0
или если я использую изменчивый вектор вместо указателя и новый, например
volatile int out[16];