Programowanie: Program odporny na RESET

From Atariki

Jump to: navigation, search

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

Personal tools