Существует некоторая проблема с встроенным ассемблером, который я не мог понять.рычаг; inline asm; использовать регистр царапин;
У меня есть функция с встроенным ассемблером. Внутри блока ASM мне нужно использовать некоторый регистр нуля для изменения некоторого системного значения.
void setHW(uint32_t val) {
asm volatile (
mrc 15, 0, r0, ...
orr r0, r0, %0
mcr 15, 0, r0, ...
: :"r"(val) :"r0"
);
}
На самом деле функция встроена в компилятор, и все в порядке, код все еще работает хорошо.
Проблема возникает, когда я пытаюсь заменить hardcoded r0
на некоторую переменную-заглушку, чтобы компилятор мог выбрать наилучший возможный регистр для использования. Похоже, что этот
void setHW(uint32_t val) {
uint32_t reg;
asm volatile (
mrc 15, 0, %[reg], ...
orr %[reg], %[reg], %0
mcr 15, 0, %[reg], ...
:[reg]"=r"(reg) :"r"(val) :
);
}
Теперь компилятор выбрать регистр сам по себе, но на самом деле коррумпирован значение setHW
функции вызывающего абонента. В дизассемблере это выглядит как
add r2, r4, r5 ; caller part, r2 contain some intermedia result
mrc 15, 0, r2, ... ; inlined setHW(), r2 is choosen as scratch reg
orr r2, r2, r0
mcr 15, 0, r2, ...
; caller continue
Как вы могли видеть r2
повреждены, и все просто развалятся.
Как определить регистр царапин, чтобы этого избежать?
Когда вы добавили '[reg]', val перестали быть '% 0' и стали'% 1'. –
@DavidWohlferd, да спасибо. BTW '[reg]" = r "(reg)' все еще работает неправильно. В некоторых случаях компилятор использует один и тот же регистр для 'val' и' reg', поэтому я получаю 'mrc r3 ...; orr r3, r3, r3; mcr r3 ...; '. '[reg]" + r "(reg)' фактически исправить проблему, но теперь компилятор показывает, что ошибка '' reg 'используется uninitialized ... ', и необходимо присвоить значение дампа' reg', и появится дополнительная инструкция. Не может быть исправлено? – user3124812
Я знаю, что вы уже решили это, но в первом блоке кода я считаю, что проблема, с которой вы сталкиваетесь, заключается в том, что согласно соглашению о вызове ARM EABI первый аргумент функции будет находиться в 'r0', так что код, вероятно, скроет 'uint32_t val' с помощью' mrc 15, 0, r0, ... '. Опять же, обратно в ARM EABI, 'r4-8, r10, r11' считаются« переменными регистрами », поэтому я думаю, что если бы вы использовали один из них, вы бы были хороши. – rjp