通常我会在每次GPR访问之前做一个银行,但我发现我有许多不必要的行。所以,问题是这个。我做一些调用子程序,访问不同的调用例程访问不同的内存库。保存在GPR(STATUS寄存器)中是一个好主意,用于维护当前存储体并在返回之前切换回它或者这样做的最佳方式是什么?
答案 0 :(得分:2)
有很多方法可以解决这个问题,很多方面取决于你想要多聪明,想要保存多少代码空间,以及你的代码需要多长时间。尝试节省代码空间/时间,然后冒着错误时间错误存入错误银行的风险之间存在权衡。
我更喜欢这里的安全选择......
我所做的是,对于任何可能改变Bank的Sub,我会写一个小的“Calling Sub”来备份GPR状态。然后,“Calling Sub”调用“Real Sub”,它可以根据需要更改Bank。当“Real Sub”退出时,它返回到“Calling Sub”,然后在返回程序循环之前将Bank恢复到原来状态
Psuedo代码:
CALL_MYSUB BACKUP STATUS
BACKUP GPR
CALL MYSUB
RESTORE GPR
RESTORE STATUS
RETURN
您可以巧妙地使用上述内容并编写一个小宏来替换存储和检索代码,这样可以简化代码的外观并提高可维护性......当然,它会使用相同的代码空间。
Psuedo代码:
CALL_MYSUB BACKUP_MACRO
CALL MYSUB
RESTORE_MACRO
RETURN
理论上,如果您可能有两个以上的备份指令,两个还原,那么您可以制作一个备份例程和一个单一还原例程,而不是宏,而是调用这些指令;
Psuedo代码:
BACKUP_CONTEXT BACKUP STATUS
BACKUP GPR
BACKUP OTHER THINGS
BACKUP MORE STUFF
RETURN
BACKUP_CONTEXT BACKUP STATUS
BACKUP GPR
BACKUP OTHER THINGS
BACKUP MORE STUFF
RETURN
RESTORE_CONTEXT RESTORE MORE STUFF
RESTORE OTHER THINGS
RESTORE GPR
RESTORE STATUS
RETURN
CALL_MYSUB BACKUP_CONTEXT
CALL MYSUB
RESTORE_CONTEXT
RETURN
当然,您可以将上述内容直接纳入需要它的每个子中。但是我更喜欢上面的内容,因为它允许你在没有备份和恢复的情况下调用sub,如果你想要的话,让你的sub保持它想要做的事情,允许你把所有类似的调用放在一个地方,允许你在一个地方进行更改,并明确表示sub将更改GPR。
这里唯一需要注意的是确保你没有太多嵌套调用,这当然会溢出堆栈!
我希望这有帮助......
修改强>
如果您需要做的只是备份您的银行选择位而不是其他任何内容,您可以尝试以下操作...
仅存储Bank Select Bits;
MOVF STATUS,w ;Get the Current Bank Select bits
ANDLW B'01100000' ;Remove all but the Bank Select bits
MOVWF TEMP1 ;Store in a Temporary Register
仅检索银行选择位;
MOVLW B'10011111'
ANDWF STATUS,1 ; Clear the Bank Select Bits
MOVF TEMP1,w ; Get the Old Bank Select Bits
XORWF STATUS,1 ; Restore Old Bank Select Bits
但是,我没有这里的任何环境,所以我无法确认这是否100%有效,但我认为数学很好!
我还假设你使用的是16c77,其中STAT1位为6,RP0位于状态位5。
当然,如果你也需要IRP位,那么你需要存储STAUTS Bit 7 - IRP以及
您还需要确保TEMP1存储在GPR中,以便它没有银行账户。
答案 1 :(得分:1)
我建议最简单的方法可能是将全局策略说明,除非另有说明,否则每个例程都会假定RP0和RP1在进入时是明确的; IRP被设置为适用于FSR中加载的任何内容(如果有的话),否则未指定。退出时,除非另有说明,否则每个例程都应该保持RP0和RP1清除,并且可以使用IRP执行任何操作(尽管如果例程对IRP不执行任何操作,则记录该事实可能很有用。)
除了使用FSR之外,在银行0中“坐”的代码不需要对银行比特做任何事情。在进行任何子程序调用或返回调用者之前,访问另一个银行的代码必须重新选择存储区0。
在某些情况下,使用一些指定不同行为的特殊方法可能很有用,但在许多情况下,这个“公式”应该相当不错。关键是要有一个大多数方法都遵循的规则,并明确说明任何不使用该规则的方法都要清楚记录。
答案 2 :(得分:0)
我使用了两个宏:
m_SaveBank宏Var
clrf Var
btfsc STATUS,RP1
bsf Var,RP1
btfsc STATUS,RP0
bsf Var,RP0
endm
m_RestoreBank宏Var
bcf STATUS,RP1
bcf STATUS,RP0
btfsc Var,RP1
bsf STATUS,RP1
btfsc Var,RP0
bsf STATUS,RP0
ENDM
子程序必须首先保存STATUS.RP1& RP0然后在退出时恢复它们。 W寄存器保持不变,因为大多数时候都携带子程序的数据和除RP0&之外的STATUS位。 RP1也不受影响。 我这样说了十一个字,但我认为没有其他选择。