当执行汇编指令MOV [0001H] 01H时,计算机都做了什么?

简介: 今天和几位单位大佬聊天时,讨论到一个非常有趣的问题-当程序执行MOV [0001H], 01H计算机实际上都做了哪些工作?乍一看这个问题平平无奇,CPU只是把立即数01H放在了地址为0001的内存里,但仔细想想这个问题远没有那么简单,由于现代计算机体系中CPU速度比内存要快2到3个个数量级,因此从CPU执行MOV指令,到实际把01H写入内存之间,还有非常漫长而复杂的过程。

今天和几位单位大佬聊天时,讨论到一个非常有趣的问题-当程序执行MOV [0001H], 01H计算机实际上都做了哪些工作?乍一看这个问题平平无奇,CPU只是把立即数01H放在了地址为0001的内存里,但仔细想想这个问题远没有那么简单,由于现代计算机体系中CPU速度比内存要快2到3个个数量级,因此从CPU执行MOV指令,到实际把01H写入内存之间,还有非常漫长而复杂的过程。

为了回答好这个问题,我翻阅了一些资料,发现不同时代的CPU在执行这个操作时,行为也不一样,下面分享一下我的成果。

一.386及之前的CPU

从现在的角度来看,386及以前的CPU完全是上古时期的物件,还没有指令流水线的概念,当CPU执行这条汇编指令时,会和我们的第一印象差不多,基本会是按照以下步骤进行工作:

1.取指、译码,简单说就是从可执行文件中把MOV的二进制表示100010翻译出来。

2. 取操作数,将立即数01H加载到内部寄存器。

3. 取内存地址,将内存地址0001H(地址为0001的内存单元,不考虑段寄存器加偏移量的形式)加载到内部寄存器。

4. 指令执行,将内存地址0001H所指向的内存单元与内部寄存器中的数据(即01H)进行写入操作,完成将01H写入到内存单元000H1的操作。

二.486与酷睿之前的CPU

这个阶段的CPU和386相比增加了指令流水线的概念,我们知道CPU的每个动作都需要用晶体震荡而触发,想完成一个最简单的指令也需要取指、译码、取操作数、执行以及获取操作结果等若干步骤,而每个步骤都需要一次晶体震荡才能推进,因此在流水线技术出现之前执行一条指令至少需要5到6次晶体震荡周期才能完成。

指令/时刻

T1

T2

T3

T4

T5

MOV

取指

译码

取操作数

执行

取结果

而流水线的思想就是将不同指令的译码、寻址、执行等操作,放在一个震荡周期中并发完成。

指令/时刻

T1

T2

T3

T4

T5

T6

T7

T8

指令1

取指

译码

取操作数

执行

取结果

指令2

取指

译码

取操作数

执行

取结果

指令3

取指

译码

取操作数

执行

取结果

指令4

取指

译码

取操作数

执行

取结果

指令5

取指

译码

取操作数

执行

指令6

取指

译码

取操作数

指令7

取指

译码

指令8

取指

但上述升级对于MOV [0001H] 01H指令的执行没有带来太多本质变化。

三、酷睿后的现代多核CPU

在2006年英特尔发布一代酷睿处理器之后,现代桌面CPU正式进入了多核时代,现代CPU在执行指令时会和内存交互,但CPU本身只是直接操作高速缓存而不会直接操作内存。

现代X86 CPU的高速缓存(Cache),包括多级缓存(L1、L2、L3)。高速缓存是位于CPU内部的一块快速访问的存储区域,用于临时存储从主内存中读取的指令和数据。当CPU需要访问内存时,它首先会检查高速缓存,如果所需数据已经存在于高速缓存中,CPU会直接从高速缓存中读取或写入数据,无需访问主内存。其中L1和L2为每个CPU核心的专属缓存,L3为各核心的共享使用。 CPU多核心之间的高速缓存同步一般按照MESI协议进行,即每个缓存行都有四个状态,分别是E(exclusive)、M(modified)、S(shared)、I(invalid),说明如下:

