CPU 工作 (2)

发布: (2026年2月2日 GMT+8 15:11)
4 分钟阅读
原文: Dev.to

Source: Dev.to

CPU 如何实现循环和条件

虽然 CPU 只对数字进行算术运算,但它仍然可以通过特殊的 分支指令 来改变执行流,从而实现循环和条件分支。

条件跳转 (JZ)

一种典型的条件跳转指令是 JZ(zero 为真时跳转)。当特定标志位(零标志)被置位时,它会把控制权转移到标记的地址。

LOAD A, 1
LOAD B, 1

CMP A, B        ; compare A and B
JZ exit         ; jump to `exit` if the comparison result is zero
STOREM A, 0     ; store register A to memory
exit:
HALT

JZ 检查什么?

JZ 检查标签本身。它查看 Zero 标志 (Z),该标志由前面的 CMP 指令设置。如果标志为真(1),CPU 就跳转到标签标记的地址。

CMP 更新的标志

CMP(比较)指令会把一个操作数从另一个操作数中减去 但不保存结果;它只会更新状态标志:

标志含义
Z(Zero)如果减法结果为零,则置为 1
N(Negative)如果结果为负,则置为 1

在真实的 CPU 中,这些标志位存放在状态/标志寄存器中;在模拟器里可以用一个简单的结构体来保存。

循环示例

循环可以由条件跳转 (JZ) 和无条件跳转 (JMP) 组合而成。

LOAD A, 4
LOAD B, 1
LOAD C, 1

loop:
    SUB A, B          ; A = A - B
    CMP A, C
    JZ exit           ; if A == C, exit loop
    JMP loop          ; otherwise repeat
exit:
    HALT
  • JZ 实现条件退出。
  • JMP 无条件跳回循环起始处。

如果零标志未被置位,执行会继续到 JMP,它始终把控制权转回 loop

CMP 的实现(模拟)

// Subtract operandB from operandA and set flags
int temp = reg.r[inst.operandA] - reg.r[inst.operandB];
flag.zero     = (temp == 0);
flag.negative = (temp < 0);
programCounter++;   // advance to next instruction

关键规则:CMP 不能修改任何寄存器或内存;它只更新标志位。

其他跳转指令

根据 CPU 设计的不同,还可能提供其他条件跳转指令,例如:

  • JG – 大于时跳转(Z = 0 且 N = 0)
  • JL – 小于时跳转(N = 1)
  • JNZ – 非零时跳转(Z = 0)

这些指令使用 CMP 或类似指令设置的相同标志位。

高层代码到 CPU 分支的映射

考虑下面的 C 风格条件语句:

int valueA = 2;
int valueB = 3;

if (valueA == valueB) {
    // do stuff
}

在机器层面,编译器通常会生成:

  1. CMP valueA, valueB – 根据 valueA - valueB 设置标志位。
  2. JZ label – 如果零标志被置位(即两值相等),跳转到代码块。

因此,即使是复杂的高级结构,也会归结为一系列设置标志的比较指令和分支指令。

Back to Blog

相关文章

阅读更多 »