首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >程序在 CPU 里到底是怎么跑的

程序在 CPU 里到底是怎么跑的

作者头像
Lihua奏
发布2026-06-23 20:32:01
发布2026-06-23 20:32:01
1210
举报

CPU

CPU 和内存,本质上都属于集成电路(Integrated Circuit,IC)。

CPU 内部大致由下面几部分组成:

  • 寄存器:用来存放指令、数据这些操作对象的空间
  • 控制器:把内存中的指令和数据读进来,并根据指令结果去控制计算机
  • 运算器:负责做运算
  • 时钟:产生控制 CPU 工作节律的时钟信号

内存,这里通常说的是主存储器。它由可读写的存储元件构成,每个字节都分配了一个编号,这个编号就叫地址

很多人会把“128G”“256G”这种东西叫内存,但严格来说,那一般说的是存储空间,不叫主存。它通常对应的是硬盘、SSD 这类存储设备。

寄存器

为什么要把寄存器单独讲?

因为它是程序运行时非常核心的描述对象。

先看看它为什么会出现。

在没有寄存器的时候,数据和程序都放在内存里,执行过程大致就是:

CPU <- 内存(取指令/数据)

CPU -> 内存(写回结果)

但问题来了。

cpu运算速度极快,大约0.3纳秒,而内存的速度,大约100纳秒,内存太慢了,严重拖累cpu的速度

因此,寄存器出现了,它的速度大约为1纳秒

那问题又来了,为什么不直接用寄存器去替代内存,这不快多了吗?

  1. 寄存器是属于CPU的一部分,是无法塞下过多的寄存器的
  2. 过多的寄存器,会使电路过多
  3. 寄存器贵(越精密的东西越贵)

看到这里,你能发现一个规律:

从 CPU -> 寄存器 -> 内存 -> 硬盘 速度是越来越慢的,但容量刚好反过来,是越来越大的。

这其实就是计算机里一个很经典的取舍:

越快的东西,通常越贵、越小。越大的东西,通常越慢。

机器语言和汇编语言

机器语言指令的本质是电子信号。

但电子信号人看不懂,所以人们就用一些英语单词或者缩写,去表示这些指令的功能,这就成了汇编语言。

所以你可以先这样记:

  • CPU 真正执行的是机器语言
  • 汇编语言只是更方便人去读和写

把汇编语言变成机器语言的过程,叫**汇编(assemble) 反过来把机器语言还原成汇编形式,就叫反汇编(disassemble)**。

在机器语言这个层面上,程序的大部分操作,本质上都是围绕寄存器完成的。

寄存器也分很多种类型:

程序到底是怎么一条条跑起来的

当然,只有一行程序是干不了什么事的。

那程序是怎么按照指定顺序一条条运行的?

这里有个非常关键的角色: 程序计数器

你可以把它理解成:

它专门记着“下一条要执行哪一行”。

CPU 每执行完一条指令,程序计数器通常就自动指向下一条。 如果遇到跳转、函数调用这些情况,程序计数器就会被改成别的地址。

流程意思:把 123 和 456 两个数值相加,并输出到屏幕中

程序流程大致分三种:

  • 顺序执行
  • 条件分支
  • 循环

上面这种一条一条往下走的,就是顺序执行。

条件分支

条件分支的意思就是:

如果满足某个条件,那就别往下老老实实走了,直接跳去别的地方。

可以看出,当 0102 的条件被满足时,程序会跳转到 0104。

那 CPU 怎么知道“条件满足了没有”呢?

这里就要用到标志寄存器

标志寄存器不会去保存“累加器和通用寄存器的值”,它保存的是上一次运算之后的结果状态

比如:

  • 结果是不是 0
  • 结果是不是负数
  • 运算时有没有进位

CPU 在每次运算后,都会自动根据结果去改这些标志位。

然后到了条件跳转这里,CPU 就看标志寄存器里的状态,决定跳还是不跳。

循环

循环本质上其实没有那么神秘。

它就是:

条件分支 + 跳回去再来一次

比如你想把 1 加到 100:

  • 先加一次
  • 看看有没有到 100(判断)
  • 没到,就跳回去继续(跳转)
  • 到了,就结束

这里能看出,循环就是 "判断" + "跳转"

函数调用的原理

先来看什么是函数。

早期程序如果什么都从头写到尾,就会有一个很明显的问题:

有些逻辑完全一样,难道每次都重新写一遍?

于是人们就想到:

能不能把一段重复的代码单独放在一个地方,需要的时候跳过去执行,执行完再回来?

于是函数就出现了。

同时也有了两种很关键的指令:

  • 调用指令(CALL):在把函数入口地址设置到程序计数器之前,先把“调用后下一条指令的地址”保存到栈里
  • 返回指令(RET):把保存在栈里的地址取出来,再放回程序计数器

你可以把它理解成:

  • CALL 像“先记住回来位置,再跳过去”
  • RET 像“按着刚才记住的位置跳回来”

如何实现数组

这里会用到两个寄存器:

  • 基址寄存器:存放一段数据在内存中的起始地址
  • 变址寄存器:存放相对这个起始地址的偏移量

说得再白一点:

  • 基址寄存器 = 数组从哪开始
  • 变址寄存器 = 我要取第几个

比如:

数组起始地址是 每个元素占 4 个字节 我要取下标为 3 的元素1000

那实际地址就是:

1000 + 3 × 4 = 1012

也就是说,数组下标并不是直接“写在内存里”的,而是通过:

起始地址 + 偏移量

算出来的。

计算机内存地址范围 ,32 位寄存器就可以访问全部地址。00000000 ~ FFFFFFFF

而访问连续内存,比如数组,用基址寄存器和变址寄存器会更高效。因为你不用每次都重新找一整块地址,只要知道“从哪里开始,偏多少”就够了。

总结:

程序之所以能跑起来,就是CPU对下面这个过程不断重复:

  1. 从内存里取指令
  2. 把数据放到寄存器里
  3. 做运算或者判断
  4. 根据结果修改程序计数器
  5. 再去执行下一条

所以你看到的程序,表面上是一大堆代码。

但到了 CPU 这一层,它其实就是:

取指令、放寄存器、做运算、判断要不要跳、然后继续往下跑。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-06-02,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • CPU
  • 寄存器
  • 机器语言和汇编语言
  • 程序到底是怎么一条条跑起来的
  • 条件分支
  • 循环
  • 函数调用的原理
  • 如何实现数组
  • 总结:
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档