M:代表该缓存行中的内容被修改,并且该缓存行只被缓存在该CPU中。这个状态代表缓存行的数据和内存中的数据不同。

E:代表该缓存行对应内存中的内容只被该CPU缓存,其他CPU没有缓存该缓存对应内存行中的内容。这个状态的缓存行中的数据与内存的数据一致。

I:代表该缓存行中的内容无效。

:该状态意味着数不只存在在本地CPU缓存中,还存在其它CPU的缓存中。这个状态的数据和内存中的数据也是一致的。不过只要有CPU修改该缓存行都会使该行状态变成 I 。

四种状态的状态转移图如下:

编辑切换为居中

添加图片注释,不超过 140 字(可选)

在初始执行MOV [0001H] 01H,实际执行这条语句的核心上会触发local write的动作,这实际会把内存地址对应的缓址行置为Modify状态,而Modify状态下内存和缓存的内容实际是不一致的。而01H到底会不会被写回内存也是需要讨论的。

01H被显式写入内存0001H:这种情况也有其他其它核心也发起了对于0001H地址的读取操作,即发起remote read,在这种情况缓存的状态会从Modify迁移到Share状态,而Share状态下缓存中的数据会被显示的写回内存。也就是MOV [0001H] 01H被实际执行完成。

01H未被写入内存0001H:这种情有其他其它核心发对于地于0001H的写操作,即发起remote wri,e,这种情况下,在这种情况缓存的状态会从Modify迁移到Invalid状态,而Invalid状态下的调整缓存数据不会再被写入内存了。

01H的内存写入状态未知:如果0001H地址的读写一直由同一核心操作,那么这种情况下缓存的状态就一直是Modify,那么这时候01H是否被写入内存,就取决于0001H这个内存地址是否能始终处于热点访问状态了,如果该地址一直在缓存中不被换出的话,那么01H的值有可能不会被写入内存,只有当该地址从缓存中换出时才会触发内存的回写操作。

总之,现代的CPU在执行MOV [0001H] 01H这样一条平平无奇的指令时,其实背后也做了很多工作,甚至操作完成后01H的值到底有没有写入到内存地址0001H也是很不确定的,希望通过本文梳理各阶段CPU执行MOV [0001H] 01H指令的过程,可以帮助读者更好的理解现代CPU的工作原理。

相关文章
|
2月前
|
存储 Unix 编译器
汇编语言----X86汇编指令
汇编语言----X86汇编指令
43 1
|
2月前
|
存储 机器学习/深度学习 移动开发
汇编语言指令系列
汇编语言指令系列
135 0
|
2天前
|
存储 算法 安全
深入理解汇编语言:基础语法和常用指令介绍
深入理解汇编语言:基础语法和常用指令介绍
|
15天前
汇编语言(第四版) 实验一 查看CPU和内存,用机器指令和汇编指令编程
汇编语言(第四版) 实验一 查看CPU和内存,用机器指令和汇编指令编程
|
7天前
|
C语言
程序技术好文:部分ARM汇编指令解读
程序技术好文:部分ARM汇编指令解读
|
2月前
|
安全 编译器
8086 汇编笔记(四):[BX] 和 loop 指令
8086 汇编笔记(四):[BX] 和 loop 指令
|
2月前
|
Shell C语言 SoC
计基2—RISCV指令集介绍与汇编
计基2—RISCV指令集介绍与汇编
37 1
|
2月前
|
存储 C++
C/C++中的整数除法运算与汇编指令DIV和IDIV
C/C++中的整数除法运算与汇编指令DIV和IDIV
34 1
|
2月前
|
程序员
深入理解汇编:平栈、CALL和RET指令详解
深入理解汇编:平栈、CALL和RET指令详解
26 1
|
2月前
理解汇编中的CALL指令和参数传递
理解汇编中的CALL指令和参数传递
50 1