【反馈篇】因果律:从数值计算到标志位反馈
前言: 在 4-bit 架构中,ALU(算术逻辑单元)不是在做数学题,而是在进行位层面的肉搏。
首先介绍一下ALU的数据结构:
/** * @brief ALUResult 模拟硬件输出引脚 * value: 4根数据线 * carry: 进位线 (对于俄罗斯方块:处理8位坐标拼接) * zero: 零信号线 (对于俄罗斯方块:碰撞检测的核心) * sign: 符号线 (对于俄罗斯方块:判定左/上越界) */ struct ALUResult { uint8_t value; // 4-bit 结果 (0-15) bool carry; // 进位/借位 bool zero; // 零标志 bool sign; // 符号标志 (结果最高位为1则为true) };
它是 CPU 运算核心与状态机之间的“物理接口协议”,功能归纳为三项职责:
- 数据载体 (Value):提供本次运算截断后的 4 位有效值,完成物理层面的数据转换。
- 边界监测 (Carry/Sign):由于 4-bit 空间极小,它负责监控运算是否突破了数值边界(进位/借位)或逻辑边界(正负号)。
- 逻辑属性提取 (Zero):实时提取结果的统计特性。它不关心数值是多少,只回答“结果是否消失”,这是实现程序分支跳转(Branching)的唯一判据。
- 硬件层面:它模拟了 ALU 硬件引脚的输出电平。
- 软件层面:它将枯燥的算术运算转化为可供汇编指令(如
JZ,JC)使用的“决策素材”。没有这个结构体,CPU 就只是一个计算器,无法根据计算结果改变自己的行为。
ALUResult 不仅仅是一个简单的数值返回,它是 数据(Value) 与 元数据(Flags) 的集合。在 4-bit 架构中,计算的数值往往只是过程,而随之产生的状态信号(标志位)才是驱动后续逻辑的真正核心。
下面我来讲讲这个解构具体做了什么:
- 数据宽度(Value 0-15):这是硬件层面的“物理边界”。在 4-bit 架构下,一切宏大的数值都必须被降维、切碎,并在有限的 16 种状态内寻求最优解。
在 4-bit 架构中,0~15 的边界不仅是一个数值限制,对只有4个比特位最多可以表达15这个整数,它更像是一堵“逻辑围墙”。由于绝大多数现实需求(如坐标计算、内存寻址、得分统计)都远超 15,这导致整个体系的运行效率面临巨大的挑战。
一、 0-15 边界对效率的致命影响寻址能力的剧减(Address Bottleneck)1.能力的剧减(Address Bottleneck)
影响:如果用 4 位作为地址,我们只能管理 16 个内存格位,连存储俄罗斯方块的一个方块形状都不够。
效率损耗:为了寻址到之前设计的 256B 或 2KB 空间,CPU 必须被迫进入“长短腿”模式。取一个地址,总线要折返跑 2-3 次,导致执行一条 STA 指令的周期是现代 64 位机的数倍。2.解析的极度碎片化(Fetch Inflation)
影响:操作码(Opcode)只有 16 种可能。
效率损耗:当你需要 30 条指令时,不得不使用“前缀码”进行二次译码。这意味着 CPU 还没开始干活,就先花掉一个周期去识别“这是哪条扩展指令”。3.逻辑的“级联负担”(Propagation Delay)
影响:比如需要计算 (10 + 10)。
效率损耗:在 8 位机上一条指令搞定,但在 4 位机上,由于结果 20 溢出了 15,你必须先算低 4 位,处理进位,再算高 4 位。算力效率直接跌破 50%。
- 进位链路(Carry Flag):它是打破 4 位边界的唯一通讯协议。当运算结果溢出时,Carry 位锁存了那个关键的 1-bit,使得 4 位机具备了通过“多次往返”处理 8 位甚至 16 位数据的逻辑可能。
硬件层面:它打破了“只有 4 根数据线”的物理锁存,实质上将 CPU 的瞬时状态扩展到了 5 位。如果没有这个 1-bit 的硬件触发器,任何超越 15 的计算都会导致数据丢失。而4-bit ALU 只能处理从 (0000) 到 (1111) 的电平组合。当两个 4 位数相加产生第 5 位信号时,数据总线已经无法承载。此时,Carry 标志位充当了一个外部存储位。这引入了时序依赖。下一条指令(如 ADC 或 JC)必须能够读取这个锁存的状态。这要求硬件体系必须具备“跨指令周期”的状态保持能力,是 CPU 从简单的组合逻辑电路进化为时序逻辑系统的标志。硬件必须在 ALU 完成运算的瞬间,将溢出信号锁存到状态寄存器(Status Register)中。
软件层面:进位标志是程序员用来“以时间换空间”的终极武器,虽然硬件是 4 位的,但通过进位标志作为“接力棒”,软件可以实现 8 位、16 位甚至任意位宽的计算。
比如一个大于4位的计算步骤如下
第一步:执行 ADD(不带进位加),算低 4 位,结果溢出到 Carry。
第二步:执行 ADC(带进位加),将高 4 位的数据与 Carry 标志位相加。
这让软件具备了处理宏大数据结构(如 12-bit 内存地址、万分位得分)的能力。其代价是执行效率下降(算一次加法需要多条指令和多次内存访问)。这样硬件是 4 位的,但通过进位标志作为“接力棒”,软件可以实现 8 位、16 位甚至任意位宽的计算。在《俄罗斯方块》中,当方块尝试向右移动时,可以通过对坐标进行 SHL(左移)。如果 Carry 变为 1,说明坐标超出了当前的 Nibble 边界。这时它成为了条件跳转指令(如 JC, JNC)的触发源。软件通过监听这个 1-bit 的状态,决定程序的走向,究竟是是继续移动方块,还是判定为撞墙。所以Carry 标志位不仅用于加法,还常用于位移(Shift)和比较(Compare)指令。硬件通过 Carry 位释放了溢出的能量,而软件则通过 Carry 位重建了失去的精度。 它是连接“硬件位宽受限”与“软件逻辑无限”之间唯一的通讯协议。在汇编层面分析一下这是如何做到的:
;我们自定义的指令集asm 计算 8 位加法:RegA(低4位) + RegB(高4位) CLC ; 清除进位标志(初始化协议) ADD A, op1 ; 处理低 4 位,进位存入 Carry ADC B, op2 ; 带着 Carry 算高 4 位,完成跨位宽协作
- 逻辑栅极(Zero Flag):计算的终点。它不关心数值的大小,只关心“是否存在”。在处理图形碰撞时,它是最无情的逻辑闸口——只要 AND 运算结果有一位非零,Zero 位就会熄灭,从而切断方块继续移动的指令流。
零标志位(Zero Flag) 在本质上是一个全零检测电路。它作为 ALU 状态监控器,并不参与数值计算,而是实时反映数据总线的‘零状态(Null State)’。在硬件实现上,ALU 内部集成了一个多输入或非门(NOR Gate),直接对 4 位结果线(D_0, D_1, D_2, D_3)进行电平监控。仅当所有结果位均为逻辑低电平(0)时,该 NOR 门才会输出逻辑高电平(1),从而触发状态更新。在流水线的取指执行循环中,这一瞬时信号将被锁存(Latch)至状态寄存器。由于该标志位直接挂载在控制单元(CU)的指令分支入口上,其反馈优先级极高。它直接控制着条件跳转指令(如 JZ)对程序计数器(PC)的改写权限:若 Z 标志位为低电平(0),分支逻辑门将处于关闭状态,强制 CPU 顺序执行下一条指令;反之,若标志位被激活,PC 寄存器将被重载,实现程序流向特定逻辑(如‘方块移动’子程序)的跳转。
总结: ALUResult 是将 ALU 内部瞬时的电平状态封装而成的“逻辑快照”,它为 4-bit 处理器的指令执行流提供了从“数值计算”转化为“分支决策”的信号基础。
---------------------------------------------------------------------------------------------
- ADD & ADC:文明的接力。在 0-15 的边界下,我们如何通过进位标志(Carry Flag)的传递,用 4 位机拼接出 8 位甚至 16 位的算术野心?
- AND & OR / XOR:地牢里的感官与魔法。我们将揭秘
AND指令如何化身为“碰撞检测”的探测雷达,以及XOR如何在不占用额外显存的前提下,实现图形的无损擦除与绘制。 - SHL / SHR:空间的位移手术。面对 10 列像素与 4 位总线的不对称矛盾,位移指令是如何在内存格位之间进行精密的“比特平移”的?
- CMP:不留痕迹的审判。为什么一条不改写任何寄存器的“虚假减法”,竟是程序执行流进行生死决策(JZ/JC)的前驱核心?
posted on 2026-05-06 14:03 P_P_thoughts 阅读(32) 评论(0) 收藏 举报
浙公网安备 33010602011771号