Programowanie: Program odporny na RESET

From Atariki

(Różnice między wersjami)
Jump to: navigation, search
Wersja z dnia 07:38, 19 paź 2013
KMK (Dyskusja | wkład)
(BOOT)
← Previous diff
Aktualna wersja
Mono (Dyskusja | wkład)
(.db i .dw -> .byte i .word)
Linia 9: Linia 9:
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 RESET-u. 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 256 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 powtórką (lub, w przypadku magnetofonu, zakończeniem) procesu BOOT-owania.+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.
Linia 21: Linia 21:
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.+Wektor DOSVEC jest ustawiany przez OS w początkowej fazie procedury RESET na adres wejścia do SELF-TEST, więc jeżeli z procedury DOSINI/CASINI powrócimy do systemu nie ustawiwszy wektora DOSVEC, wtedy OS na końcu odda sterowanie właśnie tam.
-Wektor DOSVEC służy również do przekazania sterowania po wydaniu komendy "DOS" BASIC-a, oraz jest ogólnie wektorem wskazującym procedurę zakończenia programu użytkownika.+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:
Linia 35: Linia 35:
;nagłówek boot ;nagłówek boot
- .db 0 ;flaga boot - nieużywana przez system (niektóre DOS-y ustawiają tu swój identyfikator)+ .byte 0 ;flaga boot - nieużywana przez system (niektóre DOS-y ustawiają tu swój identyfikator)
- .db count ;ilość sektorów boot+ .byte count ;ilość sektorów boot
- .dw prog ;adres ładowania+ .word prog ;adres ładowania
- .dw start ;adres uruchomienia programu+ .word start ;adres uruchomienia programu
init: init:
Linia 95: Linia 95:
;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
... ...
Linia 136: Linia 133:
[[SpartaDOS X]] definiuje specjalny [[COM#SpartaDOS X|relokowalny format pliku binarnego]]. Pozwala on dodatkowo na wykorzystanie symboli oraz rezerwacje pamięci. [[SpartaDOS X]] definiuje specjalny [[COM#SpartaDOS X|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 się po wciśnięciu RESET, ponieważ podczas wywoływania łańcucha inicjalizującego poprzednio zainstalowane w systemie programy DOS nie wraca do naszej procedury inicjującej.+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ść.+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, darujemy sobie rozpoznawanie rodzaju BOOT-a i aktualizację CASINI - skoncentrujemy się wyłącznie na DOSINI.+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): Przykładowy program relokowalny (dla SpartaDOS X):
<pre> <pre>
 +DOSVEC = $a
DOSINI = $c DOSINI = $c
-COMSPEC smb 'COMSPEC '+COMTAB smb 'COMTAB '
opt h+ o+ opt h+ o+
Linia 162: Linia 160:
sty DOSINI+1 sty DOSINI+1
lda #$ff lda #$ff
- sta COMSPEC+$20+ sta COMTAB+$20
- rts+ jmp (DOSVEC)
prolong: prolong:
Linia 176: Linia 174:
sty DOSINI+1 sty DOSINI+1
lda #0 lda #0
- sta COMSPEC+$20+ sta COMTAB+$20
rts rts
-initad .dw init+initad .word init
</pre> </pre>

Aktualna wersja

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 256 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.

Wektor DOSVEC jest ustawiany przez OS w początkowej fazie procedury RESET na adres wejścia do SELF-TEST, więc jeżeli z procedury DOSINI/CASINI powrócimy do systemu nie ustawiwszy wektora DOSVEC, wtedy OS na końcu odda sterowanie właśnie tam.

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
  .byte 0      ;flaga boot - nieużywana przez system (niektóre DOS-y ustawiają tu swój identyfikator)
  .byte count  ;ilość sektorów boot
  .word prog   ;adres ładowania
  .word 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 .word init

Linki

Personal tools