我正在学习Motorola 68k汇编,并且编写了以下浪费时间的循环:
move.l #0x0fffffff,%d0
bsr timewaster
rts
timewaster:
dbra %d0,timewaster
rts
这次浪费的循环几乎立即完成。我在调试器中逐步执行了代码,以确保它实际上减去d0
了0(确实如此)。但是,另一个浪费时间的循环需要永远完成:
move.l #0x0fffffff,%d0
bsr timewaster
rts
timewaster:
sub.l #1,%d0
bne timewaster
rts
那么为什么代码使用起来dbra
这么快?
我在TI-89仿真器中运行了这些程序。
尽管由于实际处理器上的访存次数较少而会有一些改进,但时间安排差异如此之大的原因是这两种方法使用的大小不同。
从《程序员参考手册》的页面上DBcc
:
如果终止条件不成立,则计数器数据寄存器的低16位减1。如果结果为-1,则从下一条指令继续执行。如果结果不等于-1,则在程序计数器当前值加上符号扩展的16位位移所指示的位置继续执行。
因此,该DBcc
指令仅操作并检查循环计数寄存器的低位字。因此,SUB
和Bcc
版本的时间将比〜版本长4000倍DBcc
。如果您使用SUB.W
而不是SUB.L
我希望您获得更多类似的运行时间。
该DBcc
指令将执行0x10000的时间,而BNE
指令将执行0xFFFFFFF可倍。
请注意,循环计数器的高阶字不受的影响DBcc
,因此循环应以D0中的0x0FFFFFFF退出。该SUB.L
/BNE
版本应该在D0 0退出。
这与问题没有特别的关系,但是通读手册,似乎在某些地方对DBcc
指令的确切行为略有分歧。具体来说,当条件为真时,循环计数器为0时的行为。两者都导致未采用分支,但是它们在循环计数寄存器中的最终结果上存在分歧。
程序员参考手册,修订版1(M68000PM / AD,修订版1)指出,条件为真优先,并且循环计数器的减量值未存储回去,而在寄存器中保留了0。以下是手册中的内容:
If Condition False
Then (Dn - 1 -> Dn; If Dn != -1 Then PC + d_n -> PC)
《 M68000微处理器用户手册》,第九版(MC68000UM),附录A(MC68010循环模式操作)说,减一的结果优先,并且结果为-1导致将结果存回,而留下-1在寄存器中。根据手册中的描述构建以下内容:
If Dn - 1 == -1
Then Dn - 1 -> Dn
Else
If Condition False
Then (Dn - 1 -> Dn; PC + d_n -> PC)
通常,由于计数而导致的退出将保留-1,而条件退出将保留不同的值(假设计数器并非从0xFFFF开始)。当两个源均为真时,这两个源就寄存器中的值不一致。
我认为PRM是正确的,是行为的权威来源,并且由于它与UM中较早的描述相匹配,但是UM可能暗示了如何实现该指令,至少在MC68010上如此。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句