2017-02-07 8 views
0

Я пытаюсь скомпилировать некоторые функции C, используя gcc, чтобы не запускать никаких регистров. Я работаю над x86_64. Я пытаюсь использовать no_caller_saved_registers, но все это я получаю это:Gcc, используя атрибут no_caller_saved_registers

предупреждение: директива атрибут «no_caller_saved_registers» игнорируется [-Wattributes]

недействительными Foo() атрибут ((no_caller_saved_registers));

Моим временным решением было написать встроенный пролог и эпилог для сохранения и восстановления всех регистров, но я ДЕЙСТВИТЕЛЬНО предпочитаю, чтобы атрибут работал.

У кого-нибудь возникли проблемы?

+0

Можете ли вы объяснить, что вы НАСТОЯТЕЛЬНО пытаетесь сделать? Я уверен, что вы не можете заставить gcc НЕ использовать регистры в функции - конечно, не для чего-либо сложного, так как большинство инструкций в x86 требуют, чтобы один операнд был как минимум регистром. –

+1

Я использую код сборки, чтобы вызвать эти функции. Я в порядке с ними, используя любые регистры, если они будут их восстанавливать. – user1637056

+0

Я нашел этот флаг компиляции, который имеет значение, которое я хочу, но на весь файл: -fcall-saved-reg. Это не работает корректно в некоторых регистрах (rax, rdx) – user1637056

ответ

0

No_caller_saved_registers только был реализован in June 2016, поэтому он недоступен ни в одном официальном выпуске GCC.

+0

Спасибо большое !!! – user1637056

+0

Обновление: этот атрибут поддерживается для gcc 7.2. Добавляем этот флагов компиляции: gcc-7 main.c -mgeneral-regs-only – user1637056

0

Мне нужна функция, которая не клобует. ЛЮБЫЕ регистры, потому что это своего рода обработчик ошибок страницы. Благодаря предыдущему ответу, мы знаем, что этот атрибут будет поддерживаться в будущих версиях gcc, но пока не является основным.

Без этого атрибута, моя функция, которую я использую в качестве своего рода страница обработчика ошибок, которые не должен колошматить какие регистры значения выглядит следующим образом:

#define PREFIX_SIZE (14l) 
__asm__ volatile ("in: \n\t" 
        "pushf\n\t" 
        "push %rbp\n\t" 
        "mov %rsp,%rbp\n\t" 
        "push %rdi\n\t" 
        "push %rsi\n\t" 
        "push %rdx\n\t" 
        "push %rcx\n\t" 
        "push %r8 \n\t" 
        "push %r9 \n\t" 
        "push %rax\n\t" 
       ); 

void page_fault_handler() { 
    /* 
    * some code here 
    */ 
    __asm__ volatile ("jmp reg_out\n\t"); 
} 

__asm__ volatile ("reg_out: \n\t" 
        "leave\n\t" // what the original code was doing 
        "pop %rax\n\t" 
        "pop %r9 \n\t" 
        "pop %r8 \n\t" 
        "pop %rcx\n\t" 
        "pop %rdx\n\t" 
        "pop %rsi\n\t" 
        "pop %rdi\n\t" 
        "leave\n\t" // my leave 
        "popf\n\t" 
        "ret\n\t"); 

Это явно раздражает, потому что я должен назвать это адрес:

(void*)((ulong)page_fault_handler - PREFIX_SIZE) 

вместо

(void*)page_fault_handler 

Это также приводит к пр oblems при компиляции с флагом оптимизации -O2, поскольку он переупорядочивает метки.

Если вы заметили, я не сохранять RBX вручную здесь, потому что я составил этот код:

gcc -fcall-saved-rbx 

Этот флаг компиляции заставляет компилятор сохранять и восстанавливать RBX в начале и в конце функции. Так почему же я не просто делаю это для всех регистров? Потому что это вызывает внутреннюю ошибку компилятора для rax: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79407