Programowanie: Użycie OS-a przy wyłączonym ROM-ie
From Atariki
Wersja z dnia 01:26, 4 gru 2019 Mono (Dyskusja | wkład) (restrykcje pamieciowe) ← Previous diff |
Wersja z dnia 01:27, 4 gru 2019 Mono (Dyskusja | wkład) (→Restrykcje pamięciowe) Next diff → |
||
Linia 193: | Linia 193: | ||
* $5000..$57FF - SELF-TEST | * $5000..$57FF - SELF-TEST | ||
* $8000..$9FFF - cartridge | * $8000..$9FFF - cartridge | ||
- | * $A000..$BFFF - cartridge, BASIC, wbudowana gra (XEGS) | + | * $A000..$BFFF - cartridge, wbudowany BASIC, wbudowana gra (XEGS) |
* $C000..$FFFF - OS ROM oraz ROM nowego urządzenia ($D800..$DFFF) | * $C000..$FFFF - OS ROM oraz ROM nowego urządzenia ($D800..$DFFF) | ||
Wersja z dnia 01:27, 4 gru 2019
Żeby swobodnie używać mechanizmów OS-a a przy tym mieć dostęp do całego RAM-u trzeba zadbać tylko o poprawne wykonanie przerwań będących w ROM-ie w sytuacji kiedy ten jest wyłączony.
Spis treści |
Handler
Kod handlera przerwań powinien być umieszczony poza obszarem, w którym może się pojawić ROM (patrz "Restrykcje pamięciowe"):
nmiint sec scs irqint clc pha txa pha tsx ;wlaczenie OS ROM inc PORTB ;$D301 ;odlozenie na stos danych dla powrotu z przerwania (RTI) lda #>iret ;adres procedury iret pha lda #<iret pha lda $103,x ;skopiowanie wartosci rejestru stanu procesora pha ;skok przez odpowiedni wektor przerwania scc jmp (NMIVEC) ;$FFFA jmp (IRQVEC) ;$FFFE iret ;wylaczenie OS ROM dec PORTB ;$D301 pla tax pla rti
Inicjalizacja
Wszystko co jest potrzebne do uruchomienia mechanizmu to inicjalizacja wektorów NMIVEC i IRQVEC pod ROM-em:
sei lda #%00000000 sta NMIEN ;$D40E lda #%11111110 sta PORTB ;$D301 ldx #<nmiint ldy #>nmiint stx NMIVEC ;$FFFA sty NMIVEC+1 ldx #<irqint ldy #>irqint stx IRQVEC ;$FFFE sty IRQVEC+1 lda #%01000000 sta NMIEN ;$D40E cli
Od tej pory można swobodnie wyłączać i włączać dowolny obszar ROM (przez zwykłą modyfikację rejestru PORTB) bez obawy o to, że komputer się zawiesi.
Działanie
W przypadku kiedy ROM jest włączony przerwanie obsługiwane jest przez standardowe procedury umieszczone w ROM (ponieważ wektory NMIVEC oraz IRQVEC znajdują się wtedy w obszarze ROM). Kiedy ROM jest odłączony wektor wejścia w przerwanie pobierany jest z NMIVEC lub IRQVEC, które znajdują się w RAM i wykonywana jest procedura przerwania nmiint lub irqint. Obydwie te procedury mają za zadanie włączenie ROM-u, wykonanie procedury obsługi przerwania według wektora znajdującego się już w ROM, oraz przywrócenie konfiguracji ROM po powrocie. Odbywa się to poprzez zapalenie najmłodszego bitu PORTB (włączenie OS ROM), odłożenie na stos adresu powrotu do procedury iret oraz wartości rejestru F procesora odłożonego na stos w sekwencji wywołania przerwania. Zduplikowanie tej wartości jest niezbędne dla poprawnego działania procedur obsługi przerwań zachowanych w ROM, ponieważ testują one:
- czy przerwane zostało wykonanie przerwania IRQ (w przypadku obsługi przerwania NMI),
- czy przerwanie IRQ zostało zgłoszone przez układ I/O, czy może przerwanie zostało wywołane przez rozkaz BRK (w przypadku obsługi przerwania IRQ).
Po wykonaniu procedury z ROM sterowanie przekazywane jest do procedury iret, której jedynym zadaniem jest ponowne odtworzenie konfiguracji pamięci (odłączenie ROM).
Wywoływanie procedur OS
Trzeba pamiętać (co właściwie powinno być oczywiste), że gdy w programie chcemy wywołać dowolną systemową procedurę z ROM, a jest on aktualnie odłączony, to trzeba go sobie włączyć:
lda #%11111111 sta PORTB ;$D301 jsr JSIOINT ;$E459
Odwołania do procedur OS-a odbywają się przez tablice wektorów oraz tablicę skoków. Stanowią one oficjalne punkty wejścia do procedur systemu operacyjnego i gwarantują, że niezależnie od wersji oraz rodzaju systemu operacyjnego zainstalowanego w komputerze zawsze zostanie wywołana procedura żądana przez użytkownika.
Wyjątek stanowią procedury pakietu matematycznego który nie posiada tablicy skoków, przez co odpowiednie procedury niezależnie od wersji pakietu zainstalowanego w komputerze zawsze muszą znajdować się pod ustalonymi adresami.
Przelotki
Wygodnym sposobem realizowania skoków do procedur OS jest zdefiniowanie tzw. "przelotek", które zadbają o konfigurację pamięci i jej odtworzenie już po wykonaniu skoku.
UWAGA! Takie "przelotki" analogicznie, jak procedura handlera przerwań, powinny również znajdować się poza obszarem, w którym może pojawić się ROM (patrz "Restrykcje pamięciowe").
Wywołania przez systemową tablicę skoków:
JSIOINT_jump: lda PORTB ;$D301 pha ora #%00000001 sta PORTB ;$D301 jsr JSIOINT ;$E459 pla sta PORTB ;$D301 rts
Nieco odmienna jest metoda wywoływania procedur dostępnych przez tablicę wektorów, ponieważ wektory wskazują adres procedury zmniejszony o jeden i jako takie służą do wykonania skoku przez RTS:
SIO_S_SPECIAL_jump: lda PORTB pha ora #%00000001 sta PORTB jsr ?call pla sta PORTB rts ?call lda $E410+$0A+1 pha lda $E410+$0A pha rts
Ta metoda powinna być używana również do wywołania procedury PUTBT dostępnej w rejestrze ICPUTB bloku IOCB.
Rejestry OS w RAM
Rejestry $00..$7F oraz $2xx i $3xx są to rejestry zarezerwowane dla potrzeb systemu operacyjnego.
DLI
W przypadku gdy w programie używane jest przerwanie Display List, które zazwyczaj jest krytyczne czasowo, można zmodyfikować punkt wejścia do przerwania NMI tak, aby zagwarantować identyczne zależności czasowe jak w przypadku gdy przerwanie obsługiwane jest bezpośrednio przez procedurę systemu operacyjnego:
nmiint bit NMIST ;$D40F spl jmp (VDSLST) ;$0200 sec scs irqint clc ...
Należy jednak pamiętać, że po wejściu do procedury obsługi przez wektor VDSLST ($200) nie ma gwarancji że ROM jest włączony. Jeśli więc w procedurze obsługi przerwania DLI chcemy użyć jakiejś procedury z ROM należy osobiście zadbać o poprawne skonfigurowanie pamięci, oraz odtworzenie jej przed wyjściem z przerwania n.p. tak:
custom_dli: pha lda PORTB pha ora #%00000001 sta PORTB ... jsr OS_ROUTINE ... pla sta PORTB pla rti
lub też wykorzystać opisane wyżej "przelotki":
custom_dli: pha ... jsr OS_ROUTINE_jump ... pla rti
UWAGA! Należy również mieć na uwadze, że wektor VDSLST powinien wskazywać na procedurę obsługi DLI zdefiniowaną przez użytkownika i znajdującą się poza obszarem w którym może pojawić się ROM (patrz "Restrykcje pamięciowe").
Restrykcje pamięciowe
Procedury handlera, "przelotek" czy procedur użytkownika powinny znajdować się w RAM poza obszarami w którymi istnieje ryzyko pojawienia się pamięci ROM:
- $5000..$57FF - SELF-TEST
- $8000..$9FFF - cartridge
- $A000..$BFFF - cartridge, wbudowany BASIC, wbudowana gra (XEGS)
- $C000..$FFFF - OS ROM oraz ROM nowego urządzenia ($D800..$DFFF)
W przypadku gdy wykorzystywana jest pamięć dodatkowa (XE) również obszar $4000..$7FFF jest obszarem ryzykownym.
Jeśli programista może zagwarantować, że określony rodzaj pamięci nie będzie przełączany, wtedy oczywiście procedury obsługi przełączania pamięci mogą być w umieszczone w odnośnym obszarze (z oczywistych przyczyn obszar OS jest zawsze obszarem ryzykownym).
Trivia
Opisana tutaj sztuczka jest stosowana między innymi przez Turbo BASIC XL, U-BASIC oraz SpartaDOS X.