如何区分指令与数据?

Posted

技术标签:

【中文标题】如何区分指令与数据?【英文标题】:How instructions are differentiated from data? 【发布时间】:2011-01-02 14:38:22 【问题描述】:

在阅读ARM核心文档时,我有这个疑问。 CPU如何区分读取数据和数据总线,是作为指令执行还是作为可以操作的数据执行?

参考文档摘录——

"数据进入处理器内核 通过数据总线。数据可能是 执行指令或数据 项目。”

提前感谢您启发我! /MS

【问题讨论】:

【参考方案1】:

每个操作码将包含一个 N 字节的指令,然后它期望随后的 M 字节是数据(内存指针等)。因此 CPU 使用每个操作码来确定以下字节中有多少是数据。

当然对于旧处理器(例如旧的 8 位类型,如 6502 等)没有区别。您通常会将程序计数器指向内存中程序的开头,这将引用内存中其他位置的数据,但程序/数据存储为简单的 8 位值。处理器本身无法区分两者。

完全有可能将程序计数器指向被视为数据的内容,事实上,我记得我的教授在一个旧的大学教程中正是这样做的,我们必须指出错误给他。他的回答是“但那是数据!它不能执行那个!可以吗?”,此时我用有效的操作码填充了我们的数据,以证明它确实可以。

【讨论】:

这个还是可以的。 谢谢布赖恩。因此,通常在复位后不久,PC 会加载读取数据,并将其解释为要执行的指令(操作码 + 操作数等),然后是要操作的数据。一切顺利,直到 PC 和 IR 解码这些指令。否则会发生异常(中止或未定义指令)。 @Neil - 是的。我不想讨论整个细分问题,因为我不熟悉现代 CPU 架构 @MS - 这是正确的。您的异常实际上是一个中断,它强制处理器到一个已知的程序计数器地址,专门用于错误处理,我认为。但我不确定现代 CPU 是如何做到这一点的。 位是位,执行数据意味着获取指令,无论程序计数器如何设置,它现在是指令获取而不是数据获取。【参考方案2】:

简单的答案 - 它没有。机器代码指令只是二进制数,数据也是如此。更复杂的答案 - 您的处理器可能(或可能不)提供内存分段,这意味着尝试执行已指定为数据的内容会导致某种陷阱。这是“分段错误”的含义之一——处理器试图执行一些未被标记为可执行代码的东西。

【讨论】:

内存保护通常是通过分页;现代 ISA 使用包含每页 exec 权限位的页表格式。但是,是的,除了无执行权限之外,如果您跳转到它并且 CPU 将其作为指令获取,它就是代码;如果加载/存储指令将其作为数据访问,则它是数据。【参考方案3】:

我认为这取决于数据在程序中的存储位置以及操作系统是否支持通知 CPU 是代码还是数据。

与存储变量相比,所有代码都放置在图像的不同部分(以及常量字符串等静态数据)。操作系统(和内存管理单元)需要知道这一点,因为它们可以通过简单地丢弃代码并从原始磁盘文件重新加载代码来将代码交换出内存(至少 Windows 是这样做的)。

所以,我认为 CPU“知道”内存是数据还是代码。毫无疑问,我们现在拥有的现代管道 CPU 也有指令以不同方式读取此内存,以帮助 CPU 尽可能快地处理它(例如,代码可能不会被缓存,数据将始终被随机访问,而不是在流中)

仍然可以将程序计数器指向数据,但操作系统可以告诉 CPU 阻止这种情况 - 请参阅 NX 位和 Windows 的“数据执行保护”设置(系统控制面板)

【讨论】:

【参考方案4】:

处理器的每次读取都被称为数据提取或指令提取。所有新旧处理器都知道从数据获取中获取指令。从外部您可能会或可能无法分辨,通常除了哈佛架构处理器之外,ARM 不是。我最近一直在使用 mpcore (ARM11),外部接口上有一些位告诉你它是什么类型的读取,主要是连接外部缓存,结合你是否有 mmu 的知识并且 L1 缓存打开,您可以从指令中分辨出数据,但这是规则的例外。从内存总线的角度来看,它只是数据位,您不知道指令中的数据,但是启动该内存周期并等待结果的逻辑在它开始循环之前就知道它是什么类型的获取以及它将做什么获取数据时使用该数据。

【讨论】:

【参考方案5】:

最初的 ARM 设计有一个用于执行指令的三级流水线:

    将指令提取到 CPU 中 解码指令以配置 CPU 执行 执行指令。

CPU 的内部逻辑确保它知道它是在第 1 阶段(即指令获取)还是在第 3 阶段(即由于“加载”指令而获取数据)获取数据。

现代 ARM 处理器具有用于获取指令的单独总线(因此管道在获取数据时不会停止)和更长的管道(以实现更快的时钟速度),但总体思路仍然相同。

【讨论】:

【参考方案6】:

所以,我认为 CPU“知道”内存是数据还是代码。毫无疑问,我们现在拥有的现代管道 CPU 也有指令以不同方式读取此内存,以帮助 CPU 尽可能快地处理它(例如,代码可能不会被缓存,数据将始终被随机访问,而不是在流中)

【讨论】:

您迟到的答案并没有添加任何以前的答案尚未反映的新内容。 此外,这甚至是不正确的。 “以不同方式读取此内存的说明”?不,代码与数据没有特殊的加载指令。 (ARM 具有用于与代码混合的文字池的短位移 PC 相关负载,但您会尝试用数据填充至少整个高速缓存行,而不是拥有许多小池。

以上是关于如何区分指令与数据?的主要内容,如果未能解决你的问题,请参考以下文章

访问控制列表与策略路由作用区分

带你区分几种并行

Angular 材料 2:如何区分一个组件中的 2 个或多个可排序表?

如何区分代码与数据字节 pefile

如何使用 ReadDirectoryChangesW 区分 ADS(备用数据流)与主流更改

如何查看mysql表名字段是不是区分大小写