Powrót do spisu treści |
Rozdział 1URUCHOMIENIE INTERPRETERAW czasie inicjowania systemu komputerowego przez procedurę RESET (zob. "Mapa pamięci Atari XL/XE. Podstawowe procedury systemu operacyjnego") inicjowany jest także zainstalowany cartridge. Po zakończeniu inicjowania i ewentualnym odczytaniu DOS-u sterowanie komputerem jest przekazywane do cartridge'a, którego rolę pełni w tym przypadku interpreter Basica. Odpowiednie informacje znajdują się w czterech rejestrach umieszczonych na końcu obszaru zajętego przez cartridge.Warto przy okazji wspomnieć, że na końcu interpretera pozostało dziewięć pustych bajtów pamięci (równych $00), które można wykorzystać przy jego modyfikowaniu. Te niewykorzystane bajty znajdują się w obszarze $BFF1-$BFF9. 0100 ;CARTridge 0110 ; 0120 *= $BFFA 0130 ; 0140 CARTRUN .WORD $A000 0150 CARTINS .BYTE $00 0160 CARTOPT .BYTE $05 0170 CARTINI .WORD $BFF0Bajt $00 w rejestrze CARTINS (CARTridge INSerted) oznacza, że cartridge jest obecny i należy przekazać mu sterowanie. W celu zainicjowania cartridge'a wywoływana jest procedura, której adres zawiera rejestr CARTINI (CARTridge INItialization address). W przypadku interpretera Basica adres ten wskazuje tylko na instrukcję RTS, a więc interpreter nie wymaga inicjowania i następuje powrót do procedury RESET. Kolejnym sprawdzanym rejestrem jest CARTOPT (CARTridge OPTions). Jeśli zawiera on wartość różną od zera (jak w tym przypadku) to wykonywany jest wstępny odczyt z dyskietki. Po całkowitym zainicjowaniu systemu procedura RESET kończy się skokiem do adresu wskazanego wektorem CARTRUN (CARTridge RUN address). W interpreterze Basica znajduje się tu adres procedury zimnego startu interpretera CDST. Na początku procedury CDST sprawdzane są znaczniki LOADFLG (LOADing FLaG) i WARMST (WARM STart). Gdy pierwszy z nich jest różny od zera, to znaczy, że start systemu odbywa się w trakcie odczytu z urządzenia zewnętrznego i przeprowadzany jest start zimny. W przeciwnym razie start gorący jest wykonywany, jeśli znacznik WARMST jest różny od zera. Przy zimnym starcie najpierw wartość dolnej granicy dostępnej pamięci RAM jest przepisywana z rejestru MEMLO do rejestru LOMEM, a znaczniki LOADFLG i MEOLFLG (Modified End Of Line FLaG) są zerowane. Następnie wartość z MEMLO jest umieszczana w rejestrach określających położenie bloków programu od VNTP do BMEMHI (zob. Wprowadzenie). Z kolei poprzez dwukrotne wywołanie procedury INSEL wszystkie bloki powyżej tablicy nazw zmiennych przesuwane są o jeden bajt, a bloki powyżej tablicy instrukcji jeszcze o trzy bajty. W uzyskane w ten sposób miejsce w tabeli nazw zmiennych wpisywane jest zero (nie ma nazwy żadnej zmiennej), a do tabeli instrukcji ciąg bajtów $00, $80, $03, który oznacza pustą instrukcję w trybie bezpośrednim (dokładnie jest to opisane w rozdziale poświęconym tokenizacji programu). Faza zimnego startu kończy się wpisaniem wartości $0A do rejestru tabulacji PTABW (Position of TABulate Width). 0100 ;Start Basic cartridge 0110 ; 0120 CLALL = $BD45 0130 INSEL = $A87A 0140 LOADFLG = $CA 0150 LOMEM = $80 0160 MEOLFLG = $92 0170 MEMLO = $02E7 0180 PRTPRM = $BD62 0190 PSTMAD = $BD9D 0200 PTABW = $C9 0210 RSTBRG = $A8F1 0220 RSTCHN = $BD5B 0230 STARP = $8C 0240 STMCUR = $8A 0250 VNTD = $84 0260 VNTP = $82 0270 VVTP = $86 0280 WARMST = $08 0290 ; 0300 *= $A000 0310 ; 0320 ;ColD STart 0330 ; 0340 CDST LDA LOADFLG 0350 BNE CONT 0360 LDA WARMST 0370 BNE WMST 0380 CONT LDX #$FF 0390 TXS 0400 CLD 0410 ; 0420 ;eXecute NEW statement 0430 ; 0440 XNEW LDX MEMLO 0450 LDY MEMLO+1 0460 STX LOMEM 0470 STY LOMEM+1 0480 LDA #$00 0490 STA MEOLFLG 0500 STA LOADFLG 0510 INY 0520 TXA 0530 LDX #VNTP 0540 LOOP STA $00,X 0550 INX 0560 STY $00,X 0570 INX 0580 CPX #MEOLFLG 0590 BCC LOOP 0600 LDX #VVTP 0610 LDY #$01 0620 JSR INSEL 0630 LDX #STARP 0640 LDY #$03 0650 JSR INSEL 0660 LDA #$00 0670 TAY 0680 STA (VNTD),Y 0690 STA (STMCUR),Y 0700 INY 0710 LDA #$80 0720 STA (STMCUR),Y 0730 INY 0740 LDA #$03 0750 STA (STMCUR),Y 0760 LDA #$0A 0770 STA PTABW 0780 WMST JSR RSTBRG 0790 ; 0800 ;WaRM STart 0810 ; 0820 WRMST JSR CLALL 0830 WRMST2 JSR RSTCHN 0840 LDA MEOLFLG 0850 BEQ WAITIN 0860 JSR PSTMAD 0870 ; 0880 ;WAIT for INput 0890 ; 0900 WAITIN JSR PRTPRMDalszy przebieg procedury CDST jest wspólny zarówno dla zimnego, jak i gorącego startu. Najpierw wywoływana jest procedura RSTBRG, która zeruje rejestry DATAD (DATa ADdress), DATALN (DATA LiNe number), ERRCOD (ERRor CODe), STOPLN (STOP LiNe number) i RADFLG (RADian FLaG) oraz umieszcza wartość $80 w rejestrze IRQSTAT (IRQ STATus) i w starszym bajcie rejestru TRAPLN (TRAP LiNe number). Procedura ta kończy się bezpośrednim skokiem do procedury CLALL. Zaraz po zakończeniu procedura ta jest wywoływana ponownie. Jest to spowodowane koniecznością wywoływania procedury CLALL przy wznawianiu pracy interpretera od etykiety WRMST. Natomiast procedura RSTBRG jest wykorzystywana także przez inne procedury interpretera i zakończenie jej skokiem do CLALL oszczędza kilkanaście bajtów pamięci. Sama procedura CLALL najpierw zeruje rejestry generatorów dźwięku AUDF i AUDC, a więc wyłącza dźwięk. Następnie wywołuje siedem razy procedurę CLCHN umieszczając w rejestrze IODVC (Input/Output DeViCe) wartości od 7 do 1, co powoduje zamknięcie wszystkich kanałów komunikacji z urządzeniami zewnętrznymi poza kanałem 0 używanym przez edytor. Procedura CLCHN jest opisana w rozdziale 6.4. (Obsługa komunikacji). 0100 ;ReSeT Basic ReGisters 0110 ; 0120 CLALL = $BD45 0130 DATAD = $B6 0140 IRQSTAT = $11 0150 RADFLG = $FB 0160 TRAPLN = $BC 0170 ; 0180 *= $B8F1 0190 ; 0200 LDX #$05 0210 LDY #$00 0220 LOOP STY DATAD,X 0230 DEX 0240 BPL LOOP 0250 STY RADFLG 0260 DEY 0270 STY TRAPLN+1 0280 STY IRQSTAT 0290 JMP CLALL 0100 ;CLose ALL channels 0110 ; 0120 AUDF1 = $D200 0130 CLCHN = $BCF7 0140 IODVC = $C1 0150 ; 0160 *= $BD45 0170 ; 0180 LDA #$00 0190 LDX #$07 0200 SND STA AUDF1,X 0210 DEX 0220 BNE SND 0230 LDY #$07 0240 STY IODVC 0250 CHN JSR CLCHN 0260 DEC IODVC 0270 BNE CHN 0280 RTSJeżeli znacznik końca wiersza MEOLFLG jest różny od zera, to teraz jest wywoływana procedura PSTMAD. Jest to możliwe jedynie w przypadku gorącego startu interpretera. Odczytuje ona zawartość rejestru CSTAD (Current STatement ADdress) i umieszcza młodszy bajt w buforze wejściowym, w miejscu wskazanym przez starszy bajt. Na zakończenie zerowany jest znacznik MEOLFLG. 0100 ;Put STateMent ADdress 0110 ; 0120 CSTAD = $97 0130 INBUFP = $F3 0140 MEOLFLG = $92 0150 ; 0160 *= $BD9D 0170 ; 0180 LDY CSTAD+1 0190 LDA CSTAD 0200 STA (INBUFP),Y 0210 LDA #$00 0220 STA MEOLFLG 0230 RTSProcedura startu interpretera kończy się wywołaniem procedury PRTPRM. Powoduje ona umieszczenie na ekranie napisu "READY" oraz znaków końca wiersza (RETURN) przed i za napisem. Dzięki temu napis ten pojawia się zawsze w nowym wierszu ekranu. Procedura PRTPRM po wywołaniu od etykiety PRTRET służy do umieszczenia na ekranie tylko znaku RETURN. Do służącego jako licznik wyświetlanych znaków rejestru X jest wtedy wpisywana wartość zero zamiast sześć. Wykorzystywana przez PRTPRM procedura PRPCHN jest opisana także w rozdziale "Obsługa komunikacji" (6.4). 0100 ;PRinT PRoMpt 0110 ; 0120 CIX = $F2 0130 PRPCHN = $BA99 0140 ; 0150 *= $BD62 0160 ; 0170 PRTPRM LDX #$06 0180 LOOP STX CIX 0190 LDA READYP,X 0200 JSR PRPCHN 0210 LDX CIX 0220 DEX 0230 BPL LOOP 0240 RTS 0250 ; 0260 ;READY Prompt 0270 ; 0280 READYP .BYTE $9B,"YDAER",$9B 0290 ; 0300 ;PRinT RETurn character 0310 ; 0320 PRTRET LDX #$00 0330 BEQ LOOPPo wykonaniu wszystkich opisanych wyżej czynności następuje bezpośrednie przejście do procedury kontroli składni programu - SYNTAX, której opis znajduje się w następnym rozdziale. Należy jeszcze zwrócić uwagę na kilka etykiet znajdujących się w procedurze startu. Są one wykorzystywane przez inne procedury interpretera, jeśli wymagane jest ponowne jego zainicjowanie. Pozostała jeszcze do omówienia wywoływana przez CDST procedura INSEL. Tworzy ona miejsce dla umieszczania wewnątrz obszaru pamięci programu nowych elementów tego programu: wierszy, zmiennych, wartości itd. Przed jej wywołaniem w rejestrze Y musi zostać umieszczona wielkość wstawianego elementu programu, a w rejestrze X adres wektora wskazującego miejsce jego wpisania do programu. 0100 ;INSert program ELement 0110 ; 0120 APPMHI = $0E 0130 BMEMHI = $90 0140 CSTAD = $97 0150 INSMER = $B930 0160 LENPEL = $A4 0170 MEMTOP = $02E5 0180 MEOLFLG = $92 0190 MRANGE = $A2 0200 NEWMHI = $9B 0210 OLDMHI = $99 0220 ; 0230 *= $A87A 0240 ; 0250 LDA #$00 0260 STY LENPEL 0270 STA LENPEL+1 0280 TYA 0290 SEC 0300 ADC BMEMHI 0310 TAY 0320 LDA BMEMHI+1 0330 ADC LENPEL+1 0340 CMP MEMTOP+1 0350 BCC SET 0360 BNE ERR 0370 CPY MEMTOP 0380 BCC SET 0390 BEQ SET 0400 ERR JMP INSMER 0410 SET SEC 0420 LDA BMEMHI 0430 SBC $00,X 0440 STA MRANGE 0450 LDA BMEMHI+1 0460 SBC $01,X 0470 STA MRANGE+1 0480 CLC 0490 ADC $01,X 0500 STA OLDMHI+1 0510 LDA $00,X 0520 STA OLDMHI 0530 STA CSTAD 0540 ADC LENPEL 0550 STA NEWMHI 0560 LDA $01,X 0570 STA CSTAD+1 0580 ADC LENPEL+1 0590 ADC MRANGE+1 0600 STA NEWMHI+1 0610 LOOP LDA $00,X 0620 ADC LENPEL 0630 STA $00,X 0640 LDA $01,X 0650 ADC LENPEL+1 0660 STA $01,X 0670 INX 0680 INX 0690 CPX #MEOLFLG 0700 BCC LOOP 0710 STA APPMHI+1 0720 LDA BMEMHI 0730 STA APPMHI 0740 LDX MRANGE+1 0750 INX 0760 LDY MRANGE 0770 BNE DCR2 0780 NOP 0790 BEQ NXT2 0800 NOP 0810 DCR1 DEY 0820 DEC OLDMHI+1 0830 DEC NEWMHI+1 0840 NXT1 LDA (OLDMHI),Y 0850 STA (NEWMHI),Y 0860 DCR2 DEY 0870 BNE NXT1 0880 LDA (OLDMHI),Y 0890 STA (NEWMHI),Y 0900 NXT2 DEX 0910 BNE DCR1 0920 RTSPrzekazana do procedury wielkość wstawianego elementu jest najpierw umieszczana w rejestrze LENPEL (LENgth of Program ELement), a następnie dodawana jest do niej aktualna zawartość rejestru BMEMHI. Jeśli uzyskany wynik przekracza wartość MEMTOP (MEMory TOP), to przez skok do procedury INSMER sygnalizowany jest brak wystarczającego obszaru pamięci (INSufficient Memory ERror) - zob. rozdział 3, "Obsługa błędów". W przeciwnym razie wszystkie elementy programu o wyższych adresach są przesuwane w górę, aby uzyskać miejsce dla nowego elementu. Przed przemieszczeniem obliczana jest wielkość przesuwanego bloku, a uzyskany wynik zapisywany jest w rejestrze MRANGE (Memory RANGE). Aktualny adres końca programu jest przepisywany do rejestrów OLDMHI (OLD Memory HIgh address) oraz CSTAD i, po dodaniu wielkości elementu, umieszczany jest w rejestrze NEWMHI (NEW Memory HIgh address). Teraz wielkość elementu zawarta w LENPEL służy do skorygowania wartości wektorów wskazujących przesuwane bloki programu. Poprawiana jest również zawartość rejestru APPMHI (APPlication Memory HIgh address) wykorzystywanego przez system operacyjny. Ostatecznie zawartość obszaru pamięci o wielkości określonej przez MRANGE jest przemieszczana od adresu wskazanego wektorem OLDMHI do adresu wskazanego przez NEWMHI. Przemieszczenie to jest wykonywane od wyższych do niższych adresów, aby uniknąć zniszczenia przepisywanej informacji. W opróżnionym w ten sposób miejscu dotychczasowa zawartość pozostaje nadal, aż do wpisania nowych informacji (obszar ten nie jest zerowany). Procedura INSEL jest często wykorzystywana przez interpreter, posiada także swój odpowiednik o odwrotnym działaniu - DELEL - opisany w następnym rozdziale. |