很久没有使用汇编语言来写单片机了,今天想着写一段程序玩玩。在调试中出现了未能达到的效果,后来用单步执行方式发现在程序跳入子程序后,返回竟然回到了程序最开始的地方:0000H。仔细看程序发现在调用子程序的时候,居然使用了LJMP指令而不是LCALL/ACALL,所以才未达到预期的效果。
后来再改写程序,使用LCALL调用子程序,发现结果就正常了,可见是调用的时候使用了LJMP的缘故。但是转念一想,既然使用了这种非对称式的“调用返回”模式可以使得程序转向出现错误,那也可以反过来利用这种“错误”来到达某些目的,比如可以在程序的最后全部用RET指令来填充,这样如果程序出现“跑飞”的情况,而且跑飞到了这些区域,那就可以使得程序返回到0000H,而不致于出现死机等情况。也可以在烧写程序的时候填充RET的机器代码22在空白区域,也会有同样的效果。
上述讨论以Keil uVision2为编译环境。以下附程序:
LED0 EQU P0.0
LED1 EQU P0.1
LED2 EQU P0.2
LED3 EQU P0.3
ORG 0000H
LJMP INITIAL
ORG 0030H
INITIAL:
CLR LED0
SETB LED1
SETB LED2
CLR LED0
START: CPL LED0
CPL LED1
CPL LED2
CPL LED3
;RET ;如果在这里加入RET指令,调试观察程序的跳转也会跳到0000H。
LJMP SB_DELAY;这里没有使用LCALL指令,但后面的SB_DELAY却用了RET指令,
;会使程序跳到0000H处,可以通过单步调试看出
LJMP START
DL_CNT0 EQU 0AH;外层循环的次数
DL_CNT1 EQU 7DH;内层循环的次数
SB_DELAY:
MOV R0,#DL_CNT0
LP1_DELAY:
MOV R1,#DL_CNT1
LP2_DELAY:
NOP
NOP
DJNZ R1,LP2_DELAY
DJNZ R0,LP1_DELAY
RET
END
writed by eleclike 2007-10-24
文章评论(0条评论)
登录后参与讨论