你不能在一般的做到这一点,但在某种意义上,你很可以了,已经有一些历史的情况下,您确实有到。
在雅达利2600(或雅达利电视电脑系统)是最早的家用视频游戏系统之一,并于1978年首次发布不同的是时代的更高版本的系统,Atari公司无力给该设备的帧缓冲,这意味着CPU过在每条扫描线上运行代码以确定要产生的内容-如果这段代码花费了17.08微秒(HBlank间隔)运行,则在扫描线开始绘制图形之前,将无法正确设置图形。更糟糕的是,如果程序员想要绘制比Atari通常所允许的内容更复杂的内容,则他们必须测量指令的准确时间并在绘制光束时更改图形寄存器,整个扫描线的跨度为57.29微秒。
但是,Atari 2600与许多其他基于6502的系统一样,具有非常重要的功能,可以实现这种情况所需的仔细时间管理:CPU,RAM和TV信号都基于同一主时钟而不再运行时钟时钟。电视信号以3.98 MHz的时钟运行,将上述时间分成管理电视信号的整数个“彩色时钟”,CPU和RAM时钟的周期恰好是三个彩色时钟,从而使CPU时钟可以相对于当前进度电视信号的准确时间度量。(有关更多信息,请查阅为Stella Atari 2600模拟器编写的《 Stella程序员指南》)。
此外,该操作环境意味着每条CPU指令都有在每种情况下都需要定义的周期数,并且许多6502开发人员在参考表中发布了此信息。例如,考虑这个条目的CMP
指令,从取(用蓄电池比较内存)此表:
CMP Compare Memory with Accumulator
A - M N Z C I D V
+ + + - - -
addressing assembler opc bytes cycles
--------------------------------------------
immediate CMP #oper C9 2 2
zeropage CMP oper C5 2 3
zeropage,X CMP oper,X D5 2 4
absolute CMP oper CD 3 4
absolute,X CMP oper,X DD 3 4*
absolute,Y CMP oper,Y D9 3 4*
(indirect,X) CMP (oper,X) C1 2 6
(indirect),Y CMP (oper),Y D1 2 5*
* add 1 to cycles if page boundary is crossed
利用所有这些信息,Atari 2600(和其他6502开发人员)能够准确地确定他们的代码执行所花费的时间,并构建满足其要求并仍然符合Atari电视信号时序要求的例程。而且由于该计时非常精确(特别是对于诸如NOP这样的浪费时间的指令),他们甚至能够在绘制图形时使用它来修改图形。
当然,Atari 6502是一个非常特殊的情况,所有这一切都是可能的,因为该系统具有以下所有功能:
- 一个主时钟运行所有内容,包括RAM。现代系统具有CPU和RAM的独立时钟,RAM时钟通常较慢,并且两者不一定同步。
- 没有任何类型的缓存-6502始终直接访问DRAM。现代系统具有SRAM高速缓存,这使得更难以预测状态-尽管也许仍然可以预测具有高速缓存的系统的行为,但绝对要困难得多。
- 没有其他程序同时运行-墨盒上的程序可以完全控制系统。现代系统使用非确定性调度算法一次运行多个程序。
- 时钟速度足够慢,因此信号可能会在整个系统中及时传播。例如,在时钟速度为4 GHz的现代系统上,光子要经过6.67个时钟周期才能移动到半米母板的长度上-您永远都无法期望现代处理器与板上的其他器件发生交互只需一个周期,因为板上的信号甚至需要一个多周期才能到达器件。
- 一个定义明确的时钟速度很少改变(在Atari情况下为1.19 MHz)-现代系统的CPU速度一直在变化,而Atari在不影响电视信号的情况下也无法做到这一点。
- 发布的周期计时-x86并未定义其任何指令花费的时间。
所有这些东西加在一起创建了一个系统,可以在该系统上编写花费了确切时间的指令集-对于此应用程序,这正是所需要的。大多数系统之所以没有这种精确度,仅仅是因为不需要它-计算可以在完成时完成,或者如果需要精确的时间,则可以查询独立的时钟。但是,如果需求是正确的(例如在某些嵌入式系统上),它仍然可以出现,并且您将能够准确确定代码在这些环境中运行需要多长时间。
而且,我还应该添加一个巨大的免责声明,即所有这些仅适用于构建一组汇编指令,这将花费确切的时间。如果您想要做的是任意组装,即使在这些环境中,并询问“执行此操作需要多长时间?”,则您绝对无法做到这一点-那就是Halting Problem,已被证明是无法解决的。
编辑1:在此答案的先前版本中,我说过Atari 2600无法通知处理器它在电视信号中的位置,这迫使它从一开始就保持整个节目的计数和同步。正如我在评论中向我指出的那样,这在某些系统(例如ZX Spectrum)中是正确的,但在Atari 2600中则不是,因为它包含一个硬件寄存器,该寄存器可以暂停CPU直到下一个水平消隐间隔发生,以及随意开始垂直消隐间隔的功能。因此,计数周期的问题仅限于每条扫描线,并且仅当开发人员希望在绘制扫描线时更改内容时才变得精确。