Since you want to replace the whole subroutine, in-line assembler is a bit silly. Write the whole routine in assembler. That way the compiler can't get in the way doing stuff on entry and exit of the routine and the like.
It would also be better to explain what you really want this routine to do than to define it implicitly with C code. You have:
tmr0_temp = TMR0L;
TMR0L = 0;
tmr1_temp = TMR1L;
TMR1L = 0;
tmr0_value = tmr0_temp;
tmr1_value = tmr1_temp;
Apparently you want a snapshot of timer 0 in 16 bit mode into a separate variable. Your code above won't work for that in all cases since you didn't deal with the high byte incrementing between the two reads.
Unless you will access the two final registers in a routine that could get interrupted by this one, there is no need for the temporary register. Actually, without disabling interrupts you can't guarantee the final 16 bit value is written atomically anyway. Either you care about atomic update or you don't. Your method makes no sense as it seems to care in one part but in the end doesn't guarantee it.
You are also resetting the timer to 0, which is usually a bad idea. This is usually the result of wanting to make sequential time interval measurements without having thought it thru very well. If the reason you need this routine to run so quickly is because you want to minimize the instructions you lose due to resetting the timer, then this is definitely the wrong way to go about it. Take a snapshot at each point you want to measure the interval between, then do a unsigned 16 bit subtract. That will give you the interval without any cycles lost when the timer is reset.
If you can afford the timer to be off for a few cycles, then just shut it off, read it, clear it, and restart it. I really don't see a case where your method makes sense.
In any case, here is a example code snippet that takes a consistant snapshot of timer 0 while leaving it running (untested, not even syntax checked):
extern t0snapshot ;16 bit snapshot of timer 0
;*********************************************************************
;
; Subroutine T0_GRAB
;
; Grab the current timer 0 value into T0SNAPSHOT. The timer will
; continue running the whole time.
;
global t0_grab
t0_grab
banksel t0snapshot ;set bank for access to output variable
t0_retry ;back here if high byte changed
movf tmr0h, w ;get the timer high byte
movwf t0snapshot+1 ;save it
movff tmr0l, t0snapshot+0 ;grab the low byte
xorwf tmr0h, w ;check the high byte again
bnz t0_retry ;high byte changed, try again ?
return
Note this construct called "comments" in this routine. Those are very useful things you need to learn about. Undocumented code is really no code at all.
Best Answer
Without seeing your code it's difficult to give advice (your screenshot is too small to read). What you see can be typically attributed to dynamic memory or auto variables when at certain point the debugger will (erroneously) show you the stack location previously occupied by a variable defined inside a function. Move the code inside a function to see if it makes a difference.