我在一次采访中被问到PUSH
是POP
RISC 还是 CISC 指令。我说它们是 RISC,但他们告诉我它们实际上是 CISC 指令。我建议 ARM(一种常见的 RISC 实现)有这些指令,但他们指出 ARM 是混合的,不再是纯粹的 RISC。
我在网上找不到任何明确的证据。指令是否真的被认为是 CISC 架构的标志PUSH
,POP
或者它们会在 RISC 系统上找到?为什么?
我在一次采访中被问到PUSH
是POP
RISC 还是 CISC 指令。我说它们是 RISC,但他们告诉我它们实际上是 CISC 指令。我建议 ARM(一种常见的 RISC 实现)有这些指令,但他们指出 ARM 是混合的,不再是纯粹的 RISC。
我在网上找不到任何明确的证据。指令是否真的被认为是 CISC 架构的标志PUSH
,POP
或者它们会在 RISC 系统上找到?为什么?
RISC 的意思是“精简指令集”(通常是 LOAD reg、STORE 寄存器、ADD 寄存器、CMP 寄存器、条件分支 + 其他一些)。
概念和经验是,复杂指令通常无法实现简单指令序列无法实现的有用效果,特别是如果将用于实现此类复杂指令的额外逻辑投入到使简单 RISC 指令运行时快点。
PUSH 和 POP 基本上是 STORE/LOAD 间接的简单组合,并在寄存器中添加一个常量。因此,如果一个专用寄存器用于堆栈指针,则很容易模拟 PUSH 和 POP,并且快速流水线机器执行 PUSH 和 POP 的速度可能与相应的 RISC 指令一样快。所以大多数人认为 PUSH 和 POP 是 CISC 指令;他们并没有真正给你买很多东西。
如果您考虑 CALL (== PUSH PC + JMP) 和 RET (POP PC),生活会变得更加有趣。这些也很容易在正确的 RISC 架构上进行模拟。但是,POP PC 会导致管道泡沫,因为处理器很难预测新 PC 的位置,因此无法进行预取。由于内存“在时间上很远”,这可能是具有大量子例程调用的代码的主要性能抑制因素。
在这里,有一种想去CISC。您真正想要的是某种方式来预测返回 PC。许多现代 CPU 通过在硬件中保留“影子调用堆栈”来做到这一点。每个 CALL 将 PC 推入内存堆栈,同时也推入影子堆栈;每个 RET 从内存堆栈中弹出一个 PC 值,但使用影子堆栈的顶部条目预测指令流流,它本质上是零时间访问(当然,弹出影子堆栈)。这样指令流不会被中断,因此 CISC 机器在性能上获胜。
(有人想知道,如果一台具有大量寄存器的 RISC 机器,编译后的叶函数调用总是使用一个寄存器来存储返回的 PC,可能不如影子堆栈有效。Sun Sparc 有点用它的寄存器窗口来做到这一点)。
这告诉我们的是,RISC 与 CISC 过度简化了设计权衡。你想要的很简单,除非更多的复杂性实际上给你带来了一些东西。例如,硬件中的 IEEE 浮点比使用 RISC 指令的任何模拟都要快得多。
因此,大多数现代机器都不是 RISC 或 CISC。性能分析选择。
“RISC”对不同的人意味着不同的东西。我见过的定义包括:
减少指令数量
固定大小的指令(可能很多)
加载/存储架构(可能有很多可变大小的指令)
不将指令转换为微操作且没有“微代码”的 CPU(例如 8086、8088、80186,...,但不是 80486、Pentium,...)
上述两种或多种事物的任意组合
任何为了降低开发成本而牺牲性能的东西
PUSH/POP 指令被认为是 RISC 还是 CISC?
是(PUSH/POP 指令被认为是 RISC 或 CISC,或两者兼有,或两者都不是;取决于何时应用 RISC 或 CISC 的定义)。
大多数情况下,这个问题本身就是一种错误的二分法。比如问“灰色是黑色还是白色?”。