Programowanie: Program odporny na RESET

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
Wersja z dnia 22:37, 18 paź 2013
Mono (Dyskusja | wkład)

← Previous diff
Wersja z dnia 00:40, 19 paź 2013
Mono (Dyskusja | wkład)
(unifikacja procedur dla formatow nierelokowalnych; linki; styl.)
Next diff →
Linia 27: Linia 27:
Przykładowy program bootujący: Przykładowy program bootujący:
<pre> <pre>
 +DOSVEC = $a
 +
prog = $2000 prog = $2000
Linia 40: Linia 42:
init: init:
;tu można zainicjalizować dane nie inicjalizowane po RESET ;tu można zainicjalizować dane nie inicjalizowane po RESET
 + ...
clc clc
rts rts
start: start:
 + ;a tu zainicjalizować dane inicjalizowane po RESET
 + ...
 + ;i przejąć sterowanie
 + ...
 + ;lub ewentualnie zapisać DOSVEC
 + ldx #<run
 + ldy #>run
 + stx DOSVEC
 + sty DOSVEC+1
 + ;i wrócić do systemu
 + rts
 +
 +run:
 + ;a to się będzie wykonywać po zakończeniu BOOT-a i po wydaniu polecenia DOS z BASIC-a
... ...
Linia 50: Linia 67:
</pre> </pre>
-= AtariDOS =+= DOS =
-Standardowy program pracujący pod kontrolą DOS-u nie jest odporny na wciśnięcie klawisza RESET, a więc po jego wciśnięciu kontrola zostaje przekazana do DOS-u.+Program pracujący pod kontrolą jakiegokolwiek DOS-u nie jest odporny na wciśnięcie klawisza RESET. Zostaje on wtedy przerwany, a kontrola przekazywana jest bezpośrednio do DOS-u.
-Aby uodpornić taki program na RESET wykorzystuje się tradycyjny systemowy mechanizm inicjalizowania systemu:+Aby uodpornić taki program na RESET wykorzystuje się tradycyjny mechanizm inicjalizowania systemu.
-1. Poprzez wektor DOSINI/CASINI inicjalizuje się programy TSR i sterowniki zainstalowane w systemie i rozszerzające jego działanie.+Odbywa się to poprzez tzw. przedłużenie wektora DOSINI/CASINI dzięki czemu przed inicjalizacją własnego programu ma szanse zainicjalizować się DOS oraz programy TSR zainstalowane w systemie wcześniej.
-Odbywa się to poprzez tzw. przedłużenie wektora DOSINI/CASINI dzięki czemu przed inicjalizacją własnego programu mają szanse zainicjalizować się DOS oraz programy TSR zainstalowane w systemie wcześniej.+== Format nierelokowalny (zgodny z AtariDOS) ==
-2. Poprzez wektor DOSVEC oddaje się sterowanie do programu, który ma być docelowo uruchomiony po RESET.+Programy w [[Binarny plik DOSu|tradycyjnym formacie binarnym]] nie są relokowalne.
-Odbywa się to przez zapisanie wektora DOSVEC w procedurze inicjalizacji uruchamianej przez DOSINI/CASINI.+Niezależnie od rodzaju DOS-u przez który są uruchamiane przedłużanie wektora CASINI/DOSINI odbywa się w taki sam sposób:
 +<pre>
 +CASINI = 2
 +BOOT? = 9
 +DOSVEC = $a
 +DOSINI = $c
