从z80监控程序看单片机程序转移技巧
小弟学习单片机已经有3个多月了,在这段时间我发现网上有很多朋友都提到这样一个问题
如何进入中断后,返回时直接跳到其他程序段执行(不回到中断的主程序)
我通过看z80的监控程序对单片机程序跳转有一点小小的见解,拿出来和大家分享
下面是小弟改写的一段程序。说明如下:
****************************************************************************
;更换pc,转用户程序
CCS2B: POP B ;
MOV R0,B
POP B
MOV R1,B
POP B
MOV R2,B
POP B
MOV R3,B
POP B
MOV R4,B
POP B
MOV R5,B
POP B
MOV R6,B
POP B
MOV R7,B
POP ACC
POP P0
CLR INTFLG
clr p3.3
RET
******************************************************************************
;*************************************************************
;定时器中断程序
;*************************************************************
OUTINT1: JB INTFLG,OUTINT10
SETB INTFLG
RETI
OUTINT10: MOV B,SP ;保护用户的sp
MOV STKPT,B
SETB P3.3
CLR EX1
PUSH P0
PUSH ACC
MOV B,R7
PUSH B
MOV B,R6
PUSH B
MOV B,R5
PUSH B
MOV B,R4
PUSH B
MOV B,R3
PUSH B
MOV B,R2
PUSH B
MOV B,R1
PUSH B
MOV B,R0
PUSH B
NMIS2: CLR SSFLG
JNB BFLG,REMBP20 ;无断点,取出用户的pc,添入DISMEM0,1,2,3,取出
a,添入DISMEM4,5
LJMP CCS1C ;转装配断点,使键盘中断有效,并返回用户程序
REMBP20: MOV R1,#DISMEM2 ;R0指向显示缓冲区
MOV R0,STKPT ;栈顶入R0
MOV A,@R0 ;把堆栈中PCH的内容送A
LCALL UFOR1 ;A的内容送显示缓冲区
DEC R0
MOV A,@R0 ;取pc的低字节
LCALL UFOR1 ;写入显示缓冲区
INC R0
INC R0
INC R0
MOV A,@R0 ;取堆栈中a的数值
MOV R1,#DISMEM0
LCALL UFOR1 ;写入显示缓冲区
LJMP DISUP ;转到显示程序
********************************************************************************
**********
在运行到CCS2B时,堆栈指到52H,最后一条ret指令执行前,堆栈指到49H,执行ret指令
PC值被更改,所以程序转到哪里完全看47H和48H里的内容。假设已经存在一段用户程序,
他的起始地址是2000h,那我事先就要把48H中放入20H,47H中放入00H,那程序就会跳到
2000这个地址执行。
假设我在用户程序执行两条指令(mov a,#00h,mov dptr,#3000h)后遇到我设定的一个断点,
程序回到我的监控程序。请注意:回到监控程序的同时,用户程序的pc值2003h已经被入栈。
细心的人发现,48H的内容现在是20H,49H的内容是03H。当然,我在中断中会保存用户的
程序的一些内容,中断程序恰恰和CCS2B的内容相反。中断的最后一句是ljmp disup (转向显示
程序)
,而不是reti。中断完成后,堆栈又指到52h。程序不会回到用户程序,而是执行主程序,等待
键盘输入。
按继续键,程序又会运行到CCS2B,这一次执行ret的结果是
pc=2003h,程序跳到用户程序先前中断的地方。
发表评论 评论 (0 个评论)