84、【OS】【Nuttx】【启动】栈溢出保护:asm 关键字(下)
【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
背景
接之前 blog
【OS】【Nuttx】【启动】栈溢出保护:r10 寄存器
【OS】【Nuttx】【启动】栈溢出保护:asm 关键字(上)
前面分析了 r10 寄存器,以及 asm 和 __asm__ 等保留标识符的区别和联系,下面最后再补充下
asm 和 __asm__ 关键字
实际上,除了 asm 和 __asm__ 关键字,gcc 还能兼容 __asm 标识符,比如下面的代码(__asm 标识符没被 C 语法标亮,说明本身也不是正式的写法,不过也没报错)
终端输入
arm-none-eabi-gcc -std=c89 -S -mcpu=cortex-m4 -mthumb main.c -o main.s
可以正常编译,因为上篇 blog 【OS】【Nuttx】【启动】栈溢出保护:asm 关键字 说过,单下划线 _ + 大写字母和以双下划线开头的属于保留标识符,这些标识符可能被编译器,操作系统等底层基础设施使用到,而 gcc 编译器就支持 __asm 标识符
查看 gcc 源码 c-common.cc 文件,可以找到 gcc 编译器支持的保留标识符关键字如下
这里有几个点解释下:
- 这部分注释对于理解 C/C++ 语言中的关键字很重要,在这里不仅定义了 C/C++ 语言的关键字,也定义了 gcc 扩展的关键字,并规范哪些关键字是保留的,在什么条件下启用或禁止
- c_common_reswords 中定义的关键字里面会包含一些属性,这些属性会告诉编译器,在哪种标准模式下它们有效,下面解释下这些常见的属性:
D_CONLY:只属于 C,不属于 C++
D_CXXONLY:只属于 C++,不属于 C
D_C99 / D_C23:分别属于 C99 ,C23 的关键字
D_CXX11 / D_CXX20:分别属于 C++11,C++20 的关键字
D_OBJC / D_CXX_OBJC:属于 Objective-C 或 Objective-C++ 相关的关键字 - 当关键字上的属性匹配上规范上的掩码时,这些关键字将会被屏蔽 disable,比如 --std=c89,他的掩码有 D_C99(C89 不支持 C99 标准的关键字),D_C23(C89 不知 C23 标准的关键字),D_CXXONLY(C89 不支持只属于 C++ 的关键字,比如 class),D_OBJC / D_CXX_OBJC(C89 不支持 OBJC/OBJC++ 相关的关键字)
c_common_resword 类型的定义如下
里面有三个成员:
- word:保留关键字字符串
- rid:保留关键字的数字 ID,r 表示 reserve
- disable:这里的成员命名比较有意思,这里用的是 disable(禁用的意思),前面介绍过一些关键字的属性信息,表示当处于某种标准(模式)下时,比如 C89,或 C99,是否禁用相关的带有属性的关键字,比如 C89 要禁用 C99 的关键字,C99 要禁用 C23 的关键字
此外,结合之前说的,可以找到 asm,__asm__,__asm 关键字
这里有几个细节说下
- __asm 和 __asm__ 相关属性是 0,表示在所有标准(模式),不管 --std=c89,还是c99,c17,c23,或者是 C++/ OBJC/C++ 模式,都不禁用,都可以支持
- asm 的属性是 D_ASM,如果编译选项中有 -fno-asm,则禁用 asm 这个关键字(__asm 和 __asm__ 不受影响,因为它们没有这个属性)
先分析到这儿,下篇继续