不得不说,X-macro 真是个好魔法
详细说一下 X-macro 是啥:
当有如下定义时
#define REGS_FOREACH(_) _X _Y
#define DEFINE(X) static int X, X##1;
#define UPDATE(X) X = X##1;
#define PRINT(X) printf(#X " = %d; ", X);
C语言代码中写:
REGS_FOREACH(DEFINE); 会变成
DEFINE(X) DEFINE(Y) 变成
static int X, X1; static int Y, Y1;
如此一来,可以达到批量进行某一操作的效果。
只要在 REGS_FOREACH(_) 这个宏后面添加上所有需要进行同一操作的变量,那么就可以用这个宏配合所需的操作,对所有变量进行同一个操作
使用 C 语言模拟状态机,再把它的输出传递给 python 数码管模拟器
gdb命令:
layout src: 展示源码
info frame 可以展示更加详细的帧状态,如下
显示了所用的参数列表、局部变量等
可以用模拟栈来代替递归(将任何递归程序就地转为非递归),如下图
这段模拟栈的代码非常值得细读
在 gdb 中,使用 p 打印一个结构体变量时,可以清楚地看到每个结构体成员的值
构造最小的 Hello world
如上图这种使用 -static 的方式,会编译出非常非常多的代码(可以使用反汇编看一下)
(关于构造最小的Hello world这一段在53:30,如果不记得,很值得反复看)
使用正确的工具 -- gdb 去观测程序(状态机)的执行
非常推荐看看 gdb 的官方文档
状态机视角真的很棒
当代码执行到 retq 时会报错,因为我们这个最小 Hello world 的初始状态是不可返回的
使用 $status 环境变量可以观察到上一个程序的退出码
TODO:为什么在右边的minimal.S中,汇编代码中可以使用 #include <sys/syscall.h>?
什么是正确的优化?S 和 C 的可观测行为严格一致
这个问题等价于在问:操作系统给程序的初始状态是什么?
gdb使用:info proc mappings 可以打印进程的内存(或者说,内存地址空间)