【发布时间】:2014-12-25 00:31:52
【问题描述】:
我有一个混合 C 和汇编的 PIC18F25K50 项目;我想做的大部分事情都可以在 Assembly 中轻松管理(并且必须提高效率),但是我更关心开发易用性的某些部分使用 C。我实际上有几个,而且我一直遇到同样的问题:我不能使用 ASM 跳转到标签。每个要跳转的函数 - CALL、GOTO、BNC 等 - 如果给定标签,将失败,将 PC 设置为没有指令的随机但一致的值,导致程序挂起.使用地址可以正常工作:BC $+4 跳过下一行。
一个不起作用的例子是这样的:
#asm
_waitUS:
GLOBAL _waitUS
waitLoop:
//12 cycles = 1 microsecond:
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
DECFSZ WREG, F, ACCESS
GOTO waitLoop
RETURN
#endasm
void main() {
//DEBUG:
waitUS(6);
}
现在,这可能无法整体工作,我恳求您专注于跳跃问题 - 这仍在原型设计中,因为我什至无法调用函数。该程序确实编译没有问题。
只要调用waitUS(6),PC 就会从 - 在我的情况下 - 0x7C96 跳转到 0x52。将 C 调用换成 MOVLW 6; CALL _waitUS 以完全相同的方式中断。
如果我严格使用 C 进行调用/跳转(正如我在上一个项目中所必须的那样),它可以正常工作,并且可以确定它的去向。
几周以来我一直在寻找这个问题的答案,但仍然没有看到其他人遇到这个问题,即使我制作的每个项目(包括记事本中的纯文本,通过命令行编译)都有完全相同的问题。这到底是怎么回事?
编辑:发现程序内存视图后,我能够更好地了解它在做什么。编译器确实知道函数在哪里,并且它正在试图跳转到正确的位置。显然,CALL 只是不知道它的去向。
示例:
地址0x7C92 包含CALL 0x2044, 0。这正是它应该做的,这就是所需功能的开始。然而,在运行这条指令时,PC 被更改为 0x205E,缺少一半的功能。
为了聪明一点,我决定在函数的标签后添加几个 NOP,将实际代码与0x205E 对齐。不幸的是,似乎任何变化都会改变它不可预知的跳跃降落的地方,然后它降落在0x2086。
顺便说一句,当它开始在随机位置运行时,它经常会遇到GOTO - 它会按预期跳转到指定位置。这仅适用于同一个函数,因为尝试使用 GOTO 而不是 CALL 最终会出现在同一个不正确的位置,尽管编译结果需要什么。
【问题讨论】: