Sooo, da bin ich wieder.
Ich habe -wie angekündigt- einen Extrakt meines aktuellen Projekts (das einfach nicht fertig werden will) angefertigt. Da sind alle Konfigurationen, Variablen, meine Tastenauswertung in voller Länge und kleine Anregungen für die Verwendung drin, die dich interessieren könnten.
Ich hab auch noch weitere Kommentare eingefügt, die dir zum Verständnis helfen sollen.

Code:
     list            p=16f876a            ; list directive to define processor             !!!!!!! ÄNDERN !!!!!!!
     #include        <P16F876A.INC>       ; processor specific variable definitions        !!!!!!! ÄNDERN !!!!!!!

    __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC   !!!!!!! ODER HALT ANDERS !!!!!!!!

    ;*****************************************************************************
    ; '__CONFIG' directive is used to embed configuration data within .asm file.
    ; The labels following the directive are located in the respective .inc file.
    ; See respective data sheet for additional information on configuration word.
    ;*****************************************************************************


; STATUS bit definitions

     #define    _C      STATUS,0            ; für die Kurzschreibung von Bitprüfungen:  "BTFSS _C"
     #define    _Z      STATUS,2            ;




; Hardware signals definitions

     #define    AUX5    sta_ra,4            ; Taste


;***** KONSTANTEN
   ;Tastenauswertung
K_NONE              EQU        0x00         ; nix
K_FUZZI             EQU        0x01         ; unklar
K_CLICK             EQU        0x02         ; kurz
K_PRESS             EQU        0x03         ; lang



;***********
flax               EQU        0x27          ; diverse Flags
sta_ra             EQU        0x63          ; Binärstatus von Port A
iscr               EQU        0x6B          ; scratch in der ISR
mscr               EQU        0x6C          ; scratch in der main()
key_cnt            EQU        0x6E          ; Anz. ISR-Zyklen "Taste ununterbrochen LOW" (=aktiv)
key_evt            EQU        0x6F          ; erkanntes Tastenevent


;***** GLOBALE VARIABLEN  0x70..0x7F
x70                EQU        0x70          ;
x71                EQU        0x71          ;
x72                EQU        0x72          ;
x73                EQU        0x73          ;
x74                EQU        0x74          ;
x75                EQU        0x75          ;
x76                EQU        0x76          ;
x77                EQU        0x77          ;
x78                EQU        0x78          ;
x79                EQU        0x79          ;
dlycnt             EQU        0x7A          ; Delay-Restzyklen zu je 1ms
ticker             EQU        0x7B          ; virtuelle Unruh; immerzu in Bewegung
temp_w             EQU        0x7C          ; variable used for context saving
temp_status        EQU        0x7D          ; variable used for context saving
temp_pclath        EQU        0x7E          ; variable used for context saving
temp_fsr           EQU        0x7F          ; variable used for context saving			








;**********************************************************************
;**********************************************************************
        ORG       0x0000    ; Begin of 2k-Code Page #0   (1st)
                            ; processor reset vector
;**********************************************************************
;**********************************************************************

         nop                      ; nop required for icd
         goto    MAIN             ; go to beginning of program
         nop
         nop















;**********************************************************************
;**********************************************************************
         ORG     0x0004   ; interrupt vector location        ***************** hierher wird bei ALLEN Interrupt Requests verzweigt ****************
;**********************************************************************
;**********************************************************************


;**********   Kontext sichern   **********
         movwf   temp_w           ; save off current W register contents
         movf    STATUS,w         ; move status register into W register
         movwf   temp_status      ; save off contents of STATUS register
         movf    PCLATH,w         ; move pclath register into w register
         movwf   temp_pclath      ; save off contents of PCLATH register
         movf    FSR,w            ;
         movwf   temp_fsr         ;

         ; Lead-In
         ;bcf     INTCON,GIE       ; globales IRQ-Disable  ;;; das geschieht schon automatisch bei der IRQ response
         bcf     STATUS,RP0       ;
         bcf     STATUS,RP1       ; Bank 0 als default
         bcf     PCLATH,4         ;
         bcf     PCLATH,3         ; Code Page #0

         ; Identifizierung der Quelle
         btfsc   INTCON,T0IF      ; der Timer0 ?
         goto    ISR_TMR0         ;
         btfsc   PIR2,CCP2IF      ; das CCP2-Modul ?                                        Dummy zur Strukturdarstellung
         goto    ISR_CCP2         ;
         btfsc   INTCON,INTF      ; externer INT ?                                          Dummy zur Strukturdarstellung
         goto    ISR_INT          ;

         goto    ISR_RESTORE      ; !!! Fangleine !!! (gegen ungewollt aktive IRQs)



      ; ab hier die Service-Routinen für die verschiedenen IRQ-Quellen

