Programowanie: Program odporny na RESET

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
Wersja z dnia 21:56, 18 paź 2013
Mono (Dyskusja | wkład)
(link do boot)
← Previous diff
Wersja z dnia 21:47, 5 gru 2013
KMK (Dyskusja | wkład)
(BOOT)
Next diff →
Linia 1: Linia 1:
-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.+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.
= BOOT = = BOOT =
Linia 5: Linia 5:
Program ładowany z nośnika za pośrednictwem procedury BOOT otrzymuje sterowanie w dwóch momentach: 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.+1. Po załadowaniu wszystkich sektorów/rekordów programu określonych w [[BOOT (format pliku)|nagłówku BOOT]].
Wywoływana jest wtedy procedura inicjalizacji umiejscowiona pod adresem BOOT_ADDRESS+6. 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.+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 RESET-u.
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. 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.+Jeśli proces inicjalizacji przebiegł poprawnie, procedura powinna zakończyć się ze skasowanym znacznikiem C. Ustawiony znacznik C przy wyjściu z procedury skutkuje zgłoszeniem błędu BOOT ERROR i powtórką (lub, w przypadku magnetofonu, zakończeniem) procesu BOOT-owania.
2. Po zainicjalizowaniu programu. 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.+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 BOOT-owano 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. 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. 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.+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.+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.+Wektor DOSVEC służy również do przekazania sterowania po wydaniu komendy "DOS" BASIC-a, oraz jest ogólnie wektorem wskazującym procedurę uruchomienia programu powłoki (zazwyczaj Command Processor lub Menu DOS-a).
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 lub 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
... ...
- rts 
- 
-start: 
;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 106: Linia 107:
sta CASINI,x sta CASINI,x
sty CASINI+1,x sty CASINI+1,x
- rts+ jmp (DOSVEC)
prolong: prolong:
Linia 124: Linia 125:
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 on dodatkowo na wykorzystanie symboli oraz rezerwacje pamięci.
-Ponieważ SDX nie obsługuje magnetofonu, darujemy sobie rozpoznawanie rodzaju BOOT-a i aktualizację CASINI - skoncentrujemy się wyłącznie na DOSINI.+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 programu po wciśnięciu RESET, ponieważ podczas wywoływania łańcucha inicjalizującego poprzednio zainstalowane w systemie programy, DOS przejmuje kontrolę i nie wraca do procedury inicjującej program.
-== Program nierelokowalny ==+Zapobiega temu wyzerowanie zmiennej COMTAB+$20 (nieoficjalnie zwanej DOSFLG) w fazie inicjalizacji. Gdy odporność na RESET stanie się niepotrzebna (np. tuż przed zakończeniem programu), zmienną tę należy ustawić na dowolną ujemną wartość.
-Bazujemy na systemowym mechanizmie i modyfikujemy jedynie wektor DOSINI/CASINI.+Ponieważ SDX nie obsługuje magnetofonu, można darować sobie rozpoznawanie rodzaju BOOT-a i aktualizację CASINI, a skoncentrować się wyłącznie na DOSINI.
-Przykładowy program nierelokowalny uruchamiany komendą X (dla AtariDOS):+Przykładowy program relokowalny (dla SpartaDOS X):
<pre> <pre>
-prog = $2000+DOSVEC = $a
 +DOSINI = $c
- opt h+ o++COMTAB smb 'COMTAB '
- 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ą niezerową wartość. 
- 
-Przykładowy program relokowalny (dla SpartaDOS X): 
-<pre> 
opt h+ o+ opt h+ o+
blk reloc main blk reloc main
Linia 195: Linia 160:
sty DOSINI+1 sty DOSINI+1
lda #$ff lda #$ff
- sta COMSPEC+$20+ sta COMTAB+$20
- rts+ jmp (DOSVEC)
prolong: prolong:
Linia 209: Linia 174:
sty DOSINI+1 sty DOSINI+1
lda #0 lda #0
- sta COMSPEC+$20+ sta COMTAB+$20
rts rts
Linia 217: Linia 182:
= 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 21:47, 5 gru 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 RESET-u. 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 zgłoszeniem błędu BOOT ERROR i powtórką (lub, w przypadku magnetofonu, zakończeniem) procesu BOOT-owania.

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 BOOT-owano 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, oraz jest ogólnie wektorem wskazującym procedurę uruchomienia programu powłoki (zazwyczaj Command Processor lub Menu DOS-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 lub 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
  ...
  ;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 on 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 programu po wciśnięciu RESET, ponieważ podczas wywoływania łańcucha inicjalizującego poprzednio zainstalowane w systemie programy, DOS przejmuje kontrolę i nie wraca do procedury inicjującej program.

Zapobiega temu wyzerowanie zmiennej COMTAB+$20 (nieoficjalnie zwanej DOSFLG) w fazie inicjalizacji. Gdy odporność na RESET stanie się niepotrzebna (np. tuż przed zakończeniem programu), zmienną tę należy ustawić na dowolną ujemną wartość.

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

Przykładowy program relokowalny (dla SpartaDOS X):

DOSVEC = $a
DOSINI = $c

COMTAB smb 'COMTAB  '

  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 COMTAB+$20
  jmp (DOSVEC)

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 COMTAB+$20
  rts

initad .dw init

Linki