Проблема встроенной сборки GNU
Я провел некоторый рефакторинг кода для платформы c167 и наткнулся на проблему встроенной сборки.
Предыдущий код:
asm volatile ( "
extp #pag:%0, #3
mov r4, pof:%0 @ R4 = g_nRcvBufCount
sub r4, #1 @ R4 = R4 - 1
mov pof:%0, r4 @ g_nRcvBufCount = R4"
: "=m" (g_nRcvBufCount)
:
: "r4"
);
[
В основном этот код выполняет атомарный декремент переменной "g_nRcvBufCount"
Инструкция "extp" принимает "страницу" переменной "g_nRcvBufCount" и количество следующих атомарных выражений (3 в данном случае)
]
Текущий - не компилируемый код:
asm volatile ( "
extp #pag:%0, #3
mov r4, pof:%0 @ R4 = cfg->g_nRcvBufCount
sub r4, #1 @ R4 = R4 - 1
mov pof:%0, r4 @ cfg->g_nRcvBufCount = R4"
: "=m" (cfg->g_nRcvBufCount)
:
: "r4"
);
где cfg - указатель на структуру, содержащую переменную "g_nRcvBufCount".
struct {
...
unsigned short g_nRcvBufCount;
...
}cfg;
Ошибки, полученные при компиляции:
test.c:1124:Warning:Missing operand value assumed absolute 0.
test.c:1124:extp #pag:[r2+#66],#3: trailing chars after expression
test.c:1125:Warning:Missing operand value assumed absolute 0.
test.c:1125:mov r4,pof:[r2+#66]: trailing chars after expression
test.c:1127:Warning:Missing operand value assumed absolute 0.
test.c:1127:mov pof:[r2+#66],r4: trailing chars after expression
Любые советы о том, как сделать эту работу, приветствуются. Также была бы полезна версия x86 (встроенной сборки) о том, как получить доступ к переменным, определенным в структуре C/C++. Документация встроенного ассемблера GNU, объясняющая, что делает ключевое слово "= m", также полезна.
Заранее спасибо,
Юлиан
2 ответа
Посмотрите на asm в предупреждающем сообщении:
extp #pag:[r2+#66],#3
Видимо #pag:
вещь допустима с регистром или абсолютным адресом после нее, но не с более сложным выражением, уже содержащим смещение, подобное [r2+#66]
, Возможно, вам придется перейти на использование "r"
аргумент, содержащий адрес cfg->g_nRcvBufCount
вместо "m"
аргумент, ссылающийся на это.
Если это так, обратите внимание, что исходный код был поддельным с самого начала и работал только потому, что gcc решил заменить простое адресное выражение, которое работало в asm.
Из ибиблио
"m": разрешен операнд памяти с любым типом адреса, который машина поддерживает в целом.
насчет "ошибок" - это "только" предупреждения - попробуйте создать небольшой файл.c с этой сборкой, разобрать его и посмотреть, как его выводит objdump. это может дать вам подсказку о том, как редактировать код, чтобы не было этих предупреждений.