我只知道 Forth 语言的作者设计过一些基于栈的小众 CPU 。
https://en.wikipedia.org/wiki/Charles_H._Moore
基于栈的构建,所有参数都可以用栈来传递,感觉指令集可以更精简。
那么为什么市场上没有这样的指令集流行呢?是因为它有什么别的劣势吗?
1
billlee 2023-10-19 17:03:10 +08:00 via Android
1. 手写汇编的时候,基于寄存器的指令集更直观
2. 电路里又没有栈,用栈做指令集还要增加电路来模拟栈的行为,指令集精简但电路却更复杂 |
2
felixlong 2023-10-19 17:03:27 +08:00
1 , 慢。
2 ,java 的指令集就是基于 stack 的。 |
3
wniming 2023-10-19 17:27:33 +08:00
借楼问一下,为啥 x86 使用 16 个通用寄存器而 arm64 使用 31 个?是不是通用寄存器越多 ipc 就会越高?
|
4
summerLast 2023-10-19 17:45:29 +08:00
硬件设计导致的。
寄存器比内存更快(速度更快,离 cpu 更近,但是也小),缓存次之,内存在次之, 容量从小到大 速度从快到慢 寄存器的空间有限,因此要知道哪些是高频数据,利用好它的速度。 我们换个思路去思考这个问题,现在你有一台图灵机的原型,请问如何改进提高性能和响应速度? 据个不是那么恰当的例子:内存是个放在桌子上的记事本,寄存器直接是瞬时记忆 |
5
summerLast 2023-10-19 17:48:41 +08:00
@wniming 历史原因,额,就比如 x86 是复杂指令集的代表 ARM 是精简指令集的代表,但现实是 x86 现在里面有许多指令最后执行的指令的复杂度也和 ARM 没太大区别了。
|
6
summerLast 2023-10-19 17:50:31 +08:00
@wniming 理论是越高,但我们有那么多高频数据吗?,所以结果是提升有限。
|
7
UN2758 2023-10-19 17:59:26 +08:00
@wniming 你可以把寄存器理解为指令周期级别延迟的缓存,cpu 的流水线长度和应用场景还有边际效用决定了民用 cpu 不值得做太多寄存器
|
8
kita 2023-10-19 18:03:40 +08:00
|
9
iOCZ 2023-10-19 18:07:59 +08:00
精简指令集参数多了才会入栈吧
|
10
agagega 2023-10-19 18:27:47 +08:00 via iPhone 1
@wniming
x86 的指令操作数可以直接是内存地址,所以不需要那么多名义寄存器。arm 这类精简指令集必须要 load/store 才能从内存里读/写信息,isa 寄存器数量少了会有大量 spill/reload isa 里规定的寄存器也不等于 cpu 物理上真的只有这么多。cpu 真实的寄存器数量很可能大于 isa 里的寄存器数量,因为 cpu 内部为了减少指令间依赖会做寄存器重命名 |
11
CRVV 2023-10-19 19:31:13 +08:00
@wniming
16 个寄存器需要 4 位来编码,31 个需要 5 位,这个应该是最主要的原因。 比如 inc eax 只需要 1 个 byte ( 8 位)来编码。如果寄存器需要 5 位,就不太可能放在 1 byte 里面。( ARM 好像也没有 inc 这个指令) 所谓 CISC ,是指在一条指令里面可以同时访问内存和做运算。比如 add eax, (ecx),是 eax += *ecx ,这条指令在 x86 上面只占 2 bytes 在 RISC 上面需要先 load edx, (ecx),再做加法 add eax, edx ,RISC 上面这两条指令很可能都要 4 bytes ,一共 8 bytes 。而且 load ecx 需要多用一个寄存器 edx 来保存结果。也就是 RISC 需要更多的寄存器来做到的 CISC 一样的事情。 指令短是 CISC 的一个重要设计目标,到 RISC 的年代不在乎这个事了,所以有这个差别。 CPU 实际有多少个寄存器和指令上定义的寄存器数量无关,CPU 有一部分专门来处理这个事情 https://en.wikipedia.org/wiki/Register_renaming |
12
mmdsun 2023-10-19 19:57:51 +08:00 via iPhone
@felixlong
编程语言更看中平台的独立性,基于栈的指令集不依赖于特定数量的寄存器,更容易在不同的硬件和操作系统上移植。Python 、JVM 、dotNET 、甚至 WebAssembly 都是基于栈。 |
13
e3c78a97e0f8 2023-10-19 22:36:54 +08:00
@summerLast x86 和 ARM 可都是基于寄存器的,和题主问题没关系。
|
14
roycestevie6761 2023-10-19 22:40:03 +08:00
函数调用不都是寄存器不够了再入栈吗,设计一个基于栈的不是退化吗,寄存器肯定比内存访问快太多了
|
15
DeWjjj 2023-10-19 22:40:34 +08:00
因为 ARM 的电路更多,有的时候为了实现模拟 x86 的算法需要多次缓存数据。
|
16
roycestevie6761 2023-10-19 22:41:42 +08:00
而且有一些专门做代码混淆的人基于栈式指令集搞出来的基于堆栈的虚拟机,这种机子复杂的一批,但是同时执行起来也慢的一批
|
17
misdake 2023-10-19 22:51:27 +08:00
核心原因就是性能差。
ISA 比较灵活,依赖比较小,改做 AOT 的字节码还是很合适的。 |
18
felixlong 2023-10-19 22:56:37 +08:00
@mmdsun 基于栈主要是为了节省空间和简单。和可移植多大没关系,同样是 Java ,Android VM 就是基于寄存器的。
基于栈的 JVM 每条指令只要一个 byte 编码。基于寄存器的 Android VM 每条指令需要 2 个 byte 。X86/ARM 都是需要 4 byte 得。 |
19
tek 2023-10-20 07:34:16 +08:00
STACK 式的操作速度慢,是用更多的操作步骤换取实现的简单。设想在一个电视机的组装流水线上,用有两只手的机器人来完成工作需要 n 个步骤。如果换用一只手的机器人来完成同样的工作,必然需要更多的拿起,放下的步骤和更多的周转空间。但单手机器人结构更简单,造价更低
|