This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Can keil optimize the interrupt routines?

When I set optimize(9,size) to a interrupt function, which should be optimize for "Common Block Subroutines", but it wasn't!
All interrupt funtions contain following duplicate blocks(see BOLD):


    PUSH    ACC
    PUSH    B
    PUSH    DPH
    PUSH    DPL
    PUSH    DPH1
    PUSH    DPL1
    PUSH    DPS
    MOV     DPS,#00H
    PUSH    PSW


    MOV     PSW,#010H ;Depend on using.
    LCALL   MyFunc


    POP     PSW
    POP     DPS
    POP     DPL1
    POP     DPH1
    POP     DPL
    POP     DPH
    POP     B
    POP     ACC
    RETI


Because I have so many interrupt functions. The optimize could save some code space, isn't it?

Parents
  • No, it will not work in the whole. In your example, when RET command of LB1() executes, MCU jumps to random address (in fact it goes to address given from two last bytes on the stack). See once again: LCALL LB1 puts return address (address of the next command after LCALL) on the top of stack. Inside your LB1() routine there are some PUSHes which increase stack pointer for each byte held on stack area. The last command of LB1() is RET. It takes two bytes from the top of stack and does jump on address constructed from these bytes. So if the end of your LB1() looks like:

    LB1:
        ....
        PUSH    DPL1
        PUSH    DPS
        RET
    ...then after RET command MCU does not return to command after LCALL LB1 but goes to address (DSP<<8 +DPL1) instead! Based on it I ask you again: could you even imagine? (=
    Okay, there are many ways to do it by right anyway. For example (just one of many solutions):
    ;void INT0 (void) intterupt x using y
    	PUSH	DPL
    	PUSH	DPH
    	MOV	DPTR,#MyFunc
    	CALL	SafeRun   ; <- common for all the interrupts
    	POP	DPH
    	POP	DPL
    	RET
    
    ; Common function which saves resisters,
    goes to subroutine with address in DPTR
    and retrives registers back
    SafeRun:
    	PUSH	PSW
    	PUSH	ACC
    ;	....  push rest registers except DPTR (mark1)
    	CALL	SafeRun_Go
    ;	.... pop previous pushed registers (mark1)
    	POP	ACC
    	POP	PSW
    	RET
    SafeRun_Go:
    	CLR	A
    	JMP	@A+DPTR
    Good days!

Reply
  • No, it will not work in the whole. In your example, when RET command of LB1() executes, MCU jumps to random address (in fact it goes to address given from two last bytes on the stack). See once again: LCALL LB1 puts return address (address of the next command after LCALL) on the top of stack. Inside your LB1() routine there are some PUSHes which increase stack pointer for each byte held on stack area. The last command of LB1() is RET. It takes two bytes from the top of stack and does jump on address constructed from these bytes. So if the end of your LB1() looks like:

    LB1:
        ....
        PUSH    DPL1
        PUSH    DPS
        RET
    ...then after RET command MCU does not return to command after LCALL LB1 but goes to address (DSP<<8 +DPL1) instead! Based on it I ask you again: could you even imagine? (=
    Okay, there are many ways to do it by right anyway. For example (just one of many solutions):
    ;void INT0 (void) intterupt x using y
    	PUSH	DPL
    	PUSH	DPH
    	MOV	DPTR,#MyFunc
    	CALL	SafeRun   ; <- common for all the interrupts
    	POP	DPH
    	POP	DPL
    	RET
    
    ; Common function which saves resisters,
    goes to subroutine with address in DPTR
    and retrives registers back
    SafeRun:
    	PUSH	PSW
    	PUSH	ACC
    ;	....  push rest registers except DPTR (mark1)
    	CALL	SafeRun_Go
    ;	.... pop previous pushed registers (mark1)
    	POP	ACC
    	POP	PSW
    	RET
    SafeRun_Go:
    	CLR	A
    	JMP	@A+DPTR
    Good days!

Children