Если произойдет сбой с «неопределенной ссылкой на« сохраненную_спаму »» (которая действительно является ошибкой компоновщика , а не ошибкой компилятора), когда saved_sp
равен static
, но работает, когда это не так,тогда кажется вероятным, что компилятор решил, что saved_sp
не используется в вашем исходном файле, и поэтому решил полностью исключить его из скомпилированного кода, который передается ассемблеру.
Компилятор непонять код сборки внутри блока asm
;он просто вставляет его в код сборки, который он генерирует.Таким образом, он не знает, что блок asm
ссылается на saved_sp
, и если ничего из кода C никогда не читает из него, он может решить, что он полностью не используется, особенно если у вас включены какие-либо опции оптимизации.
Вы можете сказать gcc
, что saved_sp
используется чем-то, что оно не может видеть, и, следовательно, предотвратить его выбрасывание, добавив атрибут used
(см. документация переменных атрибутов , примерно на полпути вниз страницы), например:
static long __attribute__((used)) saved_sp;
Вот полностью обработанный пример:
$ cat test.c
#ifdef FIXED
static long __attribute__((used)) saved_sp;
#else
static long saved_sp;
#endif
int main(void)
{
__asm__ __volatile__ (
"movq saved_sp, %rsp\n\t" );
}
$ gcc -m64 -o test test.c
$ gcc -m64 -O1 -o test test.c
/tmp/ccATLdiQ.o: In function `main':
test.c:(.text+0x4): undefined reference to `saved_sp'
collect2: ld returned 1 exit status
$ gcc -m64 -DFIXED -O1 -o test test.c
$
(Это от 32-битная система сжатия Debian с gcc 4.4.5, которая является самой близкой вещью, которую я должен вручить; -m64
вполне может быть ненужным в вашей системе.)