Эквивалент голого атрибута GCC

У меня есть приложение, написанное на чистом C, смешанное с некоторыми функциями, содержащими чистый ASM. Атрибут Naked недоступен для x86 (почему? Почему ?!), и мои функции asm не любят, когда пролог и эпилог возятся со стеком. Возможно ли каким-то образом создать чистую функцию ассемблера, на которую можно ссылаться из частей кода C? Мне просто нужен адрес такой функции ASM.


person kjagiello    schedule 04.12.2011    source источник
comment
Вы можете сделать это. Используйте подходящую для вашей ОС функцию, чтобы сделать область памяти исполняемой.   -  person Alexey Frunze    schedule 04.12.2011


Ответы (3)


Просто используйте asm() вне функционального блока. Аргумент asm() просто игнорируется компилятором и передается непосредственно ассемблеру. Для сложных функций отдельный исходный файл сборки - лучший вариант, чтобы избежать неудобного синтаксиса.

Пример:

#include <stdio.h>

asm("_one:              \n\
        movl $1,%eax    \n\
        ret             \n\
");

int one();

int main() {
        printf("result: %d\n", one());
        return 0;
}

PS: Убедитесь, что вы понимаете соглашения о вызовах вашей платформы. Часто вы не можете просто скопировать / прошить ассемблерный код.

PPS: если вам важна производительность, используйте вместо этого расширенный asm. Расширенный asm по существу встраивает ассемблерный код в ваш код C / C ++ и работает намного быстрее, особенно для коротких ассемблерных функций. Для более крупных функций сборки предпочтительнее отдельный исходный файл сборки, поэтому этот ответ действительно является хаком для того редкого случая, когда вам нужен указатель функции на небольшую функцию сборки.

person Mackie Messer    schedule 04.12.2011
comment
Это то, что я искал! Спасибо за объяснение. - person kjagiello; 04.12.2011
comment
asm() внешние функциональные блоки не работают в c99. - person hauzer; 10.10.2013
comment
@hauzer попробуйте __asm или __asm__ вместо asm. - person Mackie Messer; 10.10.2013
comment
@hauzer В переносимой программе c99 может быть глобальная переменная с именем asm, которая конфликтует с этим расширением GCC. Но имена, начинающиеся с двух знаков подчеркивания, зарезервированы для реализации (например, GCC). Таким образом, расширение GCC может использовать __asm и __asm__ и по-прежнему соответствовать стандарту, но не asm. - person Mackie Messer; 10.10.2013
comment
@MackieMesser: Спасибо за объяснение. - person hauzer; 10.10.2013
comment
Я получил ошибку undefined reference to 'one', и мне пришлось изменить объявление на int one() asm ("_one"); (в Linux). - person Ben C; 04.12.2017

Всем хорошие новости. Разработчики GCC наконец-то реализовали атрибут ((naked)) для x86. Эта функция будет доступна в GCC 8.

person user576557    schedule 31.07.2017
comment
В некотором роде примечание. В GCC 7.1 добавлена ​​поддержка прерываний x86 с attribute((interrupts)) вместе с соответствующей опцией командной строки -mgeneral-regs-only. Реализация оставляет желать лучшего, но она уже не завершена нереализованной. - person Michael Petch; 01.08.2017

Конечно, просто создайте .s файл (источник сборки), который будет запущен через gas (ассемблер) для создания обычного объектного файла.

person Greg Hewgill    schedule 04.12.2011
comment
Если вы используете суффикс .S (заглавная S), ваш ассемблерный код также будет предварительно обработан cpp. - person Mackie Messer; 04.12.2011