LINUX.ORG.RU

Проблема с asm-вставками, C++


0

1

Никак не могу заставить проект, активно использующий асм-вставки, работать.

void Hook_strangepacket();
asm(".intel_syntax noprefix\n"
    "_Hook_strangepacket:\n"
    "add     esp, 0x0FFFFFFE0\n"
    "lea     edx, [esp+4]\n"
    "lea     eax, [ebp+8]\n"

    "lea		ecx, [esp+0x30]\n"
    "pushad\n"
    "push	3\n"
    "push	ecx\n"
    "call %P0\n" : : "i"(AddWarns) //ошибка: expected «)» before «:» token
    "add		esp, 8\n"
    "popad\n"
    "push	0x08057125\n"
    "ret\n"
    ".att_syntax\r\n"
);
Дело в том, что мне нужно создать naked-функцию, т.е. без прологов и эпилогов. Почему-то создатели g++ отказываются реализовывать поддержку атрибута naked для платформы IA32, поэтому приходится реализовывать функцию целиком на ассемблере. Но когда из-за «call AddWarns\n» появлялась ошибка undefined symbol: AddWarns, мне пришлось, погуглив, переделать её в «call %P0\n» : : «i»(AddWarns). Однако такая запись ну никак не хочет работать, если эта строка объявлена не в теле функции. Т.е. такая запись:
void Hook_strangepacket(){
    asm(".intel_syntax noprefix\n"
        "add     esp, 0x0FFFFFFE0\n"
        "lea     edx, [esp+4]\n"
        "lea     eax, [ebp+8]\n"

        "lea		ecx, [esp+0x30]\n"
        "pushad\n"
        "push	3\n"
        "push	ecx\n"
        "call %P0\n" : : "i"(AddWarns)
        "add		esp, 8\n"
        "popad\n"
        "push	0x08057125\n"
        "ret\n"
        ".att_syntax\r\n"
    );
}
...вполне компилируема, вот только генерирует прологи и эпилоги. Как быть?


Ответ на: комментарий от r2d2

В том-то и проблема, что __attribute__ ((naked)) не поддерживается ни для чего кроме ARM, AVR, MCORE, RX и SPU. Никакого ответа кроме «вы не сможете сделать рабочую naked-функцию» создатели g++ не дали. А проблему я решил тем, что для всех вызываемых и naked функций прописал extern «C», и после этого call AddWarns заработал.

Balbes
() автор топика

«call %P0\n» : : «i»(AddWarns)

После этого сразу закрывающая скобка и точка с запятой. Хоть бы сначала прочитал вообще, как писать ассемблерные вставки. Сначала ВЕСЬ код, потом «:», потом output, потом «:», потом input, потом «:», потом изменяемые регистры. Т.е. в данной ситуации просто надо текст «: : «i»(AddWarns)» перенести в самый конец, иначе получается, что код продолжается в 3-ей секции с инпутами.

gentoo_root ★★★★★
()
Ответ на: комментарий от gentoo_root

Хотите верьте, хотите - нет, но я пробовал. Я пробовал разбивать построчно на asm(...). Кстати, неправильный у меня второй пример, который работал. Работал этот:

void Hook_strangepacket(){
    asm(".intel_syntax noprefix");
    asm("add     esp, 0x0FFFFFFE0");
    asm(lea     edx, [esp+4]");
    asm("lea     eax, [ebp+8]");
    asm("lea		ecx, [esp+0x30]");
    asm("pushad");
    asm("push	3");
    asm("push	ecx");
    asm("call %P0" : : "i"(AddWarns));
    asm("add		esp, 8");
    asm("popad");
    asm("push	0x08057125");
    asm("ret");
    asm(".att_syntax");
}

Balbes
() автор топика

Сделай отдельный файлик для своих ассеблерных ф-ий, funcs.s какой-нибудь, и компеляй его в объектник, который потом линкуй в свой чудопроект.

nanoolinux ★★★★
()

Скажите что вы пишете чтобы я случайно этим не воспользовался.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.