Как использовать глобальную переменную в встроенной сборке gcc - PullRequest
8 голосов
/ 11 января 2012

Я пытаюсь использовать встроенную сборку, как это, для глобальной переменной, но компилятор выдает ошибку, говоря неопределенную ссылку на сохраненный_сп .

__asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );

сохраненный_сп объявлен как static long saved_sp глобально (для файла, который есть). Какую ошибку я здесь делаю?

Ответы [ 3 ]

6 голосов
/ 11 января 2012

Если произойдет сбой с «неопределенной ссылкой на« сохраненную_спаму »» (которая действительно является ошибкой компоновщика , а не ошибкой компилятора), когда 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 вполне может быть ненужным в вашей системе.)

1 голос
/ 30 июля 2014

Желательно использовать входные и выходные параметры:

__asm__ __volatile__ ( 
    "movq %0, %%rsp\n\t"
    : : "r"(saved_sp) : "memory"
);

Часто на этапе сборки могут быть некоторые переменные, которые вообще не являются символами (например, переменные стека или регистры. Также выЯ хотел бы сжать всю память, чтобы гарантировать, что никакие переменные стека не будут храниться в регистре после того, как saved_sp сохранен в RSP.

1 голос
/ 11 января 2012

Как я указал в комментариях, следующие компилируются (и генерируют правильный машинный код), используя gcc 4.4.4 на 64-битной Ubuntu:

long saved_sp;

int main() {
  __asm__ __volatile__ (
        "movq saved_sp, %rsp\n\t" );
}

Возможно, проблема может заключаться в чем-то другом (отсутствует #include, так что saved_sp на самом деле не определен? edit : теперь, когда вы говорите, что это static, я думаю, это не очень вероятно .)

...