;**********   ISR für den Timer0-Interrupt
ISR_TMR0
         ; IRQ-flag löschen und preload
         bcf     INTCON,T0IF      ; Timer0-IRQ
         movlw   d'8'             ; 256-(250-2!) = 8 für 1000,0 Hz @ 16,00MHz   !!! DIESEN WERT AUCH BEIM INIT IM HAUPTPROGRAMM SETZEN !!!
         movwf   TMR0             ; preload = verkürzter Anlauf zum nächsten Überlauf-IRQ

         ; Eingänge lesen
         movf    PORTA,w          ;
         movwf   sta_ra           ; Port A in Abbildvariable einlesen




ISR_TMR0_1                                        ;      ***********  ein paar kleine Anregungen **************
         ; Millisekunden-Eieruhr
         movf    dlycnt,f         ; Z-Flag generieren
         btfss   STATUS,Z         ;
         decf    dlycnt,f         ; dekr., wenn nicht null (Z=0)


         ; Millisekunden-Ticker  (= virtuelle Unruh)
         incf    ticker,f         ;



       ;  ***************** und hier wird es interessant für dich *******************

ISR_KEY
         ; Tastenauswertung
           ; Tastenstatus elektrisch
         btfsc   sta_ra,4         ; LOW-aktiv !
         goto    ISR_KEY_1        ; NICHT betätigt, also auswerten
         incf    key_cnt,f        ; betätigt, also hochzählen
         movlw   d'255'           ; Endanschlag
         subwf   key_cnt,w        ;
         btfsc   STATUS,Z         ; auf Gleichheit prüfen
         decf    key_cnt,f        ; Zählerstand deckeln
         goto    ISR_KEY_TAIL     ; und Schluss
ISR_KEY_1
           ; Ereignis-Erkennung
         movlw   d'20'            ; Max-Wert für Prellen
         subwf   key_cnt,w        ; 
         btfss   STATUS,C         ; überschritten ?
         goto    ISR_KEY_END      ; NEIN, dann Schluss
         movlw   K_CLICK          ; JA!
         movwf   key_evt          ; reicht für ein CLICK

         movlw   d'150'           ; Max-Wert für CLICK
         subwf   key_cnt,w        ; 
         btfss   STATUS,C         ; überschritten ?
         goto    ISR_KEY_END      ; NEIN, dann Schluss
         movlw   K_FUZZI          ; JA!
         movwf   key_evt          ; reicht für ein FUZZI

         movlw   d'250'           ; Max-Wert für FUZZI
         subwf   key_cnt,w        ; 
         btfss   STATUS,C         ; überschritten ?
         goto    ISR_KEY_END      ; NEIN, dann Schluss
         movlw   K_PRESS          ; JA!
         movwf   key_evt          ; reicht für ein PRESS
ISR_KEY_END
         clrf    key_cnt          ; Event oder Prellen detektiert, daher löschen
ISR_KEY_TAIL


         goto    ISR_RESTORE      ;                                       Ende der Serviceroutine für den Timer0-Interrupt


;**********   ISR für den CCP2-Interrupt   **********  das hier nur noch beispielhaft; es gehört zur anfänglichen Verzweigung
ISR_CCP2
         ; das wäre der CCP2-Interrupt - derzeit ohne Funktion
         bcf     PIR2,CCP2IF      ; auslösendes Flag löschen
           ;   !!!!!!!!!  hier dazwischen gehört dein eigener Code  !!!!!!!!!!!!!
         goto    ISR_RESTORE      ;



;**********   ISR für den externen INT-Eingang   **********  das hier nur noch beispielhaft; es gehört zur anfänglichen Verzweigung
ISR_INT
         ; das wäre der externe INT-Eingang - derzeit ohne Funktion
         bcf     INTCON,INTF      ; auslösendes Flag löschen
           ;   !!!!!!!!!  hier dazwischen gehört dein eigener Code  !!!!!!!!!!!!!
         goto    ISR_RESTORE      ;



