为什么gcc不支持裸功能?

are*_*s94 6 c++ linux gcc g++

我在程序运行时使用裸函数来修补程序的各个部分.我可以在Windows中的VC++中轻松完成此操作.我试图在Linux中这样做,似乎gcc不支持裸功能.用裸函数编译代码给了我:警告:'naked'属性指令被忽略了.在CentOS 5.5 i386下编译.

Upr*_*ted 6

===更新===

截至 2023 年,它们确实有效:

__attribute__((naked))    
void my_write(int fd, char const* str, int size) {
    asm
    (
    "       pusha                              \n\t"
    "       movl   $4, %eax                    \n\t"
    "       movl   36(%esp), %ebx              \n\t"
    "       movl   40(%esp), %ecx              \n\t"
    "       movl   44(%esp), %edx              \n\t"
    "       int    $0x80                       \n\t"
    "       popa                               \n\t"
    "       ret                                \n\t"
    );
}

void _start() {
    my_write(1, "hi\n", 3);
    my_write(1, "bye\n", 4);
}
Run Code Online (Sandbox Code Playgroud)

编译gcc -m32 -nostdlib my_write.c使用gcc version 10.2.1 20210110 (Debian 10.2.1-6)

===旧答案===

在 x86 上,您可以通过在全局范围内使用 asm 来解决:

void my_write(int fd, const void *buf, int count);                                            
                                                                                 
asm                                                                              
(                                                                                
".global my_write                          \n\t"
"my_write:                                 \n\t"
"       pusha                              \n\t"
"       movl   $4, %eax                    \n\t"
"       movl   36(%esp), %ebx              \n\t"
"       movl   40(%esp), %ecx              \n\t"
"       movl   44(%esp), %edx              \n\t"
"       int    $0x80                       \n\t"
"       popa                               \n\t"
"       ret                                \n\t"
);

void _start()
{
    my_write(1, "hi\n", 3);
    my_write(1, "bye\n", 4);
}
Run Code Online (Sandbox Code Playgroud)

naked列在x86 函数属性中,所以我认为它适用于较新的 gcc。


Dav*_*son 5

根据文档,仅 GCC 在某些平台(ARM、AVR、MCORE、RX 和 SPU)上支持裸属性:

naked: 在ARM、AVR、MCORE、RX 和SPU 端口上使用该属性来表示指定的函数不需要编译器生成的序言/尾声序列。由程序员提供这些序列。唯一可以安全地包含在裸函数中的语句是没有操作数的 asm 语句。应避免使用所有其他语句,包括局部变量的声明、if 语句等。裸函数应该用于实现汇编函数的主体,同时允许编译器为汇编器构造必要的函数声明。

我不知道为什么。

  • @Seth:汇编代码中使用的指令可以有操作数,但“asm 语句”并不意味着汇编指令,它是整个`asm(“一些insns”:outputblah:inputblah:clobberblah);`。“blahs”是 asm 语句的操作数,如果没有编译器生成的序言,就不能使用它。您可以编写汇编程序,但不能将其连接到 C 变量。 (4认同)