为什么早期游戏采用汇编语言编写而当时已经有更高级别的编程语言存在?

14

我注意到大多数Nes / Atari等游戏都是用汇编语言编写的,但是那个时候C、COBOL和FORTRAN存在,我认为这些高级语言会使编码更容易,那么为什么他们选择使用汇编语言而不是这些可用的高级语言呢?


2
我们仍然使用汇编语言编写许多游戏的代码块,或者更常见的是使用类似于函数的C++编译器内置函数,但实际上会编译成单个硬件操作码。当时和现在的原因都是为了提高性能。 - Crashworks
8个回答

30

当时的游戏使用了8位CPU芯片和微小的内存,例如2kB。这个答案会占用超过一半的RAM。

编译代码是不可能的。即使在具有“大”内存(例如“64K”)的8位CPU上,编译代码也很难使用;直到16位微处理器出现后才普遍出现。

此外,唯一有用的语言是C语言,但它尚未成为主流。当时,8位微型机上几乎没有C语言编译器。

但即使使用C语言,也没能帮上太多忙。那些游戏中有可怕的廉价hack技巧,几乎需要特定于时间的指令循环...例如,精灵的Y坐标可能取决于(在视频扫描中)何时写入其控制寄存器。(发抖...)

现在有一种不错的解释字节码语言,在那个时候或稍晚一些出现:运行在UCSD P-System上的UCSD Pascal。虽然我不是Pascal的粉丝,但对于那些早期的处理器来说,它比其他语言都要先进得多。但是,它无法适用于游戏或足够快地运行游戏。


3
"640K应该对于任何人来说足够了。" - 比尔·盖茨。完成。 - user1481860
3
啊!美好(?)的过去... ::目送远方:: - dmckee --- ex-moderator kitten
此外,与现代gcc/clang相比,编译器很糟糕,因为编写一个优化编译器是很困难的。(而且它需要大量的内存和时间来运行,所以一个好的Z80或其他处理器的优化编译器不能在Z80上运行。)以前用手写汇编语言轻松击败C编译器,但现在只有在小范围内(对于某些循环:为什么这个C++代码在测试Collatz猜想时比我手写的汇编代码快?),但要在大规模常量传播中击败编译器则完全不切实际。 - Peter Cordes

6
性能,性能,性能。游戏一直都是关于如何充分利用硬件的。即使是最好的C、COBOL或FORTRAN编译器,也无法与精心制作的汇编代码竞争。
正如DigitalRoss所指出的那样,曾经还存在着严重的内存限制,而汇编语言是唯一允许进行细粒度控制的工具。
尽管像Python这样非常易于使用的编程语言已经存在,但低级别的编程语言仍然是最苛刻应用程序的首选。现在的汇编语言已经被更多或更少地取代了C++。

2
今天真正能够击败C、COBOL或FORTRAN编译器的人非常非常少。 - btilly
3
那只是因为如今很少有人费心去获取必要的知识来做那件事。这已经不值得了。 - user1481860
4
从前,我们改变了Fortran编译器的输出,以手动优化性能关键部分。虽然合同要求使用Fortran,但它无法满足性能要求。 - S.Lott
1
@btilly:与现代优化编译器相比,以前的编译器真的很糟糕。它们更容易被手写汇编代码击败。例如:为什么C到Z80编译器会产生糟糕的代码?(Z80是一个特别糟糕的编译器目标,旧的编译器也很差)。现代优化编译器是数百万开发小时努力的产物,而且在旧系统的狭小内存中无法运行。为什么C编译器这么少? - Peter Cordes
1
@PeterCordes 不仅如此,现代硬件也是一个更加复杂的优化目标。 - btilly
显示剩余4条评论

4

"让编码更容易做对"

这并不重要。

高性能,最小内存使用是必要的。

易于编码是无关紧要的。

请记住,早期游戏在非常缓慢的处理器上只有微小的内存,并且没有实际设备。东西基本上是直接连接到CPU芯片。


3

过去的编译器不如我们现在拥有的编译器那么优秀。因此,许多人感到,无论是正确还是错误,他们都可以超越编译器进行优化。


2
幸运的是,大多数有能力的人都在编写编译器。 :D - Gordon Gustafson

