程序执行、调用栈与模型边界
编译执行流程与数据表示
前置:能阅读顺序执行、整数运算和栈的压入弹出;Python 3.10+ 用于自定义 32 位有符号栈机。教学范围为RISC-V 20240411非特权ISA概念;自定义栈机;Python 3.10+。核对日期2026-10-17。示例未执行,本轮没有安装依赖、生成协议代码、启动服务或浏览器预览。完整文件与输入见栈机完整程序与输入边界;推演结论只适用于写明的模型。
源码如何变成执行
以表达式7-2为例,前端先确认这是减法节点,后端可以生成机器码,也可以生成PUSH7、PUSH2、SUB供解释器执行。两条路径应实现相同语义,但中间表示和性能代价不同。
查看图表代码
源码如何变成执行有不同路径:编译器把表达式和控制流转换为目标指令,解释器逐项执行中间表示,运行时提供分配和异常等服务。语言本身不必永远绑定一种实现方式;JIT也不会让所有代码始终以同一层级执行。
栈机执行状态
执行SUB前要求至少两个操作数;先取右值2,再取左值7,结果5替换原两个栈项。程序计数器前进并不证明整段程序有效,还需检查最终HALT和单一结果条件。
查看图表代码
栈机执行状态包含程序计数器、操作数栈和指令序列。每条指令定义前置条件和转移,执行后计数器指向下一条。本课小栈机不是RISC-V仿真器,而用显式状态帮助读者理解真实ISA为何必须定义寄存器、异常和指令语义。
位宽与有符号解释
位宽与有符号解释决定同一位模式的数值。八位11111111按无符号解释为255,按补码为-1;溢出行为由语言和指令规定,不能拿Python任意精度整数证明C有符号溢出可绕回。本课显式限制结果为32位有符号范围。
来源与适用边界
- 英文官方、作者或规范原文:本专题机制依据;按上述固定版本族阅读。
- 中文官方或作者资料:用于术语和讲解交叉核对,冲突以原始规范为准。
调用栈、对象寿命与求值顺序
调用栈与求值栈
假设main调用calc,calc再调用helper。helper返回时只撤销自己的调用帧,calc继续执行;表达式求值栈则可能同时保存7与2。二者可在实现中合并或优化,图只表达不同职责。
查看图表代码
调用栈与求值栈用途不同:前者常保存返回地址和局部状态,后者保存表达式操作数。优化可能消除栈帧或把变量放寄存器,源码变量数不等于真实栈槽数。递归深度、尾调用与异常展开应按具体实现讨论。
堆栈与对象寿命
局部变量可以保存堆对象的引用。函数返回时局部引用消失,如果对象仍被全局容器引用,它仍可达;只有所有强引用消失后才可能回收,且回收时刻不等于资源关闭时刻。
查看图表代码
堆栈与对象寿命应分配位置和引用寿命分开。返回指向已失效局部对象的引用可能悬挂;垃圾回收依赖可达性,并不保证外部文件资源及时关闭。所有权或显式清理管理的是资源责任,不只是释放字节。
求值顺序与副作用
求值顺序与副作用直接影响结果。a()-b()必须遵守该语言定义的调用顺序,异常可能阻止后续副作用。小栈机SUB先弹出右操作数,再弹左操作数,计算左减右;调换弹栈顺序会把7-2变成2-7。
来源与适用边界
- 英文官方、作者或规范原文:本专题机制依据;按上述固定版本族阅读。
- 中文官方或作者资料:用于术语和讲解交叉核对,冲突以原始规范为准。
执行模型边界与抽象成本
机器模型遗漏边界
机器模型遗漏边界包括真实内存、并发、分支和调用。本例整数栈没有地址,因此不展示指针越界;异常也只是教学错误文本,不能推断硬件trap实现。模型越简单越容易推演,但每次迁移结论都要重新检查假设。
抽象成本如何验证
模型事件数适合比较同一模型内的工作量。例如一条ADD会经过取指、分派、弹栈和范围检查;在真实运行中还会受到宿主语言和硬件实现影响。应先固定输入、预热与计时范围,再比较同一指标,不能把模型事件数直接换算成纳秒。
查看图表代码
抽象成本如何验证不能只看源码行数。相同表达式可能生成不同指令数;真实性能还受缓存、分支预测、分配与IO影响。解释器一步在宿主语言中可能需要很多机器指令,本课事件数只用于模型复杂度,不是CPU周期。
执行规范阅读方法
执行规范阅读方法从ISA规定的可观察状态出发,再区分实现自由。RISC-V官方固定20240411版本族,中文微软托管执行资料用于比较编译与运行时,不作为RISC-V翻译;自定义栈机语义由本课明确定义。旧补码与IEEE笔记继续可达,特殊浮点值不能套普通规格化公式。
来源与适用边界
- 英文官方、作者或规范原文:本专题机制依据;按上述固定版本族阅读。
- 中文官方或作者资料:用于术语和讲解交叉核对,冲突以原始规范为准。
- 相关既有参考:原URL与专业范围保留;历史案例不能自动代表当前实现。
继续阅读
- 表达式栈机
- 模型代价与规范
- 模型代价与规范