有没有办法在 GCC 中禁用内联汇编程序?

Is there a way to disable inline assembler in GCC?

我正在为LeetCode,Codeforces等编程竞赛开发一个在线评委系统。对于大多数编程竞赛,C/C++不允许使用内联汇编,所以我想添加对我的系统有同样的限制。

我想让GCC和G++在编译包含内联汇编的C/C++程序时产生错误,这样任何包含内联汇编的代码都会导致编译错误。

有办法实现吗?我应该将一些命令行参数传递给 GCC/G++ 吗?

注意:禁用内联汇编只是为了遵守规则,并非出于安全考虑。

有没有办法在 GCC 中禁用内联汇编程序?

是的,有几种方法。

关闭编译器中的汇编

要在编译阶段完成,使用参数-fno-asm。但是,请记住,这只会影响 asm 而不会影响 __asm__

文档:

-fno-asm

Do not recognize "asm", "inline" or "typeof" as a keyword, so that code can use these words as identifiers. You can use the keywords "__asm__", "__inline__" and "__typeof__" instead. -ansi implies -fno-asm.

In C++ , this switch only affects the "typeof" keyword, since "asm" and "inline" are standard keywords. You may want to use the -fno-gnu-keywords flag instead, which has the same effect. In C99 mode (-std=c99 or -std=gnu99), this switch only affects the "asm" and "typeof" keywords, since "inline" is a standard keyword in ISO C99.

定义宏

可以使用参数-Dasm=error -D__asm__=error

请注意,此构造是通用的。它的作用是创建宏。它的工作原理与 #define 非常相似。文档说:

-D name=definition

The contents of definition are tokenized and processed as if they appeared during translation phase three in a #define directive. In particular, the definition will be truncated by embedded newline characters.

...

所以它所做的只是将 asm__asm__ 的出现次数更改为 error。这是在预处理器阶段完成的。您不必使用 error。只需选择任何不会编译的东西。

使用在编译期间触发的宏

zwol评论中提到的在编译阶段使用宏解决的方法,可以使用-D'asm(...)=_Static_assert(0,"inline assembly not allowed")'。如果存在名为 error.

的标识符,这也将解决问题

注意:此方法需要-std=c11或更高。

在使用 gcc 之前先使用 grep

另一种可能解决您的问题的方法是在编译之前在源代码树的根目录中执行 grep

grep -nr "asm"

这也会捕获 __asm__ 但它可能会产生误报,例如,如果您有一个包含子字符串 "asm" 的字符串文字、标识符或注释。但在你的情况下,你可以通过禁止在源代码中的任何地方出现该字符串来解决这个问题。只是改变规则。

可能出现的意外问题

请注意,禁用程序集可能会导致其他问题。例如,我不能将 stdio.h 与此选项一起使用。系统头文件包含内联汇编代码是很常见的。

一种欺骗上述方法的方法

可以将字符串作为机器码来执行。有关示例,请参见此答案:

上面link的一段代码:

/* our machine code */
char code[] = {0x55,0x48,0x89,0xe5,0x89,0x7d,0xfc,0x48,
0x89,0x75,0xf0,0xb8,0x2a,0x00,0x00,0x00,0xc9,0xc3,0x00};

/* copy code to executable buffer */    
void *buf = mmap (0,sizeof(code),PROT_READ|PROT_WRITE|PROT_EXEC,
            MAP_PRIVATE|MAP_ANON,-1,0);
memcpy (buf, code, sizeof(code));

/* run code */
int i = ((int (*) (void))buf)();

上面的代码只是为了快速了解如何欺骗 OP 规定的规则。它无意成为如何在现实中实际执行它的一个很好的例子。此外,代码不是我的。这只是我提供的 link 中的一个简短代码引用。如果您有关于如何改进它的想法,请评论 4pie0:s 原来的 post。