为什么6502汇编中的条件分支有128字节的限制?

4

为什么程序必须在发出分支指令的128或-127字节范围内执行?这是由硬件限制所决定的。


3
简单翻译:偏移量使用8位有符号数字进行编码。 - Jester
1
为了绕过这个限制,反转条件跳转的意义,使其跳过一个跳转指令,到一个超出127字节的位置。一些汇编程序有一个条件分支宏来实现这一点,但我不知道6502汇编器是否有这种类型的宏。 - rcgldr
2个回答

11

硬件原因有两个:

  • 首先,6502是一种8位处理器,这意味着单个字节可以保存从0到255的无符号值,或者如果使用第7位来表示符号(二进制补码)则为-128至+127。

  • 其次,Chuck Peddle将分支指令设计为一个双字节操作——第一个字节表示分支条件(操作码),第二个字节表示有符号偏移值(操作数),如果条件成立,则将其添加到程序计数器[PC]中。

如今已经显而易见,使用单个有符号偏移字节作为分支操作数意味着BRx指令可以容纳的最大“跳跃”范围要么向当前PC后退128个位置,要么向前跳127个位置。

在需要分支距离超过范围的情况下,这种限制可能会很麻烦;然而,对6502汇编编程技术进行实践和经验,深入了解代码流程和组织常常可以通过巧妙的设计避免需要跨越更大的距离。

CPU体系结构绝对能够弥补范围限制,因为BRx是一条非常快的指令——如果分支不被执行,只需要2个时钟周期;如果执行,则只需再加上一个时钟周期(即2个时钟周期读取操作码和操作数,并在内部寄存器中设置比较掩码,然后再添加操作数到PC,如果条件成立)。

相比之下,JMP指令允许程序流在16位地址范围内跳转到任何位置,因为它使用双字节地址操作数,但是它的开销是固定的3个周期,并且无条件执行。通过精心构建跳转表或使用JMP自修改代码并由分支索引来利用BRx的速度和条件性,程序员可以只在条件成立时才产生“远跳转”的开销。


1
克服这个限制可以很简单,例如将BEQ label转换为BNE 3; JMP label,如果label不适合于有符号8位范围。 - Cactus

5
这是因为条件分支语句只有2个字节长,第一个字节是指令的操作码,第二个字节是一个带符号的(二进制补码)值,用于标记如果条件为真要跳转到的地址距离。 (我认为该值是DestinationAddress-AddressImmediatelyFollowingBranchStatement)。由于只有一个字节可用且使用二进制补码,因此距离目标地址的范围限制在以下范围内:[-128,+127]。
简而言之,这是因为6502的设计者仅提供了一个带符号的二进制补码字节作为条件分支语句的参数。

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