如果我想在8051汇编语言中创建有限状态机,我需要一个有效的等效C
[对于这个问题,让我们忽略落空行为,保留和删除都是可以接受的]
有几种方法可以在8051汇编中实现这一点,但它们各自有其缺点。对于5-10个情况的短开关,它们足够简单、清晰,但如果我需要一个>128甚至>256个情况的开关,事情就会变得复杂。
第一种方法很简单,一系列用
接下来的方法是乘法跳转偏移量。将控制变量乘以2,将结果加载到DPTR中,使用偏移量将累加器加载到先前预加载了大量
还有一种方法是从专用表中提取地址,预加载堆栈并执行
总的来说,我想知道是否有更优雅、更有效的方法来执行switch()风格的跳转——一种不会创建太多开销、不浪费太多内存并至少具有
switch()
表达式。[对于这个问题,让我们忽略落空行为,保留和删除都是可以接受的]
有几种方法可以在8051汇编中实现这一点,但它们各自有其缺点。对于5-10个情况的短开关,它们足够简单、清晰,但如果我需要一个>128甚至>256个情况的开关,事情就会变得复杂。
第一种方法很简单,一系列用
CJNE
比较操作数的链,如果不相等,则跳转到下一个情况;相当于if(){...}else if(){....} else if(){...}
。优点是简单,缺点是显而易见的:在长开关的情况下,这将创建一个非常长的选择字符串。通过构建二叉树,使用JB
来连续比特位的控制变量可以减少这种情况。这仍然不太有效,非常难以维护,并且使得实现稀疏键集变得困难(例如case 1:...; case 5:...; case 23:...; case 118:...)接下来的方法是乘法跳转偏移量。将控制变量乘以2,将结果加载到DPTR中,使用偏移量将累加器加载到先前预加载了大量
AJMP
的区域中,然后执行JMP @A+DPTR
。 (或者将其乘以3并跳转到预先加载了大量LJMP
的区域)。我曾经这样做过。调整跳转指令的位置到字节是一个难题,我不想重复它,而且跳转表过于庞大(每个其他字节都会重复ajmp
)。也许我不知道一些可以使其更容易的技巧...还有一种方法是从专用表中提取地址,预加载堆栈并执行
RET
。听起来非常整洁,除了需要使用可怕的MOVC A, @A+DPTR
或MOV A, @A+PC
这些寻址模式,这些模式让我感到非常难过,我从未尝试过实现它们。如果您知道一种好的方法,请把它作为答案发布。总的来说,我想知道是否有更优雅、更有效的方法来执行switch()风格的跳转——一种不会创建太多开销、不浪费太多内存并至少具有
AJMP
距离跳转自由度的方法,其中case的数量达到了数百个。