第五期“一生一芯”第四课 -- 从C语言到二进制程序
1. 预处理 = 文本粘贴 + 去除注释 gcc -E
可以通过 gcc --verbose(阅读工具的日志)来查看头文件是如何被编译器找到的(可以使用 gcc --verbose > /dev/null 丢掉预处理的结果,只看verbose的内容)
在 C 编程语言中,#warning 指令类似于#error 指令,但不会导致取消预处理。#warning 指令之后的信息在预处理继续之前作为消息输出。 来源:https://blog.csdn.net/wuxiaopengnihao1/article/details/124997255
1.5 类函数宏
2. 编译
编译包括:词法分析、语法分析、语义分析、中间代码生成、中间代码优化、目标指令生成、目标指令集相关优化等。
(视频介绍了很多 clang 的相关选项,可以支持程序员查看 clang 的细节行为,包括优化用了哪些选项,生成的中间代码,针对优化结果的统计等等)
3. 汇编(把汇编代码翻译成二进制代码)
一般要使用 binutils 来阅读二进制文件,比如 objdump, readelf 等等
4. 链接 (合并多个目标文件,生成可执行文件)
使用 --verbose 观看链接过程,可以看到很多 crtxxx.o 文件
crt = C runtime,C语言运行时环境(的一部分)
可以通过 objdump 确认(使用动态链接的函数不会被包含在反汇编文件里 )
5. 执行
通过一些配置工作, RISCV的程序可以在本地(x86)执行
6. implementation-defined behavior and ABI
想搞清楚上述行为的原因,需要去了解工具的实现,而不是自己瞎猜
比较好的做法是,用过日志观察工具的行为
比如 clang,可以打印出词法分析结果、语法分析结果、语义分析结果等等,可以通过这些内容来判断编译过程中发生了什么
此外,还可以结合 C90/C99 手册来理解编译过程
什么是ABI?implementation-defined behavior 卸载了哪个文档里?
关于跨平台开发的头文件 <stdint.h>
在进行数值比较的( ==,>=, <= )时候,数据类型会被扩展,比如 char 有可能被扩展成 int
可以通过ABI手册了解 implementation-defined behavior
a
啊