Мы разрабатываем приложение для Atmel AVR32 / UC3C0512C с использованием AtmelStudio 7.0.1645. Выполняя некоторые базовые тесты, я заметил кое-что очень странное.
Пожалуйста, рассмотрите следующий код (я знаю, что это плохой стиль и необычный, но здесь дело не в этом):
float GetAtan2f(float p_f_y,
float p_f_x)
{
unsigned int l_ui_x,
l_ui_y,
l_ui_Sign_x,
l_ui_Sign_y,
l_ui_Result;
float l_f_Add,
l_f_Result;
asm volatile(
"RJMP GETATAN2_EXIT \n"
:
: /* 0 */ "m" (p_f_y),
/* 1 */ "m" (p_f_x)
: "cc", "memory", "r0", "r1", "r2", "r3", "r5"
);
GETATAN2_EXIT:
return (l_f_Result);
}
При просмотре разборки этого кода (после его компиляции / компоновки) я обнаружил следующее:
Disassembly of section .text.GetAtan2f:
00078696 <GetAtan2f>:
78696: eb cd 40 af pushm r0-r3,r5,r7,lr
7869a: 1a 97 mov r7,sp
7869c: 20 9d sub sp,36
7869e: ef 4c ff e0 st.w r7[-32],r12
786a2: ef 4b ff dc st.w r7[-36],r11
786a6: e0 8f 00 00 bral 786a6 <GetAtan2f+0x10>
786aa: ee f8 ff fc ld.w r8,r7[-4]
786ae: 10 9c mov r12,r8
786b0: 2f 7d sub sp,-36
786b2: e3 cd 80 af ldm sp++,r0-r3,r5,r7,pc
Мы замечаем, что rjmp
стало bral
- вполне приемлемо, просто еще одна мнемоника для того же.
Но, глядя на цель ветвления в этой строке, мы также замечаем, что это создаст бесконечный цикл , чего явно не должно быть. Он должен перейти на 786aa
(что является началом возврата функции) вместо 786a6
.
Если я изменю код так, чтобы он читался
float GetAtan2f(float p_f_y,
float p_f_x)
{
unsigned int l_ui_x,
l_ui_y,
l_ui_Sign_x,
l_ui_Sign_y,
l_ui_Result;
float l_f_Add,
l_f_Result;
asm volatile(
"RJMP GETATAN2_EXIT \n"
:
: /* 0 */ "m" (p_f_y),
/* 1 */ "m" (p_f_x)
: "cc", "memory", "r0", "r1", "r2", "r3", "r5"
);
asm volatile(
"GETATAN2_EXIT: \n"
:
:
: "cc", "memory"
);
return (l_f_Result);
}
работает как положено, т.е. разборка теперь читает
Disassembly of section .text.GetAtan2f:
00078696 <GETATAN2_EXIT-0x12>:
78696: eb cd 40 af pushm r0-r3,r5,r7,lr
7869a: 1a 97 mov r7,sp
7869c: 20 9d sub sp,36
7869e: ef 4c ff e0 st.w r7[-32],r12
786a2: ef 4b ff dc st.w r7[-36],r11
786a6: c0 18 rjmp 786a8 <GETATAN2_EXIT>
000786a8 <GETATAN2_EXIT>:
786a8: ee f8 ff fc ld.w r8,r7[-4]
786ac: 10 9c mov r12,r8
786ae: 2f 7d sub sp,-36
786b0: e3 cd 80 af ldm sp++,r0-r3,r5,r7,pc
Мы заметили, что цель ветки теперь верна.
Таким образом, встроенный ассемблер, очевидно, не знает о метках C (т. Е. Метках, которые не находятся во встроенной сборке), которые сами по себе были бы O.K. - урок усвоен.
Но кроме этого он не предупреждает и не выдает ошибки, когда встречает неизвестную (неопределенную) метку, а вместо этого создает бесконечные циклы, просто используя смещение 0 при переходе / переходе к таким меткам .
Я считаю последний катастрофической ошибкой. Это, вероятно, означает, что (без какого-либо предупреждения) я получу бесконечный цикл в моем программном обеспечении всякий раз, когда я использую неопределенную метку во встроенном коде сборки (например, из-за опечатки).
Что я могу с этим поделать?