3
我认为有更多的程序员会使用汇编语言,并且不会对使用汇编语言编程感到犹豫。即使在IBM-PC和AT时代,那些从未真正编写过任何东西但仍然能够轻松地编写汇编语言程序的人仍然存在,并且可以轻松地比C和Pascal程序员更加高效地编程。
一旦Pascal和C获得了立足点并且你买得起编译器,你就会很高兴能够用一种新的语言进行编程,并且从未听说过优化器,你只是假定高级语言会以相同的方式转换成机器代码。你仍然可以轻松地将你的程序放在5.25英寸软盘上。而且还有足够的640K可供使用。
我认为我们需要恢复或者增加一些4K编程比赛。为GBA或NDS编写一个游戏,但二进制、数据、代码等都不能超过4K。或者重新发明小行星的游戏玩法,岩石、飞船、坏家伙、导弹,不要担心视频像素,因为首先它不是问题,其次这是由第二个处理器(好吧,硬件状态机)处理的,只需生成矢量绘图命令即可。现在有免费的6502 C编译器和基于p-code的Pascal编译器,很容易在6502上运行输出,并查看能否将帧速率提高到1.5MHz或其他运行速度。并且适合于PROM。我认为这个练习将回答你的问题。或者...只需制作一个运行时p-code解释器,看看它是否适合。(standardpascal.org,寻找p5编译器)。
几千字节就像一千行代码或更少。程序并不是那么复杂,汇编语言也不难,至少在6502或其他类似系统中是如此。你没有缓存、mmus、虚拟化和多核心,至少没有我们今天所面临的头痛。你可以自由选择任何寄存器,每个子例程都可以使用自己的自定义调用约定,你不会因为要以标准方式调用函数而浪费大量指令来操纵寄存器或堆栈或内存。你只有一个中断,并且用它来定时轮询/管理硬件(视频更新、均匀定时轮询按钮和其他用户输入、即使在游戏进行时轮询25美分的插槽探测器)。
小行星的汇编代码大约有3000行。使用现在或当时的编译器效率,我会说你需要用约500行C代码来完成整个游戏才能打败它,使用p-code的Pascal我会给你100行代码,好吧200行(不是p-code但针对目标进行了优化,我会给你比C更多的行数)。
Atari VCS(即2600)甚至没有内存用于视频的帧缓冲区。程序必须实时生成像素并执行所有游戏任务。虽然像素不多,但考虑到编程任务以及rom的大小和速度限制。对于这样的东西,你开始进入每个像素的指令数,而我们谈论的是一个很小的数字。高级编译代码将会断断续续地运行,无法保证时间的流畅性。
如果有机会,您应该反汇编一些旧的游戏rom,这是非常有教育意义的,指令序列通常非常优雅。优化编译的高级代码有一些酷炫的技巧,但却不同于原始代码。
据说更好的语言和编译器并不能自动使您变得更好、更快、更有效或更可靠。就像豪华汽车并不能使人成为更好的司机一样。

1

在它们被开发的时候,高级语言还没有出现或者在它们必须运行的平台上表现不佳。


1

内存和速度一直是游戏中至关重要的因素。我的姐夫拥有一套远远超过我运行虚拟服务器和桌面电脑的系统,他抱怨游戏的刷新率。汇编代码可以提供优化代码的能力,而旧编译器可能无法实现这种优化。现代优化编译器可以进行优化,使得生成的代码比手写代码更快。

旧游戏在计时方面严重依赖CPU速度。它们在现代CPU上运行几倍于原来的速度,会导致运行出错。其中一种延迟方法是运行一个循环,递增或递减一个计数器一定次数。(这些可能会被编译器优化掉。)


1
尽管Atari 2600游戏存在有限的内存和速度问题,但高级语言的主要问题是缺乏对时间控制的支配。几乎包括垂直消隐等涉及时间的系统方面都必须由软件处理,而通常你会期望硬件为你完成这些工作。
在扫描线中进行位置、颜色或数据的更改越多,时间就变得越重要。在某些情况下,你必须在行开始后特定数量的CPU周期后写入寄存器。如果你早了1个CPU周期或晚了1个CPU周期,结果将是不正确的。
使用高级语言实现如此精确的时间控制并不切实际。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接