zmiana adresu programu, po wyjsciu z przerwania...

Szukasz drobnej pomocy przy kodowaniu, albo chcesz przedstawić światu swoją gotową lub w trakcie realizacji produkcję? To właściwy dział.
Wiadomość
Autor
przemo.bundy
Posty: 7
Rejestracja: 30 wrz 2017, 14:37

zmiana adresu programu, po wyjsciu z przerwania...

#1 Post autor: przemo.bundy »

Witam Serdecznie.

szukam podpowiedzi w "konstrukcji" kodu.
szkielet kodu jest poniżej.
przerwanie wykonuje kod od etykiety "irq"
program który jest przerywany przerwaniem, znajduje się od etykiety "pusta"
moje pytanie jest takie. Jak po wyjściu z przerwania, zmienić adres wykonywania programu z "pusta".
Na adres etykiety "prog_1".
Czy można coś takiego wykonać, w trakcie wykonywania przerwania?
Moje rozumowanie jest takie. Że gdy wywoływane jest przerwanie. na stos odkładany jest adres w którym miejscu został przerwany program. gdy przerwanie kończy działanie. ze stosu pobierany jest adres gdzie wrócić do programu.
Problem jest z tym, że nie wiem jak się do tego dobrać.
Z góry dzięki za wszelkie podpowiedzi, i pozdrawiam serdecznie fanów C64...

Kod: Zaznacz cały

*=$1000

        sei
        lda #<irq
        sta $0314
        lda #>irq
        sta $0315
        cli
pusta   
        inc $0405
        jmp pusta  
;-------------------------------------------------  
irq     

        jmp $ea31
;-------------------------------------------------
prog_1 
        inc $0400   
        jmp prog_1

Awatar użytkownika
Nitro
Posty: 1551
Rejestracja: 03 wrz 2008, 20:23
Grupa: Black Sun

Re: zmiana adresu programu, po wyjsciu z przerwania...

#2 Post autor: Nitro »

Stos w 6502 jest na stronie $01 ($0100-$01FF) i zjeżdża w dół do $100. Po wywołaniu przerwania na stos idą trzy bajty - wysoki bajt adresu powrotnego, niski, finalnie wartość rejestru S procesora określająca aktualną pozycję na stosie.

Przykładowo jeśli S będzie zawierać $EE po wywołaniu przerwania pamięć będzie wyglądać tak
$1EE - wysoki
$1ED - niski
$1EC - $EE
i finalnie S zmieni się na $EB.

Zawartości S nie da się odczytać programowo.
Tak więc w twoim przypadku trzeba zmienić rejestry powyżej, choć nie pamiętam czy stos jest całkowicie pusty po zwykłym uruchomieniu via RUN z BASICa, możliwe, że coś na nim jest więc adresy będą niżej.
Ogarnij sobie monitor w emu VICE - następujące tematy
breakpoint na przerwaniu
stepowanie
podgląd rejestrów procesora
albo też obadaj polski C64 Debugger

Awatar użytkownika
skull
Posty: 760
Rejestracja: 15 wrz 2008, 08:18
Grupa: samar

Re: zmiana adresu programu, po wyjsciu z przerwania...

#3 Post autor: skull »

no więc korzystając z tego co napisał Nitro. Przy wyjściu z przerwania (jak już odtworzysz rejestry a,x,y):

pla
tax ; zapamiętaj status w x
pla ;stary adres po prostu zrzuc ze stosu
pla
;i wstaw nowy
lda #high_byte_nowego_adresu
pha
lda #low_byte_nowego_adresu
pha
;odwtórz status
txs
rti

a jeśli w ogóle chcesz olać tą pierwszą pętle to przy końcu przerwania (po d019):

pla
pla
pla
cli
jmp gdzie chcesz
Bo pecet to zwykły banan...

przemo.bundy
Posty: 7
Rejestracja: 30 wrz 2017, 14:37

Re: zmiana adresu programu, po wyjsciu z przerwania...