ISR_RESTORE
         ; Kontext wiederherstellen
         movf    temp_fsr,w       ;
         movwf   FSR              ;
         movf    temp_pclath,w    ; retrieve copy of PCLATH register
         movwf   PCLATH           ; restore pre-isr PCLATH register contents
         movf    temp_status,w    ; retrieve copy of STATUS register
         movwf   STATUS           ; restore pre-isr STATUS register contents
         swapf   temp_w,f         ; Kniff, um W zu laden, ohne den Status zu verändern !
         swapf   temp_w,w         ; restore pre-isr W register contents

         retfie                   ; return from interrupt (impliziert ein "bsf INTCON,GIE")




















;**********************************************************************
MAIN                    ;  Das Hauptprogramm
;**********************************************************************


         clrf    INTCON           ; alle Interruptquellen sperren, alle IRQs verwerfen



         ; Timer0 konfigurieren
         bsf     STATUS,RP0       ; Bank 1
         clrwdt                   ; WDT-Register und implizit Prescaler löschen, das gehört sich so!
         movlw   b'10000011'      ; int sys clk, 1:16, prescale assg. to TMR0
         movwf   OPTION_REG       ;
         bcf     STATUS,RP0       ; Bank 0
         movlw   d'8'             ; Presetwert vgl. Timer0-ISR
         movwf   TMR0             ;






         ; Startzustände herstellen
         movlw   d'0'             ;
         movwf   ticker           ;
         movwf   flax             ; acht Flag-Bits

         movlw   K_NONE           ;
         movwf   key_evt          ;

         bsf     STATUS,RP0       ; Bank 1
         clrf    PIE1             ;
         clrf    PIE2             ;
         bcf     STATUS,RP0       ; Bank 0
         clrf    PIR1             ;
         clrf    PIR2             ;
         clrf    INTCON           ; alle Quellen und IRQs disablen/rücksetzen



         ; Interrupts enablen bzw. in Gang setzen
         bsf     INTCON,T0IE      ; Timer 0 enable
         bsf     INTCON,PEIE      ; Gruppe der Peripherals 
         bsf     INTCON,GIE       ; globales Enable










           ;   !!!!!!!!!  hier dazwischen gehört dei eigener Code  !!!!!!!!!!!!!


; und hier endlich die Hauptprogrammschleife
LOOOP 

         ; auf Event K_PRESS prüfen
         movlw   K_PRESS          ;
         subwf   key_evt,w        ;
         btfsc   STATUS,Z         ;
         incf    tastenzaehler    ;


         pagesel LOOOP            ;
         goto    LOOOP            ;






;**********************************************************************
         ; wartet stur, bis die ISR den Zähler dlycnt bis Null heruntergezählt hat
                                                                    *******  Das ist das Gegenstück zur dlycnf-Manipulation in der ISR ****************
                                                                    *******  auch wieder nur als Anregung zu verstehen                 ****************
P0_IDLE
         movwf   dlycnt           ; Delayzeit wird im W-Register geliefert
P0_IDLE_1
         movf    dlycnt,f         ; zero flag generieren
         btfss   STATUS,Z         ; bei Z=1 ausbrechen
         goto    P0_IDLE_1        ;

         return                   ;
;**********************************************************************



     


;**********************************************************************
         END                      ; directive 'end of program'
;**********************************************************************
Hoffentlich habe ich dich nicht unterschätzt; langweilen will ich dich damit nicht. Ich nehme an, daß du mit MPLAB arbeitest, dann wirst du vieles schon kennen. Wenn du konkrete Fragen hast zu meinen Konstrukten - immer raus damit.
Das minimale Grundgerüst für Interrupts findest du noch übersichtlicher in der MPLAB-Installation, ich glaube unter dem Namen p16f628atemp.asm. Aber da bist du vermutlich auch gestartet.

Jetzt bist du dran, das gründlich durchzuarbeiten. Ist doch ne ganze Menge Code übrig geblieben. Allerdings hab ich mit flinker Schere geschnitten, da ist manche Franse dran, die noch weg müsste, vielleicht hab ich auch mal ins gute geschnitten - ich hab nicht getestet, ob's assemblierbar ist!