The 18F series has some extra instructions and a deeper stack. One huge improvement is the PUSH (and POP) instructions plus the ability to access the ToS (Top of Stack) as a Register. The only drawback is that access to the ToS is limited to the low byte of the address - and ADDing or SUBing to TOSL has no effect on the upper bits. Since all addresses are byte addresses, this limits manipulation to the current 128 instruction 'block'. However, despite these restrictions, all sorts of 'stack' tricks can be pulled, especially using the 'Return with value' (Look Up Table - although since each LUT entry is a one word 'Return with value' instruction, the max. LUT size is 128). String look-up It's not unusual to want to look-up a 'string' (sequence of codes) and 'output' the looked up values at maximum speed to one of the PORTS (for example, look up ascii character shape pixel values in a FONT LUT and output the pixels as a video feed for a VTI/OSD) The 'classical' method is to set up a loop in the 'main' code that Calls the LUT control code which in turn calculates a 'jump' into the LUT. The LUT then 'Returns with value' to the Calling code which outputs the value, and loops until 'end of string' is detected. If the 'end of string' is 'flagged' by one of the codes being 'looked up' (0x00 is typically used), then the LUT control code has all the data it needs to detect 'end of string'. Time can be saved if the control code outputs the values (and only returns to the main-line code when all have been output). To get the LUT to 'Return with value' to the start of it's own control code (rather than back to the main code) the control code must 'PUSH' to create a new entry on the stack and then over-write the ToS to 'point' back to the very start of the control code (which will be the 'output to PORT instruction). So when the LUT 'Returns with value', it returns to it's own control code. The EOL (End of Line) = 'End of String' character is 'detected' not by 'testing' for 0x00 (which wastes time) but by replacing LUT entry 0x00 with a 'POP'. When code 0x00 is 'looked up', the POP removes the control code Return address from the stack and exposes the Return address to the main-line code, so when execution 'falls through' from the 0x00 'POP' to the next LUT entry, 0x01 'Return with value', it will Return to the main-line code. ControlStart: Output value MainLineCall: ;main line code Calls here PUSH Set ToS = ControlStart: Calculate next LUT address Jump to LUT address ;LUT Returns with value either to 'ControlStart:' (or the mainline Return address when you jump to 0x00=EOL) Note that no value is output for the EOL 'end of string' code. This means that a 'null' string (one consisting of a single EOL (0x00) code) will generate no output. Loops with Interrupts Another 'cunning trick' to save time in a 'loop' is not to bother with 'counting' or 'testing' in any way for an 'end of loop'. Instead the Timer/Counter is pre-set with the N loop (CLK count) before the loop is started. The loop code is then written so it 'runs for ever', i.e. until N CLK's have elapsed and the Timer/Counter terminates the loop :-)