#4 Post autor: przemo.bundy »

idea podpowiedzi ok. ale to nie działa !

niby zdejmuje ze stosu, adres. później odkładam na stos nowy adres gdzie ma wrócić program. po wyjściu z przerwania.
Ale to nie działa. może szanowny "ktoś" wrzuci mi bardzo prosty działający listing. Będę wdzięczny.
Jak zmodyfikować ten program, aby po zmianie adresu powrotu z przerwania. program startował od etykiety "prog_1"

Kod: Zaznacz cały

*=$1000

        sei
        lda #<irq
        sta $0314
        lda #>irq
        sta $0315
        cli
pusta   
        inc $0405
        jmp pusta  
;-------------------------------------------------  
irq     
        pla ;status
        tax
        pla ;H byte
        pla ;L byte

        lda #<prog_1
        pha
        lda #>prog_1
        pha
        txa
        pha
        jmp $ea31

;-------------------------------------------------
prog_1 
        inc $0400
   
        jmp prog_1

mono
Posty: 28
Rejestracja: 03 lis 2008, 18:52
Grupa: tristesse
Kontakt:

Re: zmiana adresu programu, po wyjsciu z przerwania...

#5 Post autor: mono »

Wskaźnikiem stosu manipuluje się za pomocą rozkazów transferów TSX i TXS (co wykorzystuje zresztą systemowa procedura obsługi IRQ do rozpoznania czy źródłem przerwania był rozkaz BRK czy inne IRQ - polecam gorąco http://www.ffd2.com/fridge/docs/c64-diss.html adres $FF48).

Po wystąpieniu przerwania CPU kończy wykonanie aktualnego rozkazu i odkłada na stos: MSB adresu powrotu, LSB adresu powrotu i rejestr _STANU_ CPU czyli P (a nie wskaźnik stosu S, no bo i po co?).

Tak więc masz dwie metody:

1. Jak pisał Skull - zdjąć ze stosu co zostało wrzucone (zerknij na systemową obsługę IRQ, bo korzystasz z wektora CINV=$314 systemu a nie hardwarowego IRQVEC=$FFFE) po czym skoczyć gdzie trzeba:

pla ;y
pla ;x
pla ;a
pla ;p
pla ;lsb
pla ;msb
cli
jmp prog1

To metoda najszybsza.

2. Zmodyfikować adres powrotu na stosie:

tsx
inx ;y
inx ;x
inx ;a
inx ;p
inx
lda #<prog1
sta $100,x
inx
lda #>prog1
sta $100,x
jmp $ea31

Oczywiście niektórzy wolą krócej:

tsx
lda #<prog1
sta $105,x
lda #>prog1
sta $106,x
jmp $ea31

ale ostrzegam przed zawijaniem się stosu - kwestia tego na co sobie możesz pozwolić.

Analogicznie się ma rzecz z obsługą przerwania rozkazu BRK (wektoryzowane przez CBINV=$316), bo BRK odkłada na stos MSB, LSB, P, ale adres powrotu jest _ZA_ argumentem rozkazu BRK (tak, BRK jest rozkazem dwubajtowym).

Obsługa NMI (gdybyś zmienił zdanie co do rodzaju przerwania) jest podobna z tym, że systemowa procedura obsługi $FE43 nie odkłada na stos niczego a skacze od razu do NMINV=$318, więc jest nieco krócej:

pla ;p
pla ;lsb
pla ;msb
cli
jmp prog1

(na przykładzie pierwszej metody zaproponowanej przez Skull'a).

mistrzswiata
Posty: 7
Rejestracja: 03 lis 2017, 07:44

Re: zmiana adresu programu, po wyjsciu z przerwania...

#6 Post autor: mistrzswiata »

Przerwania irt to znaczy że program już się skończył i trzeba od nowa uruchomić telefon ?

dziekuje za odpowiedzi

Radek aka "Mistrz Swiata" ze sceny komputerowej

ODPOWIEDZ