-Standardowo DOS podczas własnej procedury inicjalizacyjnej zapisuje tu adres programu DUP.SYS lub CP.SYS. 
- 
-Programy TSR zazwyczaj potrzebują jedynie zainicjalizować swoje działanie i wykorzystują jedynie DOSINI/CASINI nie zapisując wektora DOSVEC. 
- 
-Przykładowy fragment programu odpornego na RESET: 
-<pre> 
prog = $2000 prog = $2000
Linia 77: Linia 93:
init: init:
jsr prolong jsr prolong
- ldx DOSVEC 
- ldy DOSVEC+1 
- stx olddosvec 
- sty olddosvec+1 
- ldx #<start 
- ldy #>start 
- stx DOSVEC 
- sty DOSVEC+1 
;w przypadku TSR można tutaj podnieść MEMLO ;w przypadku TSR można tutaj podnieść MEMLO
... ...
Linia 92: Linia 100:
;tutaj wykonujemy program główny ;tutaj wykonujemy program główny
... ...
- ;po czym przy wyjściu z programu przywracamy zawartości wektorów+ ;po czym przy wyjściu z programu przywracamy zawartość wektora
- ldx olddosvec+
- ldy olddosvec+1+
- stx DOSVEC+
- sty DOSVEC+1+
lda BOOT? lda BOOT?
ldx #0 ;BOOT z kasety (przywracamy CASINI=$02) ldx #0 ;BOOT z kasety (przywracamy CASINI=$02)
Linia 124: Linia 128:
sty CASINI+1,x sty CASINI+1,x
rts rts
- 
-olddosvec .ds 2 
run init run init
</pre> </pre>
-= SpartaDOS X =+== Format relokowalny (SpartaDOS X) ==
-Generalnym imperatywem jest zakaz modyfikowania zawartości wektora DOSVEC (!), gdyż zawiera on adres bazowy dla różnych zmiennych DOS-a.+[[SpartaDOS X]] definiuje specjalny [[COM#SpartaDOS X|relokowalny format pliku binarnego]]. Pozwala od dodatkowo na wykorzystanie symboli oraz rezerwacje pamięci.
 + 
 +Przedłużenie wektora DOSINI następuje tu analogicznie, jak w przypadku programów nierelokowalnych, okazuje się jednak że to nie wystarcza do poprawnego uruchomienia się po wciśnięciu RESET, ponieważ podczas wywoływania łańcucha inicjalizującego poprzednio zainstalowane w systemie programy DOS nie wraca na powrót do naszej procedury inicjalizującej.
 +Zapobiega temu wyzerowanie zmiennej COMTAB+$20 (nieoficjalnie zwanej DOSFLG) w fazie inicjalizacji.
 +Po zakończeniu programu należy ją ustawić na dowolną ujemną wartość.
Ponieważ SDX nie obsługuje magnetofonu, darujemy sobie rozpoznawanie rodzaju BOOT-a i aktualizację CASINI - skoncentrujemy się wyłącznie na DOSINI. Ponieważ SDX nie obsługuje magnetofonu, darujemy sobie rozpoznawanie rodzaju BOOT-a i aktualizację CASINI - skoncentrujemy się wyłącznie na DOSINI.
-== Program nierelokowalny ==+Przykładowy program relokowalny (dla SpartaDOS X):
- +
-Bazujemy na systemowym mechanizmie i modyfikujemy jedynie wektor DOSINI/CASINI.+
- +
-Przykładowy program nierelokowalny uruchamiany komendą X (dla AtariDOS):+
<pre> <pre>
-prog = $2000+DOSINI = $c
- opt h+ o++COMSPEC smb 'COMSPEC '
- org prog+
-init: 
- jsr prolong 
- ... 
- ;tutaj wykonujemy program główny 
- ... 
- ;po czym przy wyjściu z programu przywracamy zawartość wektora 
- ldx init+1 
- ldy init+2 
- stx DOSINI 
- sty DOSINI+1 
- rts 
- 
-prolong: 
- ;a to wykona się tylko raz po uruchomieniu programu przez DOS 
- ldx DOSINI 
- ldy DOSINI+1 
- stx init+1 
- sty init+2 
- ldx #<init 
- ldy #>init 
- stx DOSINI 
- sty DOSINI+1 
- rts 
- 
- run init 
-</pre> 
- 
-== Program relokowalny == 
- 
-Okazuje się, że to jednak nie wystarcza żeby relokowalny program dla SpartaDOS X mógł poprawnie uodpornić się na RESET, ponieważ podczas wywoływania łańcucha inicjalizującego poprzednio zainstalowane w systemie programy DOS nie wraca na powrót do naszej procedury inicjalizującej, a skacze bezpośrednio przez DOSVEC. 
-Zapobiega temu wyzerowanie zmiennej COMTAB+$20 (nieoficjalnie zwanej DOSFLG) - po zakończeniu programu należy ustawić w niej dowolną ujemną wartość. 
- 
-Przykładowy program relokowalny (dla SpartaDOS X): 
-<pre> 
opt h+ o+ opt h+ o+
blk reloc main blk reloc main
Linia 217: Linia 184:
= Linki = = Linki =
-[[BOOT (format pliku)]]+* [[BOOT (format pliku)|Format BOOT]]
 +* [[Binarny plik DOSu|Format binarnego pliku DOS]]
 +* [[COM#SpartaDOS X|Format binarnego pliku SpartaDOS X]]
[[Kategoria:Programowanie Atari 8-bit]] [[Kategoria:Programowanie Atari 8-bit]]
[[Kategoria:Niezbędnik kodera]] [[Kategoria:Niezbędnik kodera]]

Wersja z dnia 00:40, 19 paź 2013

Uodpornienie programu na wciśnięcie klawisza RESET realizowane jest zależnie od tego w jaki sposób program jest ładowany do pamięci komputera.

Spis treści

BOOT

Program ładowany z nośnika za pośrednictwem procedury BOOT otrzymuje sterowanie w dwóch momentach:

1. Po załadowaniu wszystkich sektorów/rekordów programu określonych w nagłówku BOOT.

Wywoływana jest wtedy procedura inicjalizacji umiejscowiona pod adresem BOOT_ADDRESS+6. Ta procedura wywoływana jest jednorazowo w całym procesie BOOT i jest to dobre miejsce do inicjalizacji danych, które nie będą inicjalizowane po wykonaniu RESETu. Ponieważ długość programu bootowalnego ograniczona jest do 255 sektorów/rekordów, jest to również dobre miejsce do załadowania pozostałej części programu do pamięci. Jeśli proces inicjalizacji przebiegł poprawnie procedura powinna zakończyć się ze skasowanym znacznikiem C. Ustawiony znacznik C przy wyjściu z procedury skutkuje głoszeniem błędu BOOT ERROR i zakończeniem procesu BOOTowania.

2. Po zainicjalizowaniu programu.

Adres startu programu umiejscowiony pod adresem BOOT_ADDRESS+4 przepisywany jest do DOSINI ($0C) jeśli BOOT odbywał się z dysku, lub do CASINI ($02) jeśli BOOTowano z kasety, i jest to automatycznie adres, pod który system operacyjny będzie przekazywał kontrolę programowi po naciśnięciu klawisza RESET.

Nie należy ingerować w zawartość rejestru BOOT? ($09), gdyż jest on ustawiany przez system operacyjny.

Wektor inicjalizacji DOSINI/CASINI może zostać wykorzystany do natychmiastowego uruchomienia programu, lub też do jego inicjalizacji i ustawienia wektora DOSVEC ($0A), do którego sterowanie przekazywane jest przez procedurę RESET po całkowitym zakończeniu jej działania. W ten sposób instaluje się w systemie DOS.

Jeżeli z procedury DOSINI/CASINI powrócimy do systemu nie ustawiwszy wektora DOSVEC, wtedy OS ustawi tam adres procedury SELF TEST.

Wektor DOSVEC służy również do przekazania sterowania po wydaniu komendy DOS BASIC-a.

Przykładowy program bootujący:

DOSVEC = $a

prog = $2000

  opt h- o+
  org prog

;nagłówek boot
  .db 0      ;flaga boot - nieużywana przez system (niektóre DOS-y ustawiają tu swój identyfikator)
  .db count  ;ilość sektorów boot
  .dw prog   ;adres ładowania
  .dw start  ;adres uruchomienia programu

init:
  ;tu można zainicjalizować dane nie inicjalizowane po RESET
  ...
  clc
  rts

start:
  ;a tu zainicjalizować dane inicjalizowane po RESET
  ...
  ;i przejąć sterowanie
  ...
  ;lub ewentualnie zapisać DOSVEC
  ldx #<run
  ldy #>run
  stx DOSVEC
  sty DOSVEC+1
  ;i wrócić do systemu
  rts

run:
  ;a to się będzie wykonywać po zakończeniu BOOT-a i po wydaniu polecenia DOS z BASIC-a
  ...

len = *-prog
count = (len+127)/128 ;obliczenie ilości sektorów boot - ceil(len/128)

DOS

Program pracujący pod kontrolą jakiegokolwiek DOS-u nie jest odporny na wciśnięcie klawisza RESET. Zostaje on wtedy przerwany, a kontrola przekazywana jest bezpośrednio do DOS-u.

Aby uodpornić taki program na RESET wykorzystuje się tradycyjny mechanizm inicjalizowania systemu.

Odbywa się to poprzez tzw. przedłużenie wektora DOSINI/CASINI dzięki czemu przed inicjalizacją własnego programu ma szanse zainicjalizować się DOS oraz programy TSR zainstalowane w systemie wcześniej.

Format nierelokowalny (zgodny z AtariDOS)

Programy w tradycyjnym formacie binarnym nie są relokowalne.

Niezależnie od rodzaju DOS-u przez który są uruchamiane przedłużanie wektora CASINI/DOSINI odbywa się w taki sam sposób:

CASINI = 2
BOOT? = 9
DOSVEC = $a
DOSINI = $c

prog = $2000

  opt h+ o+
  org prog

init:
  jsr prolong
  ;w przypadku TSR można tutaj podnieść MEMLO
  ...
  rts

start:
  ;tutaj wykonujemy program główny
  ...
  ;po czym przy wyjściu z programu przywracamy zawartość wektora
  lda BOOT?
  ldx #0      ;BOOT z kasety (przywracamy CASINI=$02)
  cmp #2
  beq @+
  ldx #10     ;BOOT z dysku (przywracamy DOSINI=$0C)
@ lda init+1
  ldy init+2
  sta CASINI,x
  sty CASINI+1,x
  jmp (DOSVEC)

prolong:
  ;a to wykona się tylko raz po uruchomieniu programu przez DOS
  lda BOOT?
  ldx #0      ;BOOT z kasety (przedłużamy CASINI=$02)
  cmp #2
  beq @+
  ldx #10     ;BOOT z dysku (przedłużamy DOSINI=$0C)
@ lda CASINI,x
  ldy CASINI+1,x
  sta init+1
  sty init+2
  lda #<init
  ldy #>init
  sta CASINI,x
  sty CASINI+1,x
  rts

  run init

Format relokowalny (SpartaDOS X)

SpartaDOS X definiuje specjalny relokowalny format pliku binarnego. Pozwala od dodatkowo na wykorzystanie symboli oraz rezerwacje pamięci.

Przedłużenie wektora DOSINI następuje tu analogicznie, jak w przypadku programów nierelokowalnych, okazuje się jednak że to nie wystarcza do poprawnego uruchomienia się po wciśnięciu RESET, ponieważ podczas wywoływania łańcucha inicjalizującego poprzednio zainstalowane w systemie programy DOS nie wraca na powrót do naszej procedury inicjalizującej. Zapobiega temu wyzerowanie zmiennej COMTAB+$20 (nieoficjalnie zwanej DOSFLG) w fazie inicjalizacji. Po zakończeniu programu należy ją ustawić na dowolną ujemną wartość.

Ponieważ SDX nie obsługuje magnetofonu, darujemy sobie rozpoznawanie rodzaju BOOT-a i aktualizację CASINI - skoncentrujemy się wyłącznie na DOSINI.

Przykładowy program relokowalny (dla SpartaDOS X):

DOSINI = $c

COMSPEC smb 'COMSPEC '

  opt h+ o+
  blk reloc main

init:
  jsr prolong
  ...
  ;tutaj wykonujemy program główny
  ...
  ;po czym przy wyjściu z programu przywracamy zawartość wektora
  ldx init+1
  ldy init+2
  stx DOSINI
  sty DOSINI+1
  lda #$ff
  sta COMSPEC+$20
  rts

prolong:
  ;a to wykona się tylko raz po uruchomieniu programu przez DOS
  ldx DOSINI
  ldy DOSINI+1
  stx init+1
  sty init+2
  ldx initad
  ldy initad+1
  stx DOSINI
  sty DOSINI+1
  lda #0
  sta COMSPEC+$20
  rts

initad .dw init

Linki