C64 Memory Map
by Michael Steil, github.com/mist64/c64ref. Revision 15fbd50, 2020-08-22
This allows you to view different commentaries side-by-side. You can enable/disable individual columns:Mapping the Commodore 64 | Reference from Mapping the Commodore 64 by Sheldon Leemon, ISBN 0-942386-23-X. | |
64'er [German] | German-language reference from Memory Map mit Wandervorschlägen by Dr. H. Hauck, in 64'er Sonderheft 1986/07. | |
64 intern [German] | German-language reference from Das neue Commodore-64-intern-Buch by Data Becker, ISBN 3890113079. | |
Joe Forster/STA | Reference by Joe Forster/STA, with awsm's changes applied. | |
Microsoft/Commodore Source | Comments from the original M6502 BASIC source by Microsoft and the original C64 KERNAL source by Commodore | |
Programmer's Reference Guide | Reference from Commodore 64 Programmer's Reference Guide. | |
64map | Reference as found in "Commodore_64_Memory_Maps.txt" by anonymous. | |
Jim Butterfield | Reference by Jim Butterfield in COMPUTE! #29 (October 1982). |
Address | Symbol | Decimal | Mapping the Commodore 64 | 64'er [German] | 64 intern [German] | Joe Forster/STA | Microsoft/Commodore Source | Programmer's Reference Guide | 64map | Jim Butterfield | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$0000 | D6510 | 0 |
6510 On-Chip I/O DATA Direction Register
This location is the first of a number of hardware registers that we will discuss. Although they can be written to and/or read like RAM, they are connected to hardware devices, and their contents affect the operation of the devices. Each bit of this Data Direction Register determines whether the contents of the corresponding bit on the Internal I/O Port (see location 1) can be written to by peripheral devices. If the bit is set to 0, it indicates the direction of data flow as Input, which means that the corresponding bit of the I/O port will be affected by peripheral defices. If the bit is set to 1, it indicates Output. On the 64, only Bits 0-5 are significant. On power-up, this register is set to 239 ($EF), which indicates that all bits, except for Bit 4 (which senses the cassette switch), are set up for Output. |
Datenrichtungsregister für Ein-/Ausgabe-Port des 6510-Mikroprozessors |
Datenrichtungsregister für Prozessor- PortBit 0 - 6; 0= Eingang 1= Ausgang |
Processor port data direction registerBits:
Default: $2F, %00101111. |
6510 data direction register | 6510 On-Chip Data-Direction Register | 6510 On-chip Data Direction Register. | Chip directional register | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0001 | R6510 | 1 |
6510 On-Chip I/O Port
The chief function of this register is to determine which blocks of RAM and ROM the 6510 microprocessor will address. The Commodore 64 comes with 64K RAM, even though it normally does not use all of that RAM at once. In addition, it has an 8K BASIC Interpreter ROM, an 8K Operating System Kernal ROM, a 4K Character Generator ROM, a Sound Interface Device (SID), a 6566 Video Interface Controller (VIC-II), and two 6526 Complex Interface adapter chips. To address all of these at once would require 88K, 24K past the addressing limit of the 6510 microprocessor. In order to allocate address space, the I/O Port is used to affect the addressing lines, and thus determine which segments of RAM and ROM will be addressed at any one time. Bit 0. This bit controls the LORAM signal. A 0 in this bit position switches the BASIC ROM out, and replaces it with RAM at addresses 40960-49151 ($A000-$BFFF). The default value of this bit is 1. Bit 1. Bit 1 controls the HIRAM signal. A 0 in this bit position switches the Kernal ROM out, and replaces it with RAM at 57344-65535 ($E000-$FFFF). As the BASIC interpreter uses the Kernal, it is also switched out and replaced by RAM. The default value of this bit is 1. The system allows a wide range of combinations of RAM and ROM to be utilized. Of course, the BASIC programmer will have little need, in the ordinary course of events, to switch out the BASIC ROM and the Kernal. To do so would just hang the system up. But one way to make use of this feature is to move the contents of ROM to the corresponding RAM addresses. That way, you can easily modify and customize the BASIC interpreter and OS Kernal routines, which are ordinarily fixed in ROM. For examples, to move BASIC into RAM, just type:
Though it appears that such a program would not do anything, it in fact copies bytes from ROM to RAM. This is because any data which is written to a ROM location is stored in the RAM which resides at the same address. So while you are PEEKing ROM, you are POKEing RAM. To switch to your RAM copy of BASIC, type in:
Now you are ready to make modifications. Examples of simple modifications include changing the text which the interpreter prints, such as the READY prompt, the power-up message, or the keyword table. An example of the latter would be POKE 41122,69. This changes the FOR keyword to FER, so that BASIC would respond normally to a FER-NEXT loop, but fail to recognize FOR as syntactically correct. On the more practical side, you could change the prompt that INPUT issues to a colon, rather than a question mark:
You are not limited to just cosmetic changes of text. Jim Butterfield has given an example in COMPUTE! magazine of changing the interpreter so that it assigns a null string the ASCII value 0. In the ROM version, the command PRINT ASC("") will return ?ILLEGAL QUANTITY ERROR. This is inconvenient when INPUTting a string, because if the user presses RETURN and you try to check the ASCII value of the string that has been entered, you will get this error. By entering POKE 46991,5, this is changed so that PRINT ASC("") now responds with a zero. For the more serious machine language programmer, it is quite feasible to add new commands or modify existing ones by diverting the vectors which are discussed in the section covering the BASIC interpreter ROM. For a good example of this technique, see the article "Hi-Res Graphics Made Simple" by Paul Schatz in COMPUTE!'s First Book of Commodore 64 Sound and Graphics. The program example there inserts new graphics commands into a RAM version of BASIC. When you want to switch back to the ROM BASIC, enter POKE 1,PEEK(1) OR 1. For machine language applications, it would be possible to replace the ROM programs with an entirely different operating system, or an application that has its own screen editing and I/O functions included. Such an application would first have to be loaded from disk into RAM. A language other than BASIC could be loaded, and could then just switch out the BASIC ROM, while still using the OS Kernal. Or a spreadsheet application that contained its own I/O routines could switch out all ROMs and have the use of all of RAM that is not actually needed for the program itself, for data. It should be remembered, however, that before switching the Kernal out, it is necessary to disable interrupts, as the vectors for these interrupts are contained in the Kernal. Bit 2. This bit controls the CHAREN signal. A 0 in this position switches the character generator ROM in, so that it can be read by the 6510 at addresses 53248-57343 ($D000-$DFFF). Normally, this bit is set to 1, so that while the VIC-II chip has access to the character generator ROM for purposes of creating the screen display, the user cannot PEEK into it. Since this ROM is switched into the system in the same location as the I/O devices (SID chip, VIC-II chip, and 6526 CIA's), o I/O can occur when this ROM is switched in. The ability to switch in the character generator ROM is very useful to the programmer who wishes to expirement with user-defined characters. Modified character graphics is one of the more powerful graphics tools available, but often the user will not want to redefine a whole character set at one time. By reading the character ROM and duplicating its contents in RAM, the user can replace only a few characters in the set. The method for reading this ROM into RAM from BASIC is as follows:
The first POKE is necessary to turn off the system timer interrupt. Since the I/O devices are addressed in the same space as the character ROM, switching that ROM in switches all I/O out, making it necessary to turn off any interrupts which use these devices. The second POKE is the one which switches in the character ROM. The program loop then reads this ROM memory into RAM, starting with the address BASE. Note that this address should start on an even 2K boundary (an address evenly divisible by 2048) within the block of memory presently being addresses by the VIC-II chip (for more information on where to put user-defined character sets, and how to use them, see the section on the VIC-II chip, under location 53272 ($D018), the section on the character ROM at 49152 ($C000), and the section on banking VIC-II memory at 56576 ($DD00)). After reading the contents of ROM into RAM, the next POKEs switch out the character ROM and restore the interrupt. It should be noted that while Bits 0-2 of this register allow software control of some signals that determine the memory configuration that is used by the Commodore 64 at any given time, they are not the only determining factor. Signals can also be generated by means of plug-in expansion cartridges which are connected to the expansion port, and these can change the memory map. Two lines located on the exapansion port are called GAME and EXROM. When used in conjunction with the software-controlled lines noted above, these two hardware lines can enable cartridge ROM to replace various segments of ROM and/or RAM. Possible configurations include 8K of cartridge ROM to be switched in at $8000-$9FFF, for a BASIC enhancement program; an 8K cartridge ROM at $A000-$BFFF, replacing BASIC, or at $E000-$FFFF, replacing the Kernal, or a 16k cartridge at $8000-$C000. When cartridge ROM is selected to replace the Kernal, a Max emulator mode is entered, which mimics the specification of the ill-fated Max Machine, a game machine which Commodore never produced for sale in the U.S. In this mode, only the first 6K of RAM are used, there is no access to the character ROM, and graphics data such as charactger dot-data is mapped down from 57344 ($E000) to 8192 ($2000). Further hardware information may be obtained from the Commodore 64 Programmer's Reference Guide. Bits 3-5 of this register have functions connected with the Datasette recorder. These are as follows: Bit 3. This is the Cassette Data Output line. This line is connected to the Cassette Data Write line on the cassette port, and is used to send the data which is written to tape. Bit 4. This bit is the Cassette Switch Sense line. This bit enables a program to tell whether or not one of the buttons that moves the recorder is pressed down. If the switch on the recorder is down, this bit will have a value of 1. Remember that Bit 4 of the data direction register at location 0 must contain a 0 for this bit to properly reflect the status of the switch. Bit 5. Bit 5 is the Cassette Motor Control. Setting this bit to zero allows the motor to turn when you press one of the buttons on the recorder, while setting it to one disables it from turning. Most of the time, the setting of this bit will be controlled by the interrupt routine that is used to read the keyboard every sixtieth of a second. If none of the buttons on the recorder is pressed, that interrupt routine shuts the motor off and sets the interlock at location 192 ($C0) to zero. When a button is pressed, if the interlock location is zero, Bit 5 of this register is set to zero to turn the motor on. When the interlock location contains a zero, the keyscan routine will not let you control the setting of this bit of the register (and the interlock is always set to zero when no buttons are pressed). In order for you to gain control of the motor, you must POKE a nonzero value into 192 after a button on the recorder has been pressed. You can then shut off the motor and turn it back on as you please, by manipulating this bit, so long as a button stays pressed. |
Datenregister für Ein-/Ausgabe-Port des 6510-MikroprozessorsIm Gegensatz zum Mikroprozessor des VC 20 hat der des C 64 sechs Ein-/Ausgabe- Leitungen, die einzeln programmierbar sind und so eine direkte Verbindung zwischen dem Mikroprozessor und der Außenwelt herstellen. Warum nur sechs Leitungen und nicht wie üblich acht? Auf dem Chip selbst könnten acht Bit verkraftet werden, aber es stehen nur sechs Anschlußbeine zur Verfügung. Um trotzdem flexibel zu bleiben, ist dieses Tor zum Prozessor - zutreffend auch »Port« genannt - in beiden Richtungen begehbar. Jede einzelne der sechs Leitungen kann vom Programmierer auf »Eingang« oder auf »Ausgang« geschaltet werden. Dazu dient das Datenrichtungsregister in der Speicherzelle 0. Datenrichtungsreglster in Zelle 0Wenn zum Beispiel in das Bit 4 der Zelle 0 eine 0 hineingePOKEt wird, ist die Leitung Nummer 4 des Ports auf »Eingang« geschaltet. Es gilt für alle 6 Bit (Nummer 0 bis 5):
Beim Einschalten schreibt das Betriebssystem in dieses Register die Dualzahl ..101111 (dezimal=47). Das heißt also, daß nur die Leitung Nummer 4 als Eingang verwendet wird, alle anderen aber als Ausgang. Warum das so ist, sehen wir gleich. Vorher will ich aber noch erwähnen, daß im C 64 von dieser Flexibilität des Mikroprozessor-Ports kein Gebrauch gemacht wird. Ich habe das ganze Betriebssystem durchgesehen, aber das einzige Mal, wo die Speicherzelle 0 angesprochen wird, ist eben bei der Einschaltroutine. Das heißt aber nicht, daß Sie, lieber Hobby-Programmierer, darauf verzichten müssen. Ich kann mir vorstellen, daß besonders Ausgefuchste unter Ihnen durch POKEn eines anderen Bitmusters in die Speicherzelle 0 vielseitige Befehle erzeugen und einsetzen können. Das wird besonders deutlich, wenn Sie jetzt sehen, mit welchen Teilen des Computers diese sechs Leitungen verbunden sind. Datenregister in Speicherzelle 1Mit diesem Register steuert der Mikroprozessor (und damit natürlich das Betriebssystem) die Auswahl von Speicherblöcken und den Betrieb mit dem Kassettenrecorder. Dem Programmierer steht diese Möglichkeit über POKEn auch zur Verfügung. Bit 0 schaltet den Speicherbereich 40960 bis 49151 ($A000 bis $BFFF) zwischen dem Basic-Übersetzer (Interpreter) im ROM und freiem RAM um (Normalzustand = 1). Bit 1 schaltet den Speicherbereich 57344 bis 65535 ($E000 bis $FFFF) zwischen dem Betriebssystem (Kernel) im ROM und freiem RAM um (Normalzustand = 1). Bit 2 schaltet den Speicherbereich 53248 bis 57343 ($D000 bis $DFFF) zwischen Zeichen-ROM und Ein-/Ausgabe-ROM um (Normalzustand = 1). Bit 3 sendet serielle Daten zum Kassettenrecorder (Normalzustand = 0). Bit 4 prüft, ob eine der Tasten des Recorders gedrückt ist, welche den Motor einschalten (Normalzustand = 1). Bit 5 schaltet den Motor des Recorders ein und aus (Normalzustand = 1). Die RAM-ROM-UmschaltungSie wissen, daß Ihr C 64 deswegen so heißt, weil er 64 KByte Speicherplätze hat. Nur stimmt das nicht! Er hat nämlich 88 KByte und müßte eigentlich C 88 heißen. Da mit den 16 Bit der High-/Low-Byte-Methode (siehe Texteinschub Nr. 2) nur 64 KByte adressierbar sind, müssen die restlichen 22 KByte bei Bedarf eingeschoben werden - und das machen die oben erwähnten Bit 0 bis 2 des Datenregisters. In Bild 1 sehen Sie die drei oben erwähnten Speicherblöcke, die sowohl mit RAM als auch mit ROM belegt sind, einer davon gleich doppelt. Ich habe ihnen folgende Namen gegeben:
Tabelle 2 gibt Ihnen die Übersicht über die gemeinsame Wirkung der Bit 0, 1 und 2 des Datenregisters auf den jeweiligen Inhalt der Speicherblöcke. Der Vollständigkeit halber muß ich hier noch erwähnen, daß neben den drei ersten Bits der Speicherzelle 1 noch zwei weitere Signale die RAM/ROM- Umschaltung beeinflussen. Es sind das die Leitungen auf Pin 8 und 9 des Erweiterungssteckers (GAME und EXROM), welche durch Spiel- und Programmodule benutzt werden. Eine genaue Beschreibung der dadurch erzeugten sinnvollen Speicherkombinationen finden Sie in dem Buch »64 Intern« von Data Becker ab Seite 14. Zwei Anwendungsbeispiele dieser Umschaltung finden Sie im Texteinschub Nr. 3 »Manipuliertes Basic«. Betrieb des KassettenrecordersBit 3, 4 und 5 regeln, wie schon gesagt, den Betrieb des Kassettenrecorders. Zu Bit 3 ist oben schon das Notwendige gesagt. Bit 4 ist im Normalzustand auf 1, »normal« heißt hier, solange keine der Motor- Tasten der Datasette (PLAY, REWIND, FAST FORWARD) gedrückt ist. Zur Probe:
funktioniert das alles nur, wenn - wie im »Normalfall« - das Bit 4 des Datenrichtungsregisters (Speicherzelle 0) auf 0 (Eingang) steht. Bit 5 schaltet den Motor der Datasette ein und aus. Es bietet sich an, damit per Programm die Datasette zu schalten - wenn so etwas nützlich ist. Leider ist dieses Bit etwas schwieriger zu handhaben, da es in der Interrupt-Routine des Betriebssystems eine Rolle spielt. Die Tasten der Datasette werden nämlich 60mal in der Sekunde abgefragt. Wenn keine Taste gedrückt ist, setzt das Betriebssystem sowohl das sogenannte »Interlock«-Register in Speicherzelle 192 auf 0 als auch Bit 5 der Zelle 1 auf 1, wodurch der Motor ausgeschaltet wird beziehungsweise bleibt. Da kann man nicht dagegen an. Wir haben nur eine Chance, wenn eine Taste bereits gedrückt ist und der Kassettenmotor schon läuft. Dann nämlich können wir zuerst das Interlock-Register mit einem Wert größer als 0 lahmlegen:
Jetzt läßt sich der Motor der Datasette mit Bit 5 steuern: POKE 1,39 beziehungsweise POKE 1,PEEK(1) OR 32 schaltet den Motor aus, POKE 1,7 beziehungsweise POKE 1,PEEK(1) AND 31 schaltet den Motor ein. Das Interlock-Register in Speicherzelle 192 werde ich später noch einmal erwähnen, da es seine Funktion auch beim VC 20 ausübt, allerdings mit anderen Ein-/Ausgangs-Ports. Das ist alles, was zur Speicherzelle 1 zu sagen ist. Ab Speicherzelle 3 bis zur Speicherzelle 672 gelten alleAngaben sowohl für den C 64 als auch für den VC 20, zumindest was die Bedeutung der Zellen betrifft. Ihr Inhalt kann entsprechend der verschiedenen Adressen der Betriebssysteme voneinander abweichen. Wie üblich werde ich natürlich jeweils darauf aufmerksam machen. |
ProzessorportIm Prozessorport kann man angeben, welche Speicherbereiche ein- oder ausgeschaltet werden. Bitbeschreibung:
Die Bits 6 und 7 sind unbenutzt und immer 0 |
Processor portBits:
Default: $37, %00110111. |
6510 data register | 6510 On-Chip 8-Bit Input/Output Register | 6510 On-chip 8-bit Input/Output Register. | Chip I/O; memory & tape control | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0002 | 2 | Unused | unbenutzt | unbenutzt | Unused | Unused | Unused. Free for user programs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0003-$0004 | ADRAY1 | 3-4 |
Vector: Routine to Convert a Number from Floating Point to Signed IntegerThis vector points to the address of the BASIC routine which converts a floating point number to an integer. In the current Kernal version, the address that it points to is 45482 ($B1AA). Disassembly of the ROMs indicates that BASIC does not use this vector. However, it may be of real assistance to the programmer who wishes to use data that is stored in floating point format. The parameter that is passed by the USR command is available only in that format, for example. Since it is extremely difficult to decipher and use a floating point number, the simplest way to deal with such data is to use the conversion routines that are built into BASIC to change it into a two-byte signed integer. This could be accomplished by jumping directly into the BASIC ROM, if you know the location of the routine. Therefore, if the address changes in future versions of the 64 or future Commodore computers, you won't have to modify your program to make it work with them. See the entry for the USR vector at 785 ($0311) for an explanation of how to use this routine in connection with the USR command. |
Vektor auf die Routine zur Umwandlung einer Gleitkommazahl in eine ganze Zahl mit VorzeichenIn diesen beiden Speicherzellen steht also ein Vektor. Was das ist, wird im Texteinschub Nr. 4 näher erläutert. Beim VC 20 deutet dieser Vektor auf die Adresse 63674 ($D1AA), beim C 64 auf 45482 ($B1AA). Sie können das mit
leicht nachprüfen. Ab diesen Adressen beginnt im Basic-Übersetzer (Interpreter) ein Programm, welches - natürlich in Maschinensprache - eine Gleitkommazahl in eine ganze Zahl umwandelt. Diejenigen Leser, die mit Gleitkommazahlen nicht so vertraut sind, möchte ich auf den Texteinschub Nr. 6 verweisen. Er ist nur eine kleine Einführung. Eine detaillierte Beschreibung finden Sie im Assemblerkurs (Teil 8) von Heimo Ponnath (Ausgabe 4/85) beziehungsweise im 64er-Sonderheft 8/85, ab Seite 42. Dieses Umwandlungsprogramm steht nicht nur den Maschinen, sondern auch den Basic-Programmierern zur Verfügung, allerdings nur über den USR-Befehl und da auch nur, wenn der »Floating Point Accumulator« #1 (FAC1) in den besagten Adressen 97 bis 102 mitbenutzt wird. Ich verschiebe daher alle weiteren Details auf unsere Ankunft bei diesen Speicherzellen. |
Vektor für Umwandlung von Fließkomma nach FestVon diesen Adressen aus beginnt der Interpreter, eine Gleitkommazahl in eine ganze Zahl umzuwandeln. Der Vektor deutet auf die Adresse $B1AA. |
Unused.Default: $B1AA, execution address of routine converting floating point to integer. |
Store here the addr of the routine to turn the FAC into a two byte signed integer in [Y,A] | Jump Vector: Convert Floating-Integer | Jump Vector: Convert FAC to Integer in (A/Y) ($B1AA). | Float-Fixed vector | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0005-$0006 | ADRAY2 | 5-6 |
Vector: Routine to Convert a Number from Integer to Floating PointThis vector points to the address of the BASIC routine which converts an integer to a floating point number. This routine is currently located at 45969 ($B391). BASIC does not appear to reference this location. It is available for use by the programmer who needs to make such a conversion for a machine language program that interacts with BASIC. For an explanation of how to use this routine in connection with the USR command, see the entry for the USR vector at 785 ($0311). |
Vektor auf die Routine zur Umwandlung einer ganzen Zahl in eine GleitkommazahlDieses Programm ist die Umkehrung der oberen Routine. Sie beginnt beim VC 20 ab Speicherzelle 54161 ($D391), beim C 64 ab 45969 ($B391). Da hier prinzipiell dasselbe gilt wie oben, möchte ich nur kurz den Vorteil beleuchten, den derartige Vektoren haben. Eigentlich könnten wir direkt auf die im Vektor enthaltenen Adressen springen - wenn wir sie kennen. Ein Sprung auf die Adresse des Vektors erlaubt uns jedoch immer die völlige Ignoranz seines Inhalts - und Commodore erlaubt die Änderung der Adressen im Basic-Übersetzer, wie es ja beim C 64 gegenüber dem VC 20 auch gemacht worden ist, ohne daß vorhandene Programme umgeschrieben werden müssen. |
Vektor für Umwandlung von Fest nach FließkommaDiese Routine verwandelt eine ganze Zahl in eine Fließkommazahl. Der Zeiger steht auf $B391. |
Unused.Default: $B391, execution address of routine converting integer to floating point. |
Store here the addr of the routine to convert [Y,A] to a floating point number in the FAC. | Jump Vector: Convert Integer--Floating | Jump Vector: Convert Integer in (A/Y) to Floating point in (FAC); ($B391). | Fixed-Float vector | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0007-$0008 | 7-8 | Temporary Integer during OR/AND. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0007 | CHARAC | 7 |
Search Character for Scanning BASIC Text InputThis location and the next are used heavily by the BASIC routines that scan the text that comes into the buffer at 512 ($0200), in order to detect significant characters such as quotes, comma, the colon which separates BASIC statements, and end-of-line. The ASCII values of such special characters are usually stored here. This location is also used as a work area by other BASIC routines that do not involve scanning text. |
Suchzeichen zur Prüfung von Texteingaben in BasicDiese Speicherzelle wird viel von denjenigen Basic-Routinen als Zwischenspeicher benutzt, die den direkt eingegebenen Text absuchen, um Steuerzeichen (Gänsefüße, Kommata, Doppelpunkte und die Zeilenbeendigung durch die RETURN-Taste) rechtzeitig zu erkennen. Normalerweise wird in der Zelle 7 der ASCII-Wert dieser Zeichen abgelegt. Die Speicherzelle 7 wird aber auch von anderen Basic-Routinen benutzt. Sie ist daher für den Programmierer praktisch nicht zu verwerten. |
SuchzeichenDie Speicherzelle $07 wird oft von BASIC-Programmen als Suchzeiger für Texteingaben verwendet. |
Byte being searched for during various operations. Current digit of number being input. |
A delimiting character. | Search Character | Search Character/Temporary Integer during INT. | Search character | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
INTEGR |
Low byte of first integer operand during AND and OR. Low byte of integer-format FAC during INT(). |
A one-byte integer from "QINT". | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0008 | ENDCHR | 8 |
Search Character for Statement Termination or QuoteLike location 7, this location is used as a work byte during the tokenization of a BASIC statement. Most of the time, its value is 0 or 34. |
Suchzeichen speziell für Befehlsende und GänsefüßeWie Speicherzelle 7 dient auch die Zelle 8 als Zwischenspeicher für Basic- Texteingabe und zwar während der Umwandlung von Basic-Befehlen in den vom Computer verwendeten Befehlscode (Tokens). Die Speicherzelle 8 ist in Basic nicht verwertbar. |
Hochkomma-FlagWährend der Umwandlung von BASIC-Befehlen in Tokens wird die Speicherzelle $08 als Zwischenspeicher für BASIC-Texteingaben verwendet. |
Byte being search for during various operations. Current byte of BASIC line during tokenization. High byte of first integer operand during AND and OR. |
The other delimiting character. | Flag: Scan for Quote at End of String | Flag: Scan for Quote at end of String. | Scan-quotes flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0009 | TRMPOS | 9 |
Column position of the Cursor before the Last TAB or SPCTRMPOS is used by TAB and SPC. The cursor column position prior to the TAB or SPC is moved here from 211 ($D3), and is used to calculate where the cursor ends up after one of these functions is invoked. Note that the value contained here shows the position of the cursor on a logical line. Since one logical line can be up to two physical lines long, the value stored here can range from 0 to 79. |
Spaltenposition des Cursors vor dem letzten TAB- oder SPC-BefehlSpeicherzelle 9 wird von den Basic-Befehlen TAB und SPC verwendet. Vor ihrer Ausführung wird die Nummer der Spalte, in der sich der Cursor befindet, aus der Speicherzelle 211 ($D3) nach 9 gebracht, von wo sie geholt wird, um die Position des Cursors nach der Ausführung von TAB und SPC auszurechnen. Diese komplizierte Erklärung können wir durch Ausprobieren deutlicher machen. Dazu PRINTen wir 16mal den Buchstaben X hintereinander (Semikolon!), allerdings mit SPC (2) jeweils um 2 Spalten versetzt.
Nach jedem X wird durch Zeile 30 die »alte« Cursor-Spaltenposition ausgedruckt und zwar in derselben Zeile, ausgelöst durch das Semikolon. Dadurch erhöht sich laufend die in Speicherzelle 9 stehende Positionsangabe des Cursors. Wir erhalten folgenden Ausdruck:
Sie können die Positionsnummer nachrechnen. Berücksichtigen Sie aber dabei, daß bei PRINT vor und nach jeder Zahl eine Stelle frei bleibt, die erste für das Vorzeichen, die zweite wegen des Abstandes. Wichtig ist außerdem, daß die maximal mögliche Spaltenzahl nicht die Bildschirmspaltenzahl, sondern die »logische« Spaltenzahl ist, also 88 beim VC 20 und 80 beim C 64. Wir können die Cursorposition in Adresse 9 auch abfragen und ein Programm damit steuern. Fügen Sie einfach in das obige Programm die folgende Zeile 35 ein:
Sobald Position 33 erreicht ist, bleibt das Programm stehen. |
Speicher für Spalte beim TAB-BefehlNach der Ausführung von TAB oder SPC wird die Cursorposition in der Speicherzelle 9 zwischengespeichert. |
Current column number during SPC() and TAB(). | Position of terminal carriage. | Screen Column From Last TAB | Screen Column for last TAB. | TAB column save | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$000A | VERCK | 10 |
Flag: LOAD or VERIFYBASIC uses one Kernal routine to perform either the LOAD or VERIFY function, depending on whether the Accumulator (.A) is set to 0 or 1 upon entry to the routine. BASIC sets the value of VERCK to 0 for a LOAD, or 1 for a VERIFY. Its contents are passed to the Kernal LOAD routine, which in turn stores it in location 147 ($93). |
Flagge für LOAD oder VERIFYIn Zelle 10 steht eine 0, wenn geladen wird und eine 1 bei einem VERIFY. Warum das so ist, will ich kurz erläutern: Die Basic-Routinen für LOAD beziehungsweise für VERIFY sind völlig identisch. Was das Betriebssystem hinterher daraus machen muß, ist natürlich unterschiedlich. Das Basic erspart sich eine doppelte Routine, zeigt aber mit der Flagge in Speicherzelle 10 den Unterschied an. Erwähnenswert ist noch, daß das Betriebssystem in einer Art Nationalismus seine eigene Flagge aufzieht: Den Unterschied zwischen LOAD und VERIFY speichert es seinerseits in Zelle 147 ($93) ab. Soweit ich es sehen kann, sind Inhalt und Bedeutung beider Speicherzellen völlig identisch. Ich habe für Sie zwar kein Kochrezept zur Anwendung der LOAD-VERIFY-Flagge in einem Programm vorrätig, möchte Sie aber trotzdem ein bißchen zum Spielen anregen. Um meine Erklärung nachzuvollziehen, tippen Sie bitte direkt LOAD ein. Den Ladevorgang brechen Sie mit der STOP-Taste ab und fragen dann den Inhalt der Zelle 10 ab mit
Wir erhalten eine 0. Wiederholen Sie bitte diesen Vorgang, aber mit VERIFY. Wir erhalten jetzt eine 1 - Quod erat demonstrandum. Wir können auch in die Zelle 10 hineinPOKEn. Die »Wachablösung« zwischen Basic und Betriebssystem unter Hissen der Flagge in Zelle 10 findet beim VC 20 in der Speicherzelle 57705, beim C 64 in 57708 statt. Bevor wir diese Maschinenroutine mit SYS 57705 (SYS 57708) starten, geben wir mit dem Inhalt der Speicherzelle 10 an, ob es ein LOAD oder ein VERIFY sein soll. Legen Sie ein Band mit Programm in die Datasette. Um ein LOAD zu erzeugen, geben wir direkt ein:
Entsprechend der Anweisung auf dem Bildschirm drücken Sie PLAY, und das Auffinden des ersten Programms wird mit LOAD gemeldet. Machen Sie das Ganze noch einmal, diesmal aber POKEn Sie bitte eine 1 in die Zelle 10. Jetzt meldet das Betriebssystem das Auffinden des Programms mit VERIFY. Wie gesagt, vielleicht fällt Ihnen eine Anwendung dafür ein. |
0= LOAD, 1= Verify, Flag des InterpretersWeil die Routine von LOAD und VERIFY identisch ist, wird ein Flag benötigt, um zu unterscheiden, ob ein LOAD oder ein VERIFY-Vorgang ausgeführt worden ist. |
LOAD/VERIFY switchValues:
|
Flag: 0 = Load, 1 = Verify | Flag: 0 = Load, 1 = Verify. | 0 = LOAD, 1 = VERIFY | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$000B | COUNT | 11 |
Index into the Text Input Buffer/Number of Array SubscriptsThe routines that convert the text in the input buffer at 512 ($0200) into lines of executable program tokes, and the routines that link these program lines together, use this location as an index into the input buffer area. When the job of converting text to tokens is finished, the value in this location is equal to the length of the tokenized line. The routines which build an array or locate an element in an array use this location to calculate the number of DIMensions called for and the amount of storage required for a newly created array, or the number of subscripts specified when referencing an array element. |
Flagge für den Eingabepuffer/Anzahl der Dimensionen von Zahlenfeldern (Arrays)Alle Buchstaben und Zeichen, die mit der Tastatur direkt eingetippt werden, kommen in einen Eingabe-Pufferspeicher. Er beginnt ab Speicherzelle 512 ($0200). Sobald die RETURN-Taste gedrückt wird, wandelt eine Routine des Basic-Übersetzers den Text in Codezahlen (Tokens) um. Diese Routine und eine andere, welche die Zeilen eines Programms aneinanderhängt, verwenden die Zelle 11 als Zwischenspeicher. Sobald die Textumwandlung beendet ist, steht in Zelle 11 eine Zahl, die die Länge der Token-Zeile angibt. Die Zelle 11 wird außerdem noch von den Basic-Routinen benutzt, die ein Feld (Array) aufbauen oder ein bestimmtes Element in einem Array suchen. Was ein Feld oder Array ist, finden Sie in den Commodore-Handbüchern gut beschrieben. Außerdem gehe ich bei der Behandlung der Speicherzellen 47 bis 50 näher darauf ein. Diese Routinen also verwenden die Speicherzelle 11, um die Anzahl der verlangten DIMensionen und den für ein neu aufgebautes Feld nötigen Speicherbedarf zu berechnen. |
Zeiger im Eingabepuffer, Anzahl der DimensionenDie Speicherzelle $0B wird dazu verwendet, die Anzahl der Dimensionen zu berechnen. Außerdem wird noch die Länge der Tokenzeile hier angegeben. |
Current token during tokenization. Length of BASIC line during insertion of line. AND/OR switch; $00 = AND; $FF = OR. Number of dimensions during array operations. |
A general counter. | Input Buffer Pointer / No. of Subscripts | Input Buffer Pointer/Number of Subscripts. | Input buffer pointer/# subscrpt | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$000C | DIMFLG | 12 |
Flags for the Routines That Locate or Build an ArrayThis location is used as a flag by the routines that build an array or reference an existing array. It is used to determine whether a variable is in an array, whether the array has already been DIMensioned, and whether a new array should assume the default dimensions. |
Flagge für Basic-Routinen, die ein Feld (Array) suchen beziehungsweise aufbauenDiese Speicherzelle wird von den Basic-Routinen als Zwischenspeicher benutzt, die feststellen, ob eine Variable ein Feld (Array) ist, ob das Feld bereits DIMensioniert worden ist, oder ob ein neues Feld die unDIMensionierte Zahl von 11 Elementen hat. |
Flag für DIMDiese Speicherzelle wird benutzt, um festzustellen, ob die Variable ein Array oder schon eine dimensionierte Variable ist. |
Switch for array operationsValues:
|
…In getting a pointer to a variable it is important to remember whether it is being done for "dim" or not. DIMFLG and VALTYP must be consecutive locations. |
Flag: Default Array DiMension | Flag: Default Array dimension. | Default DIM flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$000D | VALTYP | 13 |
Flag: Type of Data (String or Numeric)This flag is used internally to indicate whether data being operated upon is string or numeric. A value of 255 ($FF) in this location indicates string data, while a 0 indicates numeric data. This determination is made every time a variable is located or created. |
Flagge zur Bestimmung des Datentyps (Zeichenkette/String oder Zahl)Diese Flagge zeigt den Routinen des Basic-Übersetzers an, ob es sich bei den zur Verarbeitung anstehenden Daten um einen String oder um Zahlenwerte handelt. Zeigt die Flagge 255 ($FF), ist es ein String. Bei 0 handelt es sich um Zahlen. Diese Bestimmung erfolgt jedesmal, wenn eine Variable definiert oder gesucht wird. Diese Flagge kann leider nicht durch ein Basic-Programm abgefragt werden. |
Typflag $00= numerisch, $FF= StringDas Flag zeigt dem BASIC-Interpreter an, ob es sich um Zahlenwerte oder um einen String handelt. |
Current expression typeValues:
|
The type indicator.0=numeric 1=string. |
Data Type: $FF = String, $00 = Numeric | Data type Flag: $00 = Numeric, $FF = String. | Type : FF = string, 00 = numeric | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$000E | INTFLG | 14 |
Flat: Type of Numeric Data (Integer or Floating Point)If data which BASIC is using is determined to be numeric, it is further classified here as either a floating point number or as an integer. A 128 ($80) in this location identifies the number as an integer, and a 0 indicates a floating point number. |
Flagge zur Bestimmung des Zahlentyps (Ganze Zahl oder Gleitkommazahl)Sobald durch die Flagge in der vorherigen Zelle 13 eine Zahl signalisiert wird, steht hier die Zahl 128 ($80), wenn es sich um eine ganze Zahl handelt, während eine 0 die Zahl als Gleitkommazahl identifiziert. Damit wollen wir ein bißchen experimentieren. Zeile 10 definiert eine Gleitkommazahl, Zeile 20 druckt sie und die Flagge aus Zelle 14 aus.
Wir erhalten dieZahl 13.41 und als Flagge eine 0.
INT bildet die ganze Zahl von 13.41. Also müßte die Flagge in Zelle 14 auf 128 stehen. Weit gefehlt! Da intern auch die 13 als Gleitkommazahl berechnet wird, erhalten wir immer noch eine 0.
Erst die Definition der Variablen B als ganze Zahl (mit %) ergibt die Flagge 128.
Die Multiplikation einer ganzen Zahl mit der Ganzzahl-Variablen B% fällt in dieselbe Kategorie wie Zeile 30 oben, da die Verarbeitung als Gleitkommazahl erfolgt. Also erhalten wir zu Recht eine 0. Erst wenn D als ganze Zahl (Zeile 90) ausgewiesen wird, steht die Flagge wieder auf 128:
|
$80= Integer, $00= RealWenn eine Gleitkommazahl auftritt, steht in der Speicherzelle $00, bei einer ganzen Zahl eine $80. |
Current numerical expression typeBits:
|
Tells if integer. | Data Type: $80 = Integer, $00 = Floating | Data type Flag: $00 = Floating point, $80 = Integer. | Type : 80 = integer, 00 = floating point | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$000F | GARBFL | 15 |
Flag for LIST, Garbage Collection, and Program TokenizationThe LIST routine uses this byte as a flag to let it know when it has come to a character string in quotes. It will then print the string, rather than search it for BASIC keyword tokens. The garbage collection routine uses this location as a flag to indicate that garbage collection has already been tried before adding a new string. If there is still not enough memory, an OUT OF MEMORY message will result. This location is also used as a work byte for the process of converting a line of text in the BASIC input buffer (512, $0200) into a linked program line of BASIC keyword tokens. |
Flagge bei LIST, Garbage Collection und TextumwandlungDie Routine des LIST-Befehls muß unterscheiden zwischen Basic-Befehlen und normalem Text. Wenn eine Zeichenkette durch ein »Gänsefüßchen« identifiziert worden ist, wird die Flagge gesetzt, und der Text wird ausgedruckt. Unter »Garbage Collection« (Müllabfuhr) wird die Routine des Betriebssystems verstanden, welche zu bestimmten Anlässen im Variablenspeicher alle nicht mehr benötigten Strings entfernt, um Platz zu schaffen. Dabei wird eine Flagge in Zelle 15 gesetzt, die anzeigt, daß eine Müllabfuhr bereits stattgefunden hat. Wenn bei der Speicherung eines neuen Strings zu wenig Speicherplatz vorhanden ist, wird bei der Flagge nachgesehen, ob gerade vorher schon durch die Müllabfuhr (Garbage Collection) der Speicher entrümpelt worden ist. Falls das der Fall ist, wird OUT OF MEMORY angezeigt, falls nicht, wird eine Müllabfuhr durchgeführt. Schließlich wird Zelle 15 auch bei der Umwandlung von Basic-Befehlen in internen Codezahlen (Tokens) eingesetzt. |
Hochkommaflag bei LISTDurch diese Speicherzelle wird beim LIST-Befehl durch ein Hochkomma erkannt, ob eine Textkette folgt. Zusätzlich wird in dieser Speicherzelle markiert, ob eine Garbage Collection durchgeführt werden muß oder nicht. |
Garbage collection indicator during memory allocation for string variable; $00-$7F = There was no garbage collection yet; $80 = Garbage collection already took place. | Whether to do garbage collection. | Flag: DATA scan/LIST quote/Garbage Coll | Flag: DATA scan/List Quote/Garbage collection. | DATA scan/LIST quote/memry flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DORES |
Quotation mode switch during tokenization; Bit #6: 0 = Normal mode; 1 = Quotation mode. Quotation mode switch during LIST; $01 = Normal mode; $FE = Quotation mode. |
Whether can or can't crunch res'd words.Turned on when "data" being scanned by crunch so unquoted strings won't be crunched. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0010 | SUBFLG | 16 |
Flag: Subscript Reference to an Array or User-Defined Function Call (FN)This flag is used by the PTRGET routine which finds or creates a variable, at the time it checks whether the name of a variable is valid. If an opening parenthesis is found, this flag is set to indicate that the variable in question is either an array variable or a user-defined function. You should note that it is perfectly legal for a user-defined function (FN) to have the same name as a floating point variable. Moreover, it is also legal to redefine a function. Using a FN name in an already defined function results in the new definition of the function. |
Flagge zur Anzeige eines Variablen-Feldes oder einer selbstdefinierten FunktionIm Basic-Übersetzer gibt es eine Routine, die den Speicher absucht, ob es eine Variable mit bestimmten Namen bereits gibt. Wenn diese mit einer Klammer beginnt, wird die Flagge in Zelle 16 gesetzt, um anzuzeigen, daß es sich um eine Array-Variable oder um eine mit DEF FN selbstdefinierte Funktion handelt. |
Flag für FNHier wird angezeigt, ob es sich um eine Array-Variable oder um eine mit DEF FN definierte Variable handelt. |
Switch during fetch of variable nameValues:
|
Flag whether sub'd variable allowed."FOR" and user-defined function pointer fetching turn this on before calling "PTRGET" so arrays won't be detected. "STKINI" and "PTRGET" clear it. Also disallows integers there. |
Flag: Subscript Ref / User Function Call | Flag: Subscript reference/User Function call. | Subscript/FNx flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0011 | INPFLG | 17 |
Flag: Is Data Input to GET, READ or INPUT?Since the keywords GET, INPUT, and READ perform similar functions, BASIC executes some of the same instructions for all three. There are also many areas of difference, however, and this flag indicates which of the three keywords is currently being executed, so that BASIC will know whether or not to execute the instructions which relate to the areas in which the commands differ (152 ($98)=READ, 64 ($40)=GET, 0=INPUT). As a result, INPUT will show the ? prompt, will echo characters back to the screen, and will wait for a whole line of text ended by a carriage return. GET gives no prompt and accepts one character without waiting. The colon character and the comma are valid data for GET, but are treated as delimiters between data by INPUT and READ. As each command has its own error messages, this flag is used to determine the appropriate message to issue in case of an error. |
Flagge für INPUT, GET oder READDie Basic-Routinen für INPUT, GET und READ sind zum großen Teil identisch. Um Speicherplatz zu sparen, verwendet der Basic-Übersetzer die identischen Teile nur einmal. Um in die nichtidentischen Teile verzweigen zu können, wird in Zelle 17 angezeigt, um welchen der drei Befehle es sich gerade handelt. Die Flagge steht auf 0 für INPUT, auf 64 ($40) für GET und auf 152 ($98) für READ. Mit dem folgenden kleinen Programm können wir das leicht nachprüfen.
Zeile 10 und 20, 40 sowie 60 sind Anwendungen der drei zur Debatte stehenden Basic-Befehle. Nach der Durchführung jedes Befehls wird in den Zeilen 30, 50 und 70 die jeweilige Flagge ausgelesen. Nach RUN erhalten wir als Resultat der Zeile 20 die Zahl 152, als Resultat von Zeile 30 die INPUT-Aufforderung mit Fragezeichen. Geben Sie irgendeine Zahl und RETURN ein. Wir erhalten so die 0. Die GET-Schleife in Zeile 40 wartet auf einen Tastendruck, dann erhalten wir 64. |
$00= INPUT, $40= GET, $98= READDiese Speicherzelle gibt an, in welche Routine der BASIC-Interpreter verzweigen soll. |
GET/INPUT/READ switchValues:
|
Flags whether we are doing "INPUT" or "READ". | Flag: $00 = INPUT, $40 = GET, $98 = READ | Input Flag: $00 = INPUT, $40 = GET, $98 = READ. | 0 = INPUT; $40 = GET; $98 = READ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0012 | TANSGN | 18 |
Flag: Sign of the Result of the TAN or SIN FunctionThis location is used to determine whether the sign of the value returned by the functions SIN or TAN is positive or negative. |
Flagge für Vorzeichen bei SIN, COS und TANDie Routinen des Basic-Übersetzers (Interpreter), welche die drei trigonometrischen Funktionen SIN, COS und TAN berechnen, verwenden die Speicherzelle 18 zur Bestimmung des Vorzeichens. Zur Erinnerung: Die trigonometrischen Funktionen haben in den vier »Quadranten« des Kreises (0-90, 90-180, 180-270, 270-360 Grad) nicht unbedingt dieselben Vorzeichen. Die Vorzeichen ändern sich allerdings nur an den Grenzen der Quadranten, wie in Bild 2 zu sehen ist. Die Flagge in Zelle 18 gibt das Vorzeichen nicht direkt an, sondern auf Umwegen. Die Darstellung ist in der folgenden Tabelle zusammengefaßt. Dabei bedeutet »gleich«: 0-0-0-0 oder 255-255-255 »Wechsel«: 0-255-0-255 Da die Erklärung mit »gleich« beziehungsweise »Wechsel« nicht gerade einleuchtend ist, schlage ich vor, daß Sie sich das Ganze mit dem folgenden kleinen Programm selbst anschauen, welches für viele Werte des Winkels im Bogenmaß - und in kleinen Schritten - den Wert der Flagge, daneben den Winkel I und den Wert der Funktion mit Vorzeichen ausdruckt.
Diese etwas umständliche Art, den Wert von I auszudrucken, vermeidet Rundungsfehler und begrenzt den Ausdruck auf zwei Dezimalstellen. Wenn Sie die Winkelwerte von I in Graden ausgedruckt haben wollen, können Sie eine ändere Zeile 20 verwenden, welche die Umrechnungsformel vom Bogenmaß in Grade verwendet: Winkel in Grad = Winkel im Bogenmaß * 180/π
Statt SIN können Sie genauso gut COS und TAN einsetzen. In Bild 2 sind nicht nur die Kurven und die Bereiche der Vorzeichen, sondern auch die Winkelbereiche sowohl im Bogenmaß als auch in Graden dargestellt. |
Sign during SIN() and TAN()Values:
|
Used in determining sign of tangent. | Flag TAN sign / Comparison Result | Flag: TAN sign/Comparative result. | ATN sign/Comparison eval flag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DOMASK |
…Additionally, the string and numeric comparison routines use this location to indicate the outcome of the comparison. For a comparison of variable A to variable B, the value here will be 1 if A is greater than B, 2 if A equals B, and 4 if a is less than B. If more than one comparison operator was used to compare the two variables (e.g., >= or <=), the value here will be a combination of the above values. |
Flagge bei VergleichDie Speicherzelle 18 wird auch noch von anderen Routinen des Basic-Interpreters beansprucht und zwar von allen, die einen Vergleich wie <, >, >= und so weiter durchführen. Entsprechend der Art des Vergleichs steht dann in der Zelle 18 eine Ziffer von 0 bis 6. Das folgende Programm macht das deutlich.
Kurz zur Erklärung dieser Zeilen: In der FOR..NEXT-Schleife wird die Variable I mit der Konstanten A=2 verglichen. In den Zeilen 30 bis 90 werden alle möglichen Vergleichsoperatoren durchgeprüft. Jeder der zutrifft, druckt den Wert von I, den Wert der dann in Zelle 18 stehenden Flagge und schließlich den Vergleichsoperator aus. Aus dem Resultat dieses Programms läßt sich folgende Tabelle zusammenstellen:
Sie sehen, die Flagge für die kombinierten Vergleichsoperatoren entspricht der Summe ihrer Einzelwerte. Nur die Verknüpfung über OR nicht, denn die ergibt 0. |
Mask in use by relation operations. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0013 | CHANNL | 19 |
Current I/O Channel (CMD Logical File) NumberWhenever BASIC inputs or outputs data, it looks here to determine which I/O device is currently active for the purpose of prompting or output control. It uses location 184 ($B8) for purposes of deciding what device actually to put input from or output to. When the default input device (number 0, the keyboard) or output device (number 3, the display screen) is used, the value here will be a zero, and the format of prompting and output will be the standard screen output format. When another device is used, the logical file number (CMD channel number) will be placed here. This lets the system now that it may have to make some subtle changes in the way it performs the I/O operation. For example, if TAB is used with the PRINT command, cursor right characters are used if the device PRINTed to is the screen. Otherwise, spaces are output when the number here is other than zero (the assumption being that you can't tab a printer like you can the screen). Likewise, the ? prompt for INPUT is suppressed if the file number here is nonzero, as is the EXTRA IGNORED message, and input of a carriage return by itself is ignored, rather than being treated as a null string (""). Therefore, by OPENing the screen as a device, and issuing the CMD statement, you can force the suppression of the ? prompt, and the other effects above. CMD places the new output file number here, and calls the Kernal to open the device for output, leaving it LISTENing for output (such as the READY prompt, which is diverted to the new device). Many routines reset this location and UNLISTEN the device, defeating the CMD and once again sending the output to the screen. If an error message has to be displayed, for example, this location will be reset and the message will be displayed on the screen. GET, GET#, INPUT, INPUT#, and PRINT# all will reset this location after the I/O is completed, effectively redirecting output back to the screen. PRINT and LIST are the only I/O operations that will not undo the CMD. This location can also be used to fool BASIC into thinking that data it is reading from the tape is actually being entered into the keyboard in immediate mode. For a look at a technique that uses a different approach to accomplish the same thing for disk or tape users, see location 512 ($0200), the keyboard buffer. |
Flagge zur Kennzeichnung des laufenden Ein-/AusgabegerätesImmer dann, wenn von Basic Daten ein- oder ausgegeben werden, schaut die entsprechende Routine des Übersetzers in Zelle 19 nach, um welches Peripheriegerät es sich handelt. Zur Debatte stehen Tastatur, Datasette, RS232- User-Port, Bildschirm, Drucker und Floppy-Laufwerk. Die Flagge ihrerseits ist ausschlaggebend für die feinen Unterschiede, wie zum Beispiel das Fragezeichen, bei Eingabe von der Tastatur (INPUT) oder die Anweisung »Press Play on Tape« bei Eingabe von der Datasette. Beim Einschalten des Rechners setzt die Initialisierungsroutine des Betriebssystems, die beim VC 20 ab Adresse 58276 ($E3A4), beim C 64 ab 58303 ($E3BF) beginnt, die Flagge in Zelle 19auf 0. Die Null bedeutet Eingabe über Tastatur und Ausgabe über Bildschirm. Wenn Sie einen Disassembler haben, drucken Sie doch einmal das Assemblerlisting aus. Sie werden in Adresse 58324/58325 ($E3D4/$E3D5), beim C 64 in 58354/58355 ($E3F2/$E3F3) den Befehl finden, der eine Null nach Zelle 19 ($13) bringt. Immer dann, wenn ein Programm nicht Tastatur und Bildschirm, sondern eines der oben genannten anderen Peripheriegeräte anspricht (indem mit OPEN.... eine Datei = Logical File eröffnet wird), wird in Zelle 19 die Nummer der gerade bearbeiteten Datei eingetragen, mit den bereits beschriebenen Konsequenzen. Ich will hier nicht weiter darauf eingehen, da wir den Inhalt von Zelle 19 selbst nicht auslesen können. Er wird nämlich immer gleich wieder auf Null gesetzt. Wir können ihn aber durch POKE verändern. Durch POKE 19,1 gaukeln wir dem Rechner vor, daß Ein- und Ausgabe über »externe« Geräte läuft, selbst wenn nur die Tastatur und der Bildschirm betrieben werden. Wenn zum Beispiel der Rechner der Meinung ist, daß ein INPUT von der Datasette kommt, druckt er kein Fragezeichen aus; auch kein EXTRA IGNORED als Fehlermeldung bei zu zahlreicher Eingabe und das alleinige Drücken der RETURN- Taste ignoriert er auch, im Gegensatz zum »normalen« INPUT Probieren Sie es aus:
In diesem Normalfall erscheint nach RUN darunter die Aufforderung TEST? Eine Eingabe, zum Beispiel XX, erscheint mit einem Abstand daneben, und nach RETURN wird XX an den Anfang der nächsten Zeile gedruckt. Alle falschen Eingaben werden mit den üblichen Fehlermeldungen quittiert. Jetzt fügen wir ein:
Nach RUN erscheint wieder die Aufforderung TEST, aber ohne Fragezeichen. Die Eingabe XX wird ohne Abstand daneben gesetzt und nach RETURN mit einem Abstand in derselben Zeile weitergeschrieben. Das Drücken der RETURN-Taste setzt den Cursor nicht wie üblich in die nächste Zeile, sondern schiebt ihn in derselben Zeile weiter. Diesen zusätzlichen Effekt muß man beachten, da er sehr störend für den Verlauf eines Programms sein kann. Man kann ihn natürlich auch nutzbringend einsetzen, hat er doch die Eigenschaft eines automatischen »Cursor UP«. Eine pfiffige Anwendung dieser Art wurde von Brad Templeton für den PET erfunden und ist von Jim Butterfield für eine MERGE- Routine mit dem Namen »Magic Merge« veröffentlicht worden. Da diese Routine aber primär auf der Eigenschaft der Speicherzelle 153 basiert, werde ich sie dann erläutern, sobald wir bei der Zelle 153 angelangt sind. Zurück zur Flagge in Zelle 19. Umgekehrt können wir POKE 19,0 leider nicht nutzen, da die betroffenen Befehle GET, GET#, INPUT, INPUT# und PRINT # die Flagge sofort auf den richtigen Wert setzen. Nur PRINT und LIST tun das nicht, wie wir bei dem PRINT-Befehl oben ja gesehen haben. |
aktives I/O-Gerät $00= DirekteingabeDie Speicherzelle $13 wird als Zeiger für die Peripheriegeräte wie Tastatur, Datasette, RS232, User-Port, Bildschirm, Drucker und Floppy verwendet. |
Current I/O device number.Default: $00, keyboard for input and screen for output. |
Holds channel number. | Flag: INPUT Prompt | File number of current Input Device. | Current I/O prompt flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0014-$0015 | LINNUM | 20-21 |
Integer Line Number ValueThe target line number for GOTO, LIST, ON, and GOSUB is stored here in low- byte, high-byte integer format, as is the number of a BASIC line that is to be added or replaced. LIST saves the highest line number to list (or 65535 ($FFFF) if program is to be listed to the end) at this location. GOTO tests the target line number to see if it is greater than the line number currently being executed. If it is greater, GOTO starts its search for the target line at the current line number. If it is not greater, GOTO must search for the target line from the first line of the program. It is interesting to note that the test is of the most significant byte only. Therefore, INT(TARGETLINE/256) must be greater than INT(CURRENTLINE/256) in order for the search to start with the current line, instead of at the beginning of the program. PEEK, POKE, WAIT, and SYS use this location as a pointer to the address which is the subject of the command. |
Zeilennummer für LIST, GOTO, GOSUB und ON, Zeiger der Adresse bei PEEK, POKE, SYS und WAITIn diesen Speicherzellen wird die Zeilennummer der Sprungbefehle GOTO, ON..GOTO und GOSUB sowie die Zeilenangabe beim LIST-Befehl gespeichert. Da die Werte bis maximal 65535 gehen können, braucht der Computer 2 Byte zur High-/Low-Byte- Darstellung. Die GOTO-Routine (im VC 20 ab 51360 = $C8A0, im C 64 ab 43168 = $A8A0) vergleicht die Zahl in 20 und 21 mit der laufenden Zeilenzahl. Wenn sie kleiner ist, wird ab der ersten Zeile des Programms gesucht. Ist sie aber größer, dann beginnt die Suche ab der laufenden Zeilenzahl. Die Suche geht solange, bis die in 20 und 21 angegebene Zeilenzahl gefunden ist. Dann fährt das Programm mit dieser Zeile fort. LIST speichert in 20 und 21 die höchste auszulistende Zeilennummer ab, falls keine Angabe beim LISTen gegeben worden ist, den Wert 65535 ($FFFF). Die Befehle PEEK, POKE, SYS und WAIT verwenden diese Speicherzellen zur Angabe der Adressen, die dem Befehl immer folgen müssen. Leider können wir die Speicherzellen 20 und 21 mit Basic-Programmen nicht bearbeiten; ihr Inhalt wird immer gleich auf 20 zurückgesetzt. |
Integer-Adresse z.B. ZeilennummerIn dieser Speicherzelle werden die Zeilennummern von den Befehlen wie ON..GOTO, GOTO, GOSUB, ON..GOSUB und der Zeilenausgabe beim LIST-Befehl gespeichert. |
Line number during GOSUB, GOTO and RUN. Second line number during LIST. |
Location to store line number before BUF so that "BLTUC" can store it all away at once.A comma (preload or from ROM) used by input statement since the data pointer always starts on a comma or terminator. |
Temp: Integer Value | Temporary: Integer value. | Integer value | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
POKER | Memory address during PEEK, POKE, SYS and WAIT. |
Set up location used by POKE.Temporary for input and read code |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0016 | TEMPPT | 22 |
Pointer to the Next Available Space in the Temporary String StackThis location points to the next available slot in the temporary string descriptor stack located at 25-33 ($19-$21). Since that stack has room for three descriptors of three bytes each, this location will point to 25 ($19) if the stack is empty, to 28 ($1C) if there is one entry, to 31 ($1F) if there are two entries, and to 34 ($22) if the stack is full. If BASIC needs to add an entry to the temporary string descriptor stack, and this location holds a 34, indicating that the stack is full, the FORMULA TOO COMPLEX error message is issued. Otherwise, the entry is added, and three is added to this pointer. |
Zeiger auf den nächsten freien Speicherplatz im »Temporary String Descriptor Stack«Dieser Zeiger bezieht sich in seiner Wirkung auf die übernächsten Speicherzellen 25 bis 33 ($19 bis $21). Diese werden als Stapelspeicher (Stack) für Angaben über vorläufige Zeichenketten - auf englisch »Temporary String Descriptor« - verwendet. Die Speicherzelle 22 ($16) ihrerseits enthält einen Zeiger auf den jeweils nächsten verfügbaren Platz in diesem Speicher ab Zelle 25. Da er eine Kapazität von 3 * 3 Byte hat, zeigt der Zeiger auf die Zelle 25 ($19), wenn er leer ist. Bei einem Eintrag zeigt er auf 28 ($1C), bei zwei Einträgen auf 31 ($1F) und schließlich auf 34 ($22), wenn der Speicher voll ist. Eine Zeichenkette ist dann »vorläufig«, wenn sie noch nicht einer Stringvariablen zugeordnet worden ist, zum Beispiel »Mahlzeit« in dem Basic- Befehl
Beim Einschalten setzt das Betriebssystem mit der Einschaltroutine ab Adresse 58303 ($E3BF) im C 64, beim VC 20 ab 58276 ($E3A4) den Zeigerauf 25. Die Stringverwaltungsroutine ab 46215 ($B487) im C 64 beziehungsweise ab 54407 ($D487) im VC 20 fragt bei String-Eingaben die Flagge ab. Nach jeder Eintragung in den Speicher ab Zelle 25 wird der Zeiger um 3 weitergesetzt. Sie können die Leerflagge 25 mit
leicht nachprüfen. Die anderen Eintragungen können nicht nachgeprüft werden, weil sie sofort auf 25 zurückgesetzt werden. Wir können sie aber durch POKE beeinflussen; ob das sinnvoll ist, ist eine andere Frage.
Die Zahl 34 in Zelle 22 sagt dem Programm, daß der Speicher ab Zelle 25 voll ist. Wir bekommen statt der MAHLZEIT eine Fehlermeldung serviert. Mit einem POKE-Befehl, der als Argument die für den vorgesehenen Zweck ungültige Zahl 35 verwendet:
erreichen wir allerdings zwei interessante »Dreckeffekte«. Zum einen unterdrückt der Befehl die Ausgabe des READY, zum anderen aber bewirkt er, daß bei LIST ein Listing ohne Zeilennummern ausgedruckt wird, sowohl auf dem Bildschirm als auch mit dem Drucker. Das billigste editierfähige TextverarbeitungssystemDie Idee dazu habe ich von Mike Apsey’s Hinweis in »Commodore User« Juli 1984. Mit Zeilennummern versehen, läßt sich jeder beliebige Text schreiben, verbessern, verschieben, abspeichern, aber nicht RUNen!! Der POKE-Befehl von oben (POKE 22,35) gefolgt von einem CMD und LIST, druckt dann alles brav als reinen Text aus. Die maximale Zeilenlänge entspricht der Zeilenlänge des jeweiligen Computers. Probieren Sie es aus:
Jede Zeile wird mit der RETURN-Taste abgeschlossen. Damit auch alles gedruckt wird, muß - zumindest bei meinem Drucker (1526) - eine »Leerzeile« folgen (Zeile 60). Mit
wird der Text ohne Zeilennummern ausgedruckt. Sie können ihn vorher nach Belieben verändern. Wie gesagt, nur nicht mit RUN starten, denn das bringt unweigerlich eine Fehlermeldung. |
Zeiger auf StringstackDie Speicherzelle $16 zeigt auf den nächsten freien Speicherplatz im Stringstack. |
Pointer to next expression in string stackValues: $19; $1C; $1F; $22. Default: $19. |
Pointer at first free temp descriptor.Initialized to point to TEMPST. |
Pointer Temporary String | Pointer: Temporary String Stack. | Pointer : temporary strg stack | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0017-$0018 | LASTPT | 23-24 |
Zeiger auf die Adresse der letzten Zeichenkette im »Temporary String Stack«Der Inhalt dieser 2 Byte zeigt auf den zuletzt benutzten Speicherplatz Innerhalb der Adresse 22 bis 33. Das heißt, daß der Wert in 23 ($17) immer um 3 kleiner ist als der in 22 ($16), während der Wert in 24 ($18) eine Null ist. |
Zeiger auf zuletzt verwendeten StringDer Inhalt dieser beiden Bytes zeigt auf den zuletzt verwendeten Speicherplatz. |
Pointer to previous expression in string stack. | Pointer to last-used string temporary. | Last Temp String Address | Last temporary String Address. | Last temp string vector | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0019-$0021 | TEMPST | 25-33 |
Descriptor Stack for Temporary StringsThe temporary string descriptor stack contains information about temporary strings which hve not yet been assigned to a string variable. An examples of such a temporary string is the literal string "HELLO" in the statement PRINT "HELLO". Each three-byte descriptor in this stack contains the length of the string, and its starting and ending locations, expresses as displacements within the BASIC storage area. |
Stapelspeicher für Angaben über vorläufige ZeichenkettenDas ist also der Speicherbereich, von dem in den beiden vorigen Abschnitten dauernd die Rede war. Ich gebe zu, »Descriptor Stack for Temporary Strings« drückt die Sache präziser aus als der deutsche Text. Die Bedeutung eines »vorläufigen« Strings habe ich oben in der Beschreibung der Speicherzelle 22 erklärt. Was ein Stapelspeicher (Stack) ist, entnehmen Sie bitte dem Texteinschub 6. Jeder der 3 Byte langen Angaben im Stack von 22 bis 33 enthält die Länge sowie die Anfangs- und Endadressen eines vorläufigen Strings, ausgedruckt als Verschiebung im Basic-Speicherbereich. |
StringstackDie Angaben im Stringstack enthalten die Stringlänge sowie die Anfangs- und Endadressen des vorherigen Strings. |
String stack, temporary area for processing string expressions (9 bytes, 3 entries). | Storage for NUMTMP temp descriptors. | Stack for Temporary Strings | Stack for temporary Strings. | Stack for temporary strings | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0022-$0025 | INDEX | 34-37 |
Miscellaneous Temporary Pointers and Save AreaThis area is used by many BASIC routines to hold temporary pointers and calculation results. |
Verschiedene ZwischenspeicherDiese vier Speicherzellen werden vom Basic-Übersetzer (Interpreter) für verschiedene Zwischenergebnisse und Flaggen benutzt, die aber dem Programmierer nichts nutzen. |
Zeiger für diverse ZweckeDiese Speicherzellen benutzt der Interpreter, um verschiedene Zwischenergebnisse zu speichern. |
Temporary area for various operations (4 bytes). | Indexes. | Utility Pointer Area | Utility Pointer Area. | Utility pointer area | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0022-$0023 | INDEX1 | 34-35 | First Utility Pointer. | First Utility Pointer. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0024-$0025 | INDEX2 | 36-37 | Second Utility Pointer. | Secong Utility Pointer. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0026-$002A | RES | 38-42 |
Floating Point Multiplication Work AreaThis location is used by BASIC multiplication and division routines. It is also used by the routines which compute the size of the area required to store an array which is being created. |
Arbeitsspeicher für arithmetische OperationenDiese Speicherzellen werden von den Basic-Routinen bei der Multiplikation und Division als »Notizblatt« verwendet. Auch die Routinen, welche die erforderliche Speichergröße beim Definieren eines Zahlenfeldes (Array) ausrechnen, benutzen diesen Bereich. |
Register für Funktionsauswertung und ArithmetikDiese Speicherzellen werden vom BASIC-Interpreter auch zum Speichern von Zwischenergebnissen bei der Multiplikation und Division benutzt. |
Auxiliary arithmetical register for division and multiplication (4 bytes). | Floating-Point Product of Multiply | Floating point product of Multiply and Divide. | Product area for multiplication | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0026 | RESHO | 38 | Result of multiplier and divider. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0027 | RESMOH | 39 | One more byte. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0028 | RESMO | 40 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ADDEND | Temporary used by "UMULT". | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0029 | RESLO | 41 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$002B-$002C | TXTTAB | 43-44 |
Pointer to the Start of BASIC Program TextThis two-byte pointer lets BASIC know where program text is stored. Ordinarily, such text is located beginning at 2049 ($0801). Using this pointer, it is possible to change the program text area. Typical reasons for doing this include:
Such reconfiguring can be helpful in transferring programs from the 64 to the PET, or vice versa. Since the 64 automatically relocates BASIC program text, it can load and list PET programs even though the program file indicates a loading addresss that is different from the 64 start of BASIC. The PET does not have this automatic relocation feature, however, and it loads all BASIC programs at the two-byte address indicated at the beginning of the disk or tape file. So if the PET loads a 64 program at its normal starting address of 2049 ($0801), it will not recognize its presence because it expects a BASIC program to start at 1025 ($0401). Therefore, if you want to let a PET and 64 share a program, you must either reconfigure the 64 to start BASIC where the PET does, or reconfigure the PET to start BASIC where the 64 does (with a POKE 41,8:POKE 2048,0).
Since BASIC program text normally starts at 2048 ($0801), this means that you only have 6k for program text before your program runs over into screen memory. One way around this is by moving the start of basic to 16385 ($4001) by typing in direct entry mode:
Other uses might include setting aside a storage area for sprite shape data, or user-defined character sets.
This technique has a number of offshoots that are perhaps of more practical use. a) You can store two programs in memory simultaneously for the purpose of appending one to the other. This technique requires that the line numbers of the two programs do not overlap. (See Programming the PET/CBM by Raeto Collin West, pages 41-42, for a discussion of this technique). b) You can have two programs in memory at once and use the concept in (2) above to allow an easier way to create a safe area in low memory. The first program is just onw line that sets the start of BASIC pointer to the address of the second program which is located higher in memory, and then runs that second program. |
Zeiger auf den Anfang der Basic-Programme im SpeicherDieser Zeiger, in der Low-/High-Byte-Darstellung, gibt dem Basic-Übersetzer an, ab welcher Speicherzelle das Basic-Programm beginnt. Normalerweise ist diese Adresse fest vorgegeben. Beim C 64 zum Beispiel zeigt der Zeiger auf 2049 ($0801). Beim VC 20 ist die Lage schon schwieriger, denn der Speicherbeginn hängt davon ab, welche Speichererweiterung eingesetzt ist. Die folgende Tabelle 3 gibt darüber Auskunft. Tabelle 3: Beginn des Programmspeichers
Mit dem Befehl
läßt sich der jeweilige Beginn des Programmspeichers leicht feststellen. Mit einem POKE-Befehl kann der Programmierer diese Anfangsadresse verändern. Wozu das gut ist, fragen Sie? Anwendung #1:Nun, wenn Sie zum Beispiel ein Maschinenprogramm mit einem Basic-Programm gemeinsam betreiben wollen, brauchen Sie einen Speicherbereich für das Maschinenprogramm, der vom Basic-Programm nicht belegt wird. Wir sprechen vom »Schützen des Maschinenprogramms vor dem Überschreiben durch das Basic«. Der Speicherbereich eines Maschinenprogramms ist immer bekannt. Nach seinem letzten Speicherplatz kann das Basic-Programm beginnen. Die Verschiebung der Anfangsadresse erfolgt in vier Schritten:
Im folgenden kleinen Programm wird angenommen, daß der Speicher bis zur Adresse 6000 ($1388) durch ein Maschinenprogramm belegt ist. Das Basic-Programm kann daher ab 5002 ($138A) anfangen, denn in 5001 muß ja eine Null stehen. Die Adresse 5002 teilt sich auf in ein High-Byte von INT (5002/256) = 19 und ein Low-Byte von 5002-(19*256) = 138.
Der Effekt einer solchen »Verbiegung« des Zeigers in 43 und 44 wird im Texteinschub Nr. 7 »Der sichtbare Basic-Speicher« demonstriert. Neben der oben erwähnten Anwendung der Zeigerverbiegung gibt es noch andere Möglichkeiten: Anwendung #2:Christoph Sauer hat in seinem Kurs »Der gläserne VC 20« in Ausgabe 10/84 auf Seite 158 gezeigt, wie man mehrere Programme gleichzeitig im Speicher unterbringen und zwischen ihnen umschalten kann. Anwendung #3:Man kann zwei oder mehrere unabhängige Programme genau hintereinander in den Speicher bringen, um sie aneinander zu hängen, was dem im Commodore-Basic fehlenden Befehl MERGE entspricht. Dabei dürfen die Zeilennummern sich allerdings nicht überschneiden. Anwendung #4:Durch Hinaufschieben des Basic-Bereichs kann Platz geschaffen werden für selbstdefinierte Zeichen oder hochauflösende Grafik. Die Speicherzellen-Paare von 45, 46 bis 55, 56 ($37 bis $38) zeigen auf weitere für Basic-Programme wichtige Speicherbereiche, die deswegen gemeinsam betrachtet werden sollten. Bild 5 stellt den Zusammenhang grafisch dar. In diesem Bereich werden alle Variablen eines Programms gespeichert. Zur Erinnerung: Wir unterscheiden zwischen »normalen« Variablen (numerische und String- Variable) und Feld-Variablen (Arrays). Dabei ist wichtig zu wissen, daß ein Basic-Programm während des Eintippens oder Einladens von Disk beziehungsweise Kassette in den 1. Block kommt. Während des Programmlaufs werden alle normalen Variablen in den 2. Block geschrieben, alle Felder (Arrays) in den 3. Block und schließlich der Text der Zeichenketten (Strings) sozusagen rückwärts vom Ende des Arbeitsspeichers in den 4 . Block. Je nach Größe des Programms und nach Anzahl der Variablen wandern die Blockgrenzen nach oben beziehungsweise die von Block 4 nach unten. Wenn sie sich treffen beziehungsweise überschneiden, gibt es »OUT OF MEMORY«. Diese Blockbewegung ist in Bild 5 durch die Pfeile dargestellt. |
Zeiger auf BASIC-Programm AnfangDer Anfangsbereich des BASIC ist in Low- und Highbyte angegeben. Man kann durch die beiden Bytes den BASIC-Start abfragen oder verändern. |
Pointer to beginning of BASIC area.Default: $0801, 2049. |
Pointer to beginning of text.Doesn't change after being setup by "INIT". |
Pointer: Start of BASIC Text | Pointer: Start of BASIC Text Area ($0801). | Pointer : Start-of-Basic | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$002D-$002E | VARTAB | 45-46 |
Pointer to the Start of the BASIC Variable Storage AreaThis location points to the address which marks the end of the BASIC program text area, and the beginning of the variable storage area. All nonarray variables are stored here, as are string descriptors (for the address of the area where the actual text of strings is stored, see location 51 ($33)). Seven bytes of memory are allocated for each variable. The first two bytes are used for the variable name, which consists of the ASCII value of the first two letters of the variable name. If the variable name is a single letter, the second byte will contain a zero. The seventh bit of one or both of these bytes can be set (which would add 128 to the ASCII value of the letter). This indicates the variable type. If neither byte has the seventh bit set, the variable is the regular floating point type. If only the first byte has its seventh bit set, the variable is a string. If only the second byte has its seventh bit set, the variable is a defined function (FN). If both bytes have the seventh bit set, the variable is an integer. The use of the other five bytes depends on the type of variable. A floating point variable will use the five bytes to store the value of the variable in floating point format. An integer will have its value stored in the third and fourth bytes, high byte first, and the other three will be unused. A string variable will use the third byte for its length, and the fourth and fifth bytes for a pointer to the address of the string text, leaving the last two bytes unused. Note that the acrual string text that is pointed to is located either in the part of the BASIC program where the string is first assigned a value, or in the string text storage area pointed to by location 51 ($33). A function definition will use the third and fourth bytes for a pointer to the address in the BASIC program text where the function definition starts. It uses the fifth and sixth bytes for a pointer to the dependent variable (the X of FN A(X)). The final byte is not used. Knowing something about how variables are created can help your BASIC programming. For example, you can see that nonarray integer variables take up no less space than floating point variables, and since most BASIC commands convert the integers to floating point, they do not offer a speed advantage either, and in many cases will actually slow the program down. As will be seen below, however, integer arrays can save a considerable amount of space. Variables are stored in the order in which they are created. Likewise, when BASIC goes looking for a variable, it starts its search at the beginning of this area. If commonly used variables are defined at the end of the program, and are thus at the back of this area, it will take longer to find them. It may help program execution speed to define the variables that will be used most frequently right at the beginning of the program. Also, remember that once created, variables do not go away during program execution. Even if they are never used again, they still take up space in the variable storage area, and they slow down the routine that is used to search for variables that are referenced. Another point to consider about the order in which to define variables is that arrays are created in a separate area of memory which starts at the end of the nonarray variable area. Therefore, every time a nonarray variable is created, all of the arrays must be moved seven bytes higher in memory in order to make room for the new variable. Therefore, it may help performance to avoid defining nonarray variables after defining arrays. This pointer will be reset to one byte past the end of the BASIC program text whenever you execute the statements CLR, NEW, RUN, or LOAD. Adding or modifying a BASIC statement will have the same effect, because the higher numbered BASIC statements have to be moved up into memory to make room for the new statements, and can therefore overwrite the variable storage area. This means that if you wish to check the value of a variable after stopping a program, you can only do so before modifying the program. The exception to the above is when the LOAD command is issued from a program. The purpose of not resetting this pointer in such a case is to allow the chaining of programs by having one program load and then run the next (that is also why a LOAD issued from a program causes a RUN from the beginning of the program). This allows the second program to share variables with the first. There are problems with this, however. Some string variable descriptors and function definitions have their pointers set to areas within the program text. When this text is replaced by a load, these pointers are no longer valid, which will lead to errors if the FN or string value is referenced. And if the second program text area is larger than that of the first, the second program will overwrite some of the first program's variables, and their values will be lost. The ability to chain short programs is a holdover from the days of the 8K PET, for which this BASIC was written, but with the vastly increased memory of the 64, program chaining should not be necessary. You should also note that SAVE uses this pointer as the address of the byte after the last byte to SAVE. |
Zeiger auf die Anfangsadresse des Speicherbereichs für VariableDieser Zeiger, in der Low/High-Byte-Darstellung, gibt dem Basic-Interpreter an, ab welcher Speicherzelle die Variablen eines Basic-Programms gespeichert sind. Da die Variablen direkt an das Basic-Programm anschließen, zeigt dieser Zeiger natürlich gleichzeitig auf das Ende des Basic-Programms. Es muß betont werden, daß es sich nur um den Bereich der »normalen« Variablen handelt, also nicht um Felder (Arrays). Anders als der Zeiger in 43 und 44, der auf fest definierte Speicherzellen zeigt, liegt derZeiger für den Variablen- Beginn nicht fest. Je nach Länge des Programms wandert er nach oben. Sobald ein Programm eingetippt oder aus einem externen Speicher (Diskette, Kassette) eingelesen ist, wird der Zeiger in 45 und 46 durch RUN auf ein Byte hinter das Programmende gesetzt und alle Variablen werden in der Reihenfolge ihres Auftretens gespeichert. Da normalerweise die Länge eines Basic-Programms während des Ablaufs konstant bleibt, werden die Variablen in ihrer Position auch nicht gestört. Das bedeutet, daß sie sowohl vom Programm als auch vom Programmierer nach einer Unterbrechung abgefragt werden können. Nur wenn das Programm modifiziert wird, wandert der Zeiger zusammen mit den Variablen entsprechend weiter. Denselben Effekt wie das oben erwähnte RUN haben übrigens auch die Befehle NEW, CLR und LOAD. Eine Ausnahme bildet das LOAD innerhalb eines Programms, welches den Zeiger nicht zurücksetzt. Dadurch wird ein Aneinanderhängen von mehreren Programmen samt Variablen-Weiterverwendung unter bestimmten Voraussetzungen ermöglicht. Die Bearbeitung der Variablen durch das Basic-Programm und die daraus resultierenden Kochrezepte für den Programmierer sind im Texteinschub Nr. 8 »Normale Variable in BASIC« separat erläutert. Die verschiedenen Typen der Variablen und ihre Darstellung im Speicher finden Sie im 64’er, Ausgabe 10/84, Seite 157 und noch ausführlicher in Ausgabe 11/84, Seite 124, dargestellt und erklärt. Für diejenigen Leser, welche kein Monitor- beziehungsweise Disassembler- Programm haben oder benutzen können, ist im Texteinschub Nr. 9 »Darstellung der normalen Variablen im Speicher« eine kleine Anleitung gegeben, wie sie die Variablendarstellung mittels Basic anschauen können. |
Zeiger auf BASIC-ProgrammendeDieser Zeiger teilt dem Interpreter das BASIC-Ende mit, damit die Variablen hinter dem Programm abgelegt werden können. |
Pointer to beginning of variable area.(End of program plus 1.) |
Pointer to start of simple variable space.Updated whenever the size of the program changes, set to [TXTTAB] by "SCRATCH" ("NEW"). |
Pointer: Start of BASIC Variables | Pointer: Start of BASIC Variables. | Pointer : Start-of-Variables | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$002F-$0030 | ARYTAB | 47-48 |
Pointer to the Start of the BASIC Array Storage AreaThis location points to the address of the end of nonarray variable storage, and the beginning of array variable storage. The format for array storage is as follows: The first two bytes hold the array name. The format and high-bit patterns are the same as for nonarray variables (see 45 ($2D) above), except that there is no equivalent to the function definition. Next comes a two-byte offset to the start of the next array, low byte first. Then there is a one-byte value for the number of array dimensions (e.g., 2 for a two-dimensional array like A(x,y)). That byte is followed by pairs of bytes which hold the value of each array dimension+1 (DIMensioning an array always makes space for 0, so A(0) can be used). Finally come the values of the variables themselves. The format for these values is the same as with nonarray values, but each value only takes up the space required; that is, floating point variables use five bytes each, integers two bytes, and string descriptors three bytes each. Remember that as with nonarray string, the actual string text is stored elsewhere, in the area which starts at the location pointed to in 51-52 ($33-$34). |
Zeiger auf die Anfangsadresse des Speicherbereichs für Felder (Arrays)Dieser Zeiger, in der Low-/High-Byte-Darstellung, gibt dem Basic-Übersetzer (Interpreter) an, ab welcher Speicherzelle die Felder (Arrays) eines Basic- Programms gespeichert sind. Was Felder sind und wozu sie gebraucht werden, ist im Texteinschub Nr. 10 kurz erläutert. Da die Felder direkt nach den normalen Variablen gespeichert werden, zeigt dieser Zeiger natürlich gleichzeitig auf das Ende des Speichers für normale Variablen. Durch POKEn einer Adresse in die Speicherzellen 47 und 48 kann der Speicherbereich am Anfang eines Programms beinahe beliebig verschoben werden. Beinahe deswegen, weil die Verschiebung im Zusammenhang mit den anderen Bereichen (siehe Bild 5) einen Sinn haben muß. Im übrigen gilt für diesen Zeiger dasselbe, was schon für den Zeiger in 45 und 46 gesagt worden ist. Die Darstellung der Feld-Variablen selbst kann mit der Methode angesehen werden, die im Texteinschub Nr. 11 erklärt ist. Wie aus den Erklärungen hervorgeht, wird bei Feldern mit Zeichenketten (Strings) in dem von Zeiger 47 und 48 bezeichneten Speicherbereich nur die Definition beziehungsweise die Dimensionierung gespeichert. Die eigentlichen Zeichenketten stehen wie bei den normalen Variablen im vierten Block, vorn Speicherende rückwärts angeordnet. |
Zeiger auf Start der ArraysDas LOW- und HIGH-Byte der Adressen geben dem BASIC-Interpreter die Information, ab welcher Speicherzelle die Arrays eines BASIC-Programms gespeichert sind. |
Pointer to beginning of array variable area. |
Pointer to beginning of array table.Incremented by 6 whenever a new simple variable is found, and set to [VARTAB] by "CLEARC". |
Pointer: Start of BASIC Arrays | Pointer: Start of BASIC Arrays. | Pointer : Start-of-Arrays | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0031-$0032 | STREND | 49-50 |
Pointer to End of the BASIC Array Storage Area (+1), and the Start of Free RAMThis location points to the address of the end of BASIC array storage space and the start of free RAM. Since string text starts at the top of memory and builds downwards, this location can also be thought of as the last possible address of the string storage area. Defining new variables pushes this pointer upward, toward the last string text. If a string for which space is being allocated would cross over this boundary into the array storage area, garbage collection is performed, and if there still is not enough room, an OUT OF MEMORY error occurs. FRE performs garbage collection, and returns the difference between the addresses pointed to here and the address of the end of string text storage pointed to by location 51 ($33). |
Zeiger auf die Endadresse (+1) des Speicherbereichs für Felder (Arrays)Der Inhalt dieser Speicherzellen zeigt auf die Adresse, wo der Speicherbereich für Felder auf· hört. Wie aus Bild 5 hervorgeht, werden die Zeichenketten vorn Ende des verfügbaren RAM· Speichers rückwärts gespeichert. Man kann also auch sagen, daß der Zeiger in 49 und 50 die letzte mögliche Adresse für Zeichenketten angibt. Wenn in einem Programm neue Variablen definiert werden, rutscht diese Adresse weiter nach oben und nähert sich dem Ende der Zeichenketten, die durch den Zeiger in 51 und 52 angegeben wird. Wenn sich die Speicherbereiche der Felder und Zeichenketten berühren, bleibt der Computer stehen und führt die »Garbage Collection« (Müllabfuhr) durch - ein Prozeß, in dem nicht mehr gebrauchte Zeichenketten entfernt und der Zeichenketten-Speicher reduziert wird. Ist danach immer noch kein Platz, wird OUT OF MEMORY gegeben. Der Befehl FRE löst immer eine solche Garbage Collection aus und gibt dann die Differenz zwischen den Adressen in den Zeigern 49 und 50 und 51 und 52 als verbleibenden, noch verfügbaren, Speicherbereich aus. |
Zeiger auf Ende der DatenfelderDiese beiden Speicherzellen zeigen auf das Ende der Arrays. Zu beachten ist, daß die Zeichenketten rückwärts gespeichert werden. |
Pointer to end of array variable area. |
End of storage in use.Increased whenever a new array or simple variable is encountered. set to [VARTAB] by "CLEARC". |
Pointer End of BASIC Arrays (+1) | Pointer: End of BASIC Arrays + 1. | Pointer : End-of-Arrays | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0033-$0034 | FRETOP | 51-52 |
Pointer to the Bottom of the String Text Storage AreaThis pointer marks the current end of the string text area, and the top of free RAM (strings are built from the top of memory downward). Additional string texts are added, to the area below the address pointed to here. After they are added, this pointer is lowered to point below the newly added string text. The garbage collection routine (which is also called by FRE) readjusts this pointer upward. While the power-on/reset routines set this pointer to the top of RAM, the CLR command sets this pointer to the end of BASIC memory, as indicated in location 55 ($37). This allows the user to set aside an area of BASIC memory that will not be disturbed by the program, as detailed at location 55 ($37). |
Zeiger auf die untere Grenze des Speicherbereichs für den Text der Zeichenketten-VariablenDer Inhalt dieser Speicherzellen zeigt in Low-/High-Byte-Darstellung auf das jeweilige untere Ende (siehe Bild 5) des Textspeichers von Zeichenketten. Er bezeichnet aber zugleich auch das obere Ende des frei verfügbaren RAM-Bereichs. Das entsteht dadurch, daß der Text der Zeichenketten vom Ende des RAM-Bereichs nach unten gespeichert wird. In Bild 5 ist das durch den Pfeil dargestellt. Beim Einschalten des Computers und nach einem RESET wird dieser Zeiger auf das oberste Ende des RAM-Bereichs gesetzt. Beim C 64 ist das 40960 ($A000). Beim VC 20 hängt es von den eingesetzten Speichererweiterungen ab, ohne Erweiterung ist die Adresse 7680 ($1E00). Der Befehl CLR setzt den Zeiger auf die Adresse, welche durch den Zeiger in den Speicherzellen 55 und 56 als das Ende des Basic-Speichers angegeben wird. Wozu das dient, erkläre ich Ihnen bei der Beschreibung dieses Zeigers weiter unten. |
Zeiger auf StringgrenzeDer Inhalt dieser Speicherzellen zeigt auf das Ende des Textspeichers, der aber noch zugleich das obere Ende des frei verfügbaren RAM-Bereichs anzeigt. |
Pointer to beginning of string variable area.(Grows downwards from end of BASIC area.) |
Top of string free space. | Pointer: Bottom of String Storage | Pointer: Bottom of String space. | Pointer : String-storage(moving down) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0035-$0036 | FRESPC | 53-54 |
Temporary Pointer for StringsThis is used as a temporary pointer to the most current string added by the routines which build strings or move them in memory. |
Zeiger auf die Adresse der zuletzt eingegebenen ZeichenketteIn diesen Speicherplätzen steht die Adresse (im vierten Block, siehe Bild 5) der Zeichenkette, die als letzte von Routinen (Programme, Direkteingabe) zur String-Manipulation abgespeichert worden ist. Mit dem folgenden kleinen Programm können Sie das genau sehen:
Zeile 10 druckt uns zuerst (links) den Zeiger auf die zuletzt eingegebene Zeichenkette aus, Zeile 20 rechts daneben den Zeiger auf die untere Speichergrenze der Zeichenketten. Zeile 30 fordert zur Eingabe einer Zeichenkette auf. Wenn Sie bei frisch eingeschaltetem Computer das Programm starten, sehen Sie eine 0 (=vorher noch kein String eingeben) und daneben die Adresse dezimal 40960 (C 64) beziehungsweise dezimal 7680 (VC 20 ohne Erweiterung). Wenn Sie auf das Fragezeichen des INPUT hin zum Beispiel ein A eintippen, erhalten Sie links den vorigen Wert von rechts und rechts jetzt eine um 1 kleinere Zahl. Eine weitere Eingabe von zum Beispiel XXXXX schiebt die alte rechte Zahl nach links und die neue wird um die Anzahl der Zeichen, also 5, verringert. |
Hilfszeiger für StringsIn diesen Zellen wird die Adresse der Zeichenkette verzeichnet, die als letzte von Routinen zur Stringmanipulation abgespeichert worden ist. |
Pointer to memory allocated for current string variable. | Pointer to new string. | Utility String Pointer | Utility String Pointer. | Utility string pointer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0037-$0038 | MEMSIZ | 55-56 |
Pointer to the Highest Address Used by BASICThe power-on/reset routine tests each byte of RAM until it comes to the BASIC ROM, and sets this pointer to the adress of the highest byte of consecutive RAM found (40959, $9FFF). There are two circumstances under which this pointer may be changed after power-up to reflect an address lower than the actual top of consecutive RAM:
The CLR is necessary to insure that the string text will start below your safe area. You may wish to store machine language programs, sprites, or alternate character sets in such an area. For the latter two applications, however, keep in mind the 16K addressing range limitation of the VIC-II chip. If you do not assign the VIC-II to a bank other than the default memory bank of 0-16383 ($0-$3FFF), you must lower the top of memory below 16383 ($3FFF) if you wish your sprite or character data area to be within its addressing range.
Since the contents of these buffers will overwrite any variables at the top of memory, a CLR command is issued at the time device 2 is opened. Therefore, the RS-232 device should be opened before defining any variables, and before setting aside a safe area for machine language programs or other uses, as described above. |
Zeiger auf das Ende des für Basic-Programme verfügbaren SpeichersDieser Zeiger, in der Low-/High-Byte-Darstellung, gibt dem Basic-Übersetzer an, welches die höchste von Basic verwendbare Speicheradresse ist. Wie aus Bild 5 ersichtlich, ist diese Adresse zugleich der Anfang der als Variable abgespeicherten Zeichenkette (Strings). Normalerweise ist diese Adresse fest vorgegeben. Die folgende Tabelle 4 gibt darüber Auskunft: Tabelle 4: Ende des Programmspeichers
Beim Einschalten des Computers überprüft das Betriebssystem den gesamten RAM- Speicher, bis es zur ersten ROM-Speicherzelle kommt, setzt den Zeiger in 55 und 56 auf diese Adresse und druckt den bekannten Kopf mit der verfügbaren Speicherangabe auf den Bildschirm. Normalerweise wird dieser Zeiger nicht geändert. Es gibt aber zwei Gelegenheiten, bei denen eine Änderung dieses Zeigers sinnvoll beziehungsweise notwendig ist. Anwendung 1:Es kommt oft vor, daß der gesamte Speicher nicht ausschließlich für Basic benötigt wird, sondern daß ein freier Speicherbereich geschaffen wird, um zum Beispiel Maschinenprogramme, selbst definierte Zeichen oder hochaufgelöste Grafik unterzubringen, die aber nicht vom Basic-Programm überschrieben werden können. Bei der Besprechung der Zeiger in 43 und 44 haben wir das auch schon gemacht, allerdings durch »Hochschieben« des Speicheranfangs. Mit dem Zeiger in 55 und 56 erreichen wir denselben Effekt, diesmal durch »Herunterdrücken« des Speicherendes. Gegenüber den vier Schritten beim Hochschieben ist das Herunterdrücken einfacher. Mit dem Befehl:
schieben wir das Speicherende um 256 Byte nach unten, egal für welchen Computer und welche Speichererweiterung. Mit -2 verschiebt sich das Ende um 512, mit-4 um 1024 Byte (also 1 KByte) nach unten. Wenn Sie eine feinere Verschiebung als Vielfache von 256 benötigen, kommen Sie mit dem High-Byte in 56 allein nicht aus, sondern Sie müssen auch einen entsprechenden Wert in 55 hineinPOKEn. Der Befehl CLR ist notwendig, denn er setzt den Zeiger der Zellen 51 und 52 (siehe dort), das heißt das untere Ende des Speicherbereichs für Zeichenketten auf dieselbe Adresse wie Zeiger 55 und 56. Dadurch wird erzwungen, daß die Zeichenkette sozusagen als Ausgangslage unterhalb des heruntergedrückten Speicherendes abgelegt wird. Anwendung 2:Über den User-Port (Steckerleiste an der Rückseite, neben dem Datasetten- Anschluß) können VC 20 und C 64 mit anderen Geräten verbunden werden. Der Datentransfer über diese Verbindung - sie heißt RS232-Schnittstelle - muß allerdings programmiert werden. Diese RS232-Schnittstelle hat die Gerätenummer 2 (so wie der Drucker Nummer 4 und das Diskettengerät die Nummer 8 hat). Wenn nun ein Gerät Nummer 2 mit einem OPEN-Befehl angewählt wird, wird automatisch der Zeiger in 55 und 56 und der Zeiger in 643 um 512 Byte heruntergedrückt, um je einen Eingangs- und Ausgangspufferspeicher zu erzeugen. Da der Inhalt dieser Pufferspeicher alle Variable in diesen 512 Byte überschreiben würde, wird auch der CLR-Befehl automatisch gegeben. Es gilt daher als Vorschrift, daß bei RS232-Verbindungen zuerst der Datenkanal durch OPEN eröffnet werden muß, bevor Variable, Felder und Zeichenketten definiert werden. |
Zeiger auf BASIC-RAM-EndeDieser Zeiger gibt dem Interpreter an, welches die höchste von BASIC verwendbare Speicheradresse ist. |
Pointer to end of BASIC area.Default: $A000, 40960. |
Highest location in memory. | Pointer: Highest Address Used by BASIC | Pointer: Highest Address available to BASIC ($A000). | Pointer : Limit-of-memory | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0039-$003A | CURLIN | 57-58 |
Current BASIC Line NumberThis location contains the line number of the BASIC statement which is currently being executed, in LSB/MSB format. A value of 255 ($FF) in location 58 ($3A), which translates to a line number of 65280 or above (well over the 63999 limit for a program line), means that BASIC is currently in immediate mode, rather than RUN mode. BASIC keywords that are illegal in direct mode check 58 ($3A) to determine whether or not this is the current mode. When in RUN mode, this location is updated as each new BASIC line is fetched for execution. Therefore, a TRACE function could be added by diverting the vector at 776 ($0308), which points to the routine that executes the next token, to a user-written routine which prints the line number indicated by this location before jumping to the token execution routine. (LISTing the line itself would be somewhat harder, because LIST uses many Page 0 locations that would have to be preserved and restored afterwards.) This line number is used by BREAK and error messages to show where program execution stopped. The value here is copied to 59 ($3B) by STOP, END, and the stop-key BREAK, and copied back by CONT. |
Nummer der laufenden Basic-ProgrammzeileDiese Speicherzellen enthalten die Zeilennummer in Low-/High-Byte-Darstellung derjenigen Basic-Anweisung, welche gerade ausgeführt wird. Ein kurzes Programm macht das deutlich:
In jeder Zeile wird zuerst etwas gePRINTet, nämlich Text, Variable und ein Rechenresultat. Durch das Komma getrennt wird in der 2. Bildschirmhälfte (VC 20) beziehungsweise Bildschirmviertel (C 64) der Inhalt der Speicherzellen 57 und 58 ausgedruckt. Das Resultat zeigt in der Tat die jeweilige Zeilennummer an. Die Basic-Befehle GOTO, GOSUB-RETURN, FOR-NEXT, END, STOP, CONT und die Betätigung der STOP-Taste während eines Programmlaufes verwenden alle den Inhalt dieser Speicherzellen, um entweder zu der laufenden Zeile zurückzufinden oder um die Unterbrechung mit BREAK IN... anzuzeigen. Auch die meisten Fehlermeldungen verwenden diese Zellen. In vielen Basic-Erweiterungen und Programmierhilfen wird ein Befehl TRACE oder STEP angeboten, welcher ein schrittweises Abarbeiten eines Programms bei gleichzeitiger Anzeige der gerade aktiven Zeilennummer erlaubt. Dieses TRACE verwendet natürlich auch den Inhalt der Zellen 57 und 58. Schließlich sei noch erwähnt, daß im direkten Modus, also bei direkt eingetippten Aktionen des Computers ohne Programmzeilen, in der Zelle 58 immer die Zahl 255 steht. Diejenigen Basic-Befehle, welche im direkten Modus nicht erlaubt sind (INPUT, GET, DEF), prüfen in Zelle 58, ob sie im direkten Modus oder während eines Programmlaufes aufgetreten sind. |
augenblickliche BASIC-ZeilennummerIn diesen Speicherzellen wird die Zeilennummer verzeichnet, welche gerade ausgeführt wird. |
Current line #.Set to 0,255 for direct statements. |
Current BASIC Line Number | Current BASIC Line number. | Current Basic line number | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$003B-$003C | OLDLIN | 59-60 |
Previous BASIC Line NumberWhen program execution ends, the last line number executed is stored here, and restored to location 57 ($39) by CONT. |
Zeilennummer der letzten ProgrammunterbrechungImmer dann, wenn ein Programmablauf durch die Befehle END oder STOP oder aber mit der STOP-Taste abgebrochen wird, wird die Nummer der gerade ausgeführten Programmzeile nach 59 und 60 gebracht und bleibt dort solange, bis eine neue Unterbrechung erfolgt. Das läßt sich am besten mit der STOP-Taste und nachfolgendem CONT zeigen. Nehmen Sie bitte dazu das kleine Demo-Programm der Zellen 57 und 58 und ändern Sie alle PEEK-Adressen in 59 und 60 um. Fügen Sie außerdem noch eine Zeile 50 hinzu:
Den dadurch erzeugten kontinuierlichen Laufdes Programms bremsen Sie dann mit der STOP-Taste und lassen ihn danach mit CONT weiterlaufen. Auf der rechten Seite erscheint jetzt die Zeilennummer, bei der das Programm vorher unterbrochen worden ist. |
Current BASIC line number for CONT. |
Old line numberSet up by ^C,"STOP" or "END" in a program. |
Previous BASIC Line Number | Previous BASIC Line number. | Previous Basic line number | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$003D-$003E | OLDTXT | 61-62 |
Pointer to the Address of the Current BASIC StatementThis location contains the address (not the line number) of the text of the BASIC statement that is being executed. The value of TXTPTR (122, $7A), the pointer tot he address of the BASIC text character currently being scanned, is stored here each time a new BASIC line begins execution. END, STOP, and the STOP-key BREAK save the value of TXTPTR here, and CONT restores this value to TXTPTR. CONT will not continue if 62 ($3E) has been changed to a zero by a LOAD, a modification to the program text, or by error routines. |
Zeiger auf die Adresse, ab weicher der Text der laufenden Basic-Zeile gespeichert ist.Die Abarbeitung der einzelnen Basic-Zeilen während eines Programmlaufs wird von einem kleinen Maschinencode-Programm, welches in den Speicherzellen 115 bis 138 steht (wir kommen noch dahin), gesteuert. In den Zellen 122 und 123 enthält es die Adresse des letzten Bytes des gerade ausgeführten Basic-Befehls. Sobald eine neue Basic-Zeile verarbeitet wird, holt das Betriebssystem diese Adresse aus 122 und 123 und speichert sie in den hier zur Diskussion stehenden Speicherzellen 61 und 62 ab, wie üblich als Low-/High-Byte. Dasselbe geschieht bei jedem Befehl END, STOP, bei Fehlern mit dem Befehl INPUT und durch das Drücken der STOP-Taste. Der Befehl CONT hingegen schaut in 61 und 62 nach und bringt die darin befindliche Adresse zurück in die Speicherzellen 122 und 123 zur Fortsetzung des Programms. Wenn aber in Zelle 62 inzwischen eine 0 steht - und das geschieht bei einem LOAD-Befehl, durch Programm-Abbruch mit Fehlermeldung und durch Eingabe neuer Basic-Zeilen beziehungsweise deren Veränderungen mit abschließender RETURN-Taste - dann wird der CONT-Befehl nicht ausgeführt. Zur besseren Erklärung dieser in 61 und 62 als Zeiger stehenden Adresse einer Basic-Zeile möchte ich Sie an den Texteinschub Nr. 7 erinnern, in dem ich den Basic-Programmspeicher »sichtbar« gemacht habe, um die Wirkung der Verschiebung des Zeigers in den Zellen 43 und 44 zu demonstrieren. Wir nehmen dazu bitte noch einmal das kleine Demo-Programm für die Adressen 57 und 58 oben her und ersetzen die PEEK-Werte durch 61 und 62. Das Ausdrucken des Inhalts von 61 und 62 legen wir aber an den Anfang jeder Zeile. Das Programm sieht dann so aus:
Nach RUN erhalten wir jetzt auf der linken Seite Zahlen, die den jeweiligen Basic-Speicher angeben, ab dem diese Zeile gespeichert ist. Wenn Sie ab diesen Adressen mit der gerade erwähnten Methode aus Texteinschub Nr. 7 nachschauen, finden Sie genau die Zeilen des kleinen Demo-Programms wieder. Zur Anwendung dieses Zeigers kann ich wenig sagen. Ihn durch POKE zu verändern, geht in Basic nicht, weil das Betriebssystem die richtigen Werte immer neu eingibt. Man kann ihn allerdings abfragen, wenn man sich für die Speicheradressen der Basic-Zeilen interessiert. Die einzige Anwendung dafür kenne ich von S. Leemon, welche bei den Adressen 65 und 66 eingesetzt wird. |
Old text pointer.Points at statement to be exec'd next. |
Pointer: BASIC Statement for CONT | Pointer: BASIC Statement for CONT. | Pointer : Basic statement for CONT | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$003F-$0040 | DATLIN | 63-64 |
Current DATA Line NumberThis location holds the line number of the current DATA statement being READ. It should be noted that this information is not used to determine where the next DATA item is read from (that is the job of the pointer at 65-66 ($41-$42) below). But if an error concerning the DATA occurs, this number will be moved to 57 ($39), so that the error message will show that the error occurred in the line that contains the DATA statement, rather than in the line that contains the READ statement. |
Zellennummer eines gerade laufenden DATA-BefehlsDiese Speicherzellen enthalten die Nummer der Basic-Zeile, in der gerade ein DATA-Befehl mit READ gelesen wird. Sobald in einer DATA-Zeile ein Fehler gefunden wird, kommt diese Zeilennummer aus 63 und 64 in die Speicherzellen 57 und 58, um in der Fehlermeldung die fehlerhafte DATA-Zeile und nicht die laufende READ-Zeile anzuzeigen. Auf diese Weise werden Syntax-Fehler in einer DATA-Zeile angezeigt. Um andere Fehler, wie zum Beispiel ein fehlendes Komma zwischen zwei DATA-Angaben anzuzeigen, können die Speicherzellen 63 und 64 eingesetzt werden. In dem folgenden Programm wird in Zeile 20 geprüft, ob die DATA-Angaben größer als 255 sind. Da bei einem fehlenden Komma die beiden Zahlen als eine Zahl gelesen werden, wird dieser Fall erkannt und mit einem F versehen die Nummer der DATA-Zeile ausgedruckt, in der das Komma fehlt.
Sie können jetzt in den DATA-Zeilen Kommafehler einbauen, die vom Programm angezeigt werden. Ein anderer häufiger Fehler, nämlich ein Komma am Ende einer DATA-Zeile, kann damit leider nicht erkannt werden. Aber vielleicht fällt Ihnen eine Prüfformel dazu ein. |
augenblickliche Zeilennummer für DATADiese beiden Speicherzellen enthalten die Zeilennummer einer DATA-Zeile, die gerade vom READ-Befehl ausgelesen wird. |
BASIC line number of current DATA item for READ. | Data line # -- remember for errors. | Current DATA Line Number | Current DATA Line number. | Current DATA line number | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0041-$0042 | DATPTR | 65-66 |
Pointer to the Address of the Current DATA ItemThis location points to the address (not the line number) within the BASIC program text area where DATA is currently being READ. RESTORE sets this pointer back to the address indicated by the start of BASIC pointer at location 43 ($2B). The sample program below shows how the order in which DATA statements are READ can be changed using this pointer. The current address of the statement before the DATA statement is stored in a variable, and then used to change this pointer.
|
Zeiger auf die Adresse, ab der die laufende DATA-Angabe gespeichert istDiese Speicherzellen enthalten in der Low-/High-Byte-Darstellung die Adresse im Basic-Programmspeicher, ab welcher der READ-Befehl nach der nächsten DATA-Zeile sucht. Zu Beginn eines Programms steht in 65 und 66 als Adresse der Beginn des Basic- Speichers, also derselbe Wert wie in den Speicherzellen 43 und 44. Der Befehl RESTORE setzt den Zeiger immer auf diesen Anfangswert zurück. Ein Demo-Programm zeigt uns das an (die Kommata sind wichtig für das Format der Darstellung auf dem Bildschirm!):
Durch Verändern dieses Zeigers in 65 und 66 kann die Reihenfolge, mit der DATA- Angaben gelesen werden, verändert werden, allerdings nur zeilenweise. Wir brauchen dazu die oben beschriebenen Speicherzellen 61 und 62, deren jeweiligen Inhalt wir ja mit PEEK abfragen können. Wenn wir das vor jeder DATA- Zeile machen und diesen Wert einer Variablen zuweisen, haben wir die Adresse gespeichert, hinter welcher die DATA-Zeile kommt. Durch POKEn dieser Adressen in die Speicherzellen 65 und 66 vor einem READ-Befehl, wird diesem READ die nächste DATA-Zeile vorgegeben und wir können so die Reihenfolge der DATA-Zeilen ändern.
Mit den Zeilen 70 bis 90 werden für jede DATA-Zeile eigene READ-Anweisungen gegeben. Welche DATA-Zeile gelesen werden soll, wird durch die Variablen Ax und Bx (x=1,2,3) bestimmt, mit denen der Zeiger in 65 und 66 »verbogen« wird. Auf ein Detail will ich hier hinweisen: Die Adresse 61 und 62 darf nicht mit zwei Befehlen, sondern muß mit einem Befehl ausgelesen werden, da bei einem möglichen Page-Wechsel zwischen den zwei Befehlen der Zeiger nicht verbogen, sondern abgeknickt wird. Was passiert in der ersten Zeile des Demo-Programms?
Mit »A1=PEEK(61)« wird der Variablen A1 der Wert des Low-Bytes des Zeigers 61 und 62 zugewiesen. Dieser zeigt am Anfang einer Zeile auf das Null-Byte vor der Linkadresse (hier 2048), so daß A1 den Wert (2048 AND 255)=0 erhält. Mit »B1=PEEK(62)« wird der Variablen B1 der Wert des High-Bytes des Zeigers 61 und 62 zugewiesen. Dieser zeigt aber inzwischen auf das Trennzeichen (»:«) zwischen den beiden Befehlen (hier 2061), so daß B1 den Wert (INT(2061/256)) = 8 erhält. Als Zeiger auf das aktuelle DATA-Element erhalten wir die erwartete Adresse (A1 + B1 * 256) = 2048. Was aber, wenn Zeilenanfang und Trennzeichen nicht in derselben Page liegen? Dazu setzen Sie bitte den Basic-Anfang um eine Stelle zurück:
Die Zeiger auf den Zeilenanfang und das Trennzeichen werden dadurch ja ebenfalls verändert, so daß A1 jetzt den Wert (2047 AND 255)=255 und B1 den Wert (INT(2060/256))=8 erhält. Als Zeiger auf das aktuelle DATA-Element erhalten wir nun die völlig unbrauchbare Adresse (A1+B1 * 256)=2303. |
Zeiger für nächstes DATA-ElementHier ist die Adresse aufgeführt, ab welcher der READ-Befehl nach der nächsten DATA-Zeile sucht. |
Pointer to next DATA item for READ. |
Pointer to data.Initialized to point at the zero in front of [TXTTAB] by "RESTORE" which is called by "CLEARC". updated by execution of a "READ". |
Pointer: Current DATA Item Address | Pointer: Used by READ - current DATA Item Address. | Current DATA address | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0043-$0044 | INPPTR | 67-68 |
Pointer in the Source of GET, READ, or INPUT InformationREAD, INPUT and GET all use this as a pointer to the address of the source of incoming data, such as DATA statements, or the text input buffer at 512 ($0200). |
Zeiger auf die Adresse, aus welcher die Befehle INPUT, GET und READ die Zeichen/Zahlen holenINPUT und GET verlangen Angaben, die per Tastatur eingegeben werden. Tastatur- Eingaben im direkten Modus, also wenn kein Programm läuft, werden im Eingabe- Pufferspeicher des Editors (der Teil des Betriebssystems, welcher für die Zeilendarstellung auf dem Bildschirm verantwortlich ist) ab Speicherzelle 512 bis 600 zwischengespeichert. Der Zeiger in 67 und 68 zeigt auf die jeweilige Adresse in diesem Eingabe- Pufferspeicher. Bei READ ist 67 und 68 identisch mit 65 und 66. Der Inhalt dieser Speicherzellen kann mit PEEK ausgelesen werden. |
Zeiger auf Herkunft der EingabeDer Zeiger zeigt auf die jeweilige Adresse in diesem Eingabepufferspeicher. |
Pointer to input result during GET, INPUT and READ. | This remembers where input is coming from. | Vector: INPUT Routine | Pointer: Temporary storage of Pointer during INPUT Routine. | Input vector | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0045-$0046 | VARNAM | 69-70 |
Current BASIC Variable NameThe current variable name being searched for is stored here, in the same two- byte format as in the variable value storage area located at the address pointed to by 45 ($2D). See that location for an explanation of the format. |
Name der gerade aufgerufenen Basic-VariablenWenn beim Ablauf eines Programms eine Variable auftaucht, muß ihr derzeitiger Wert im Variablen-Speicher gesucht werden. Während dieses Suchvorgangs wird der Name der Variablen in 69 und 70 zwischengespeichert. Die Form der Zwischenspeicherung ist dieselbe 2-Byte-Darstellung wie im Variablenspeicher, beschrieben bei der Behandlung der Speicherzellen 45 und 46. |
VariablennameFalls während des Ablaufs eines Programms eine Variable auftaucht, wird deren Name hier zwischengespeichert. |
Name and type of current variableBits: |
Variable's name is stored here. | Current BASIC Variable Name | Name of Variable being sought in Variable Table. | Current variable name | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0047-$0048 | VARPNT | 71-72 |
Pointer to the Current BASIC Variable ValueThis location points to the address of the descriptor of the current BASIC variable (see location 45 ($2D) for the format of a variable descriptor). Specifically, it points to the byte just after the two-character variable name. During a FN call, this location does not point to the dependent variable (the A of FN A), so that a real variable of the same name will not have its value changed by the call. |
Zeiger auf die Adresse des Wertes der gerade aufgerufenen Basic-VariablenÄhnlich wie bei 69 und 70 wird hier während des Anrufes einer Variablen durch ein Programm ein Wert zwischengespeichert, diesmal aber nicht der Name der Variablen, sondern der 2-Byte-Wert, welcher direkt hinter dem Variablennamen steht. Nähere Einzelheiten sind im Text der Speicherzellen 45 und 46 beschrieben. Davon ausgenommen sind selbstdefinierte Funktionen. Wie im Texteinschub Nr. 12 »Darstellung der Variablen einer selbstdefinierten Funktion« gezeigt ist, erscheinen diese ebenfalls im Variablenspeicher in einer Darstellung, welche den normalen Variablen sehr ähnlich ist. Damit nun eine normale oder Feld-Variable denselben Namen haben kann wie eine Funktion, wird die oben genannte Zwischenspeicherung in 69 und 70 bei Funktionen unterdrückt. |
VariablenadresseIn diesen Speicherzellen wird der Zeiger auf den Variablenwert abgelegt. |
Pointer to value of current variable or FN function. | Pointer to variable in memory. | Pointer: Current BASIC Variable Data | Pointer: to value of (VARNAM) if Integer, to descriptor if String. | Current variable address | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0047 | FDECPT | 71 | Pointer into power of tens of "FOUT". | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0049-$004A | FORPNT | 73-74 |
Temporary Pointer to the Index Variable Used by FORThe address of the BASIC variable which is the subject of a FOR/NEXT loop is first stored here, but is then pushed onto the stack. That leaves this location free to be used as a work area by such statements as INPUT, GET, READ, LIST, WAIT, CLOSE, LOAD, SAVE, RETURN, and GOSUB. For a description of the stack entries made by FOR, see location 256 ($0100). |
Zwischenspeicher für Variable einer FOR-NEXT-Schleife und für diverse Basic- BefehleDie Adresse einer Schleifenvariablen wird zuerst hier gespeichert, bevor sie auf den Stapelspeicher ab Speicherzelle 256 ($0100) gebracht wird. Die Funktion und Arbeitsweise des Stapelspeichers werden wir bei diesen Adressen behandeln. Etliche Basic-Befehle, wie LIST, WAIT, GET, INPUT, OPEN, CLOSE und andere, verwenden die Speicherzellen 73 und 74 für Zwischenspeicherungen. Diese Adressen sind für den Basic-Programmierer daher nicht verwendbar. |
Zeiger auf VariablenelementDie Adresse einer Schleifenvariable wird zunächst hier gespeichert, bevor sie in den Stack gebracht wird. |
Pointer to value of current variable during LET. | A variable's pointer for "FOR" loops and "LET" statements. | Pointer: Index Variable for FOR/NEXT | Pointer: Index Variable for FOR/NEXT loop. | Variable pointer for FOR/NEXT | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0049 | ANDMSK | 73 |
Value of second parameter during WAIT. Logical number during CLOSE and CLOSE Device number of LOAD, SAVE and VERIFY. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
LSTPNT | Pntr to list string. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ANDMSK | The mask used by WAIT for ANDing. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004A | EORMSK | 74 |
Value of third parameter during WAIT. Device number during OPEN. |
The mask for EORing in wait. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004B-$0060 | 75-96 | Temp Pointer / Data Area | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004B-$004C | OPPTR | 75-76 |
Math Operator Table DisplacementThis location is used during the evaluation of mathematical expressions to hold the displacement of the current math operator in an operator table. It is also used as a save area for the pointer to the address of program text which is currently being read. |
Zwischenspeicher für Zeiger bei READ und mathematischen OperationenWährend der Auswertung eines mathematischen Ausdrucks durch die Routine FRMEVL des Basic-Übersetzers, wird der Platz des betroffenen mathematischen Operators in einer Tabelle, hier in 75 und 76, zwischengespeichert. Dieser Platz wird dabei als Abstand zum Beginn der Tabelle dargestellt. Außerdem verwendet der READ-Befehl diese Adressen als Zwischenspeicher für einen Programmzeiger. Die Speicherzeilen 75 und 76 sind in Basic nicht verwendbar. |
Pointer to current op's entry in "OPTAB". | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
VARTXT |
Zwischenspeicher für ProgrammzeigerDiese Speicherzellen dienen als Zwischenspeicher für mathematische Operationen. Außerdem werden die Speicherzellen auch noch vom READ-Befehl als Zwischenspeicher verwendet. |
Temporary area for saving original pointer to current BASIC instruction during GET, INPUT and READ. | Temporary storage for TXTPTR during READ, INPUT and GET. | Temporary storage for TXTPTR during READ, INPUT and GET. | Y-save; op-save; Basic pointer save | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004B | VARTXT | 75 | Pointer into list of variables. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004D | OPMASK | 77 |
Mask for Comparison OperationThe expression evaluation routine creates a mask here which lets it know whether the current comparieson operation is a less-than (1), equals (2), or greater-than (4) comparison. |
Hilfsspeicher für Vergleichs-OperationenDie bei 75 und 76 schon erwähnte Auswertungs-Routine FRMEVL erzeugt in der Speicherzelle 77 einen Wert, der angibt, ob es sich bei einer Vergleichsoperation um den Fall »kleiner als« (<), »gleich wie« (=) oder »größer als« (>) handelt. Diese Speicherzelle ist nur im Maschinencode erreichbar. |
Maske für VergleichsoperationenDieser Zeiger wird von mathematischen Routinen als Vergleichsoperator verwendet, daß heißt um festzustellen, ob ein Wert kleiner, gleich oder größer ist. |
Comparison operator indicatorBits:
|
Mask created by current operator. | Mask used during FRMEVL. | Mask used during FRMEVL. | Comparison symbol accumulator | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004E-$0053 | 78-83 | Misc work area, pointer, etc | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004E-$0052 | TEMPF3 | 78-82 | A third FAC temporary (4 bytes). | Temporary storage for FLPT value. | Temporary storage for FLPT value. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004E-$004F | DEFPNT | 78-79 |
Pointer to the Current FN DescriptorDuring function definition (DEF FN) this location is used as a pointer to the descriptor that is created. During function execution (FN) it points to the FN descriptor in which the evaluation results should be saved. |
Zeiger auf Adresse, ab welcher der Wert der Variablen einer selbstdefinierten Funktion gespeichert istBasic erlaubt es bekanntlich, mit dem Befehl DEF selbst erfundene Funktionen zu definieren, welche die Form FN gefolgt von einem Variablennamen haben, zum Beispiel
Im Texteinschub Nr. 12 »Darstellung von Variablen selbstdefinierter Funktionen« wird gezeigt beziehungsweise sichtbar gemacht, wie derartige Funktionen und ihre Variablen gespeichert werden. Während der Definition einer Funktion steht in 78 und 79 die Adresse, ab welcher die Funktion und der Wert ihrer Variablen gespeichert ist. Der Inhalt dieser Adressen ist identisch mit den Zeichen hinter dem Namen der Funktion (1. Gruppe im nebenstehenden Beispiel). Nach der Ausführung der Funktion steht in 78 und 79 allerdings die Adresse, ab weiche der Zahlenwert der Funktion selbst gespeichert ist. Er ist identisch mit den Zeichen der 2. Gruppe. Diesen Zusammenhang können Sie überprüfen, indem Sie im Programm des Texteinschubes folgende Zeilen hinzufügen:
Nach RUN erhalten Sie zwei Adressen, die Sie mit direkter Eingabe abfragen:
Sie werden sehen, daß der Inhalt der beiden Adressen genau den Werten der Zeichen 3 bis 7 der beiden Gruppen entspricht, allerdings im Bildschirmcode. |
Pointer to current FN function. | Pointer used in function definition. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$004E | GRBPNT | 78 | Another used in garbage collection. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0050-$0052 | DSCPNT | 80-82 |
Temporary Pointer to the Current String DescriptorThe string assignment and handling routines use the first two bytes as a temporary pointer to the current string descriptor, and the third to hold the value of the string length. |
Zeiger auf einen provisorischen Speicherplatz einer Zeichenkette, die gerade bearbeitet wirdDie Teilprogramme (von Programmierern »Routinen« genannt) des Basic-Übersetzers im ROM des Computers, welche Zeichenketten (Strings) behandeln, verwenden die ersten beiden Bytes dieser drei Speicherzellen, nämlich 80 und 81, um in Low-/ High-Byte-Darstellung diejenige Speicheradresse anzugeben, ab der die Zeichenkette im Programmspeicher zu finden ist. Das dritte Byte (82) enthält die Länge der Zeichenkette. Wegen der provisorischen Natur dieses Zeigers ist er für Basic-Programme nicht geeignet. |
Stringdescriptor | Pointer to current string variable during memory allocation. | Pointer to a string descriptor. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0053 | FOUR6 | 83 |
Constant for Garbage CollectionThe constant contained here lets the garbage collection routines know whether a three- or seven-byte string descriptor is being collected. |
Flagge für die Garbage CollectionIn dieser Speicherzelle steht während der sogenannten Garbage Collection (Müllabfuhr) eine Zahl, die angibt, ob die Variable der zur Überprüfung anstehenden Zeichenkette eine Länge von 3 oder 7 Byte hat. Der Vorgang der Garbage Collection ist von B. Schneider, 64’er-Ausgabe 1/85, ausführlich beschrieben worden. Angaben über die Bedeutung der Variablen einer Zeichenkette finden Sie in den Texteinschüben Nr. 9 und Nr. 11. |
Schrittweite für Garbage Collection |
Step size of garbage collectionValues: $03; $07. |
Variable constant used by garb collect. | Length of String Variable during Garbage collection. | Length of String Variable during Garbege collection. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0054-$0056 | JMPER | 84-86 |
Jump to Function InstructionThe first byte is the 6502 JMP instruction ($4C), followed by the address of the required function taken from the table at 41042 ($A052). |
Sprungbefehl auf die Adressen der Basic-FunktionenJede Basic-Funktion, wie zum Beispiel SGN, INT, ABS, USR und so weiter, wird durch ein spezielles Teilprogramm (Routine) des Basic-Übersetzers ausgeführt. Die Anfangsadresse jeder dieser Routinen sind in einer Tabelle im ROM fest eingespeichert. Im VC 20 steht diese Tabelle von 49234 bis 49279 ($C052 bis $C07F), im C 64 von 41042 bis 41087 ($A052 bis $A07F). In der Speicherzelle 84 steht der Sprungbefehl JMP in Maschinencode, dargestellt durch die Zahl 75 ($4C). In den beiden anderen Zellen 85 und 86 steht dann in Low-/High-Byte-Darstellung die jeweilige Adresse in der Tabelle, welche der vom Programm gerade gebrauchten Basic-Funktion entspricht. Dieser gesamte Befehl JMP plus Adresse entspricht in Basic der GOSUB-Zeilennummer. Ein Beispiel soll das verdeutlichen. Geben Sie direkt ein:
Wir erhalten
Die erste Zahl ist genauso wie oben beschrieben. Die beiden anderen Zahlen ergeben zusammen die Adresse 47117 ($B80D) beziehungsweise 55309 ($D80D). Wenn Sie ein Buch mit ROM-Listing haben, werden Sie unter dieser Adresse die Routine für die Funktion »PEEK« finden. Das ist natürlich nicht erstaunlich, haben wir doch gerade vorher als letzten Befehl genau diese Funktion eingegeben. Leider ist das auch die einzige Funktion, die ich Ihnen vorführen kann, denn zum Vorführen muß ich eben immer PEEKen, so daß beim besten Willen immer nur die oben angegebenen Zahlen erscheinen können. |
JMP ABS machine instruction, jump to current BASIC function. | Jump Vector used in Function Evaluation- JMP followed by Address ($4C,$LB,$MB). | Jump Vector used in Function Evaluation - JMP followed by Address ($4C,$LB,$MB). | Jump vector for functions | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0054 | 84 |
Konstante $4C JMP für FunktionenHier ist die Konstante für JMP ($4C) festgelegt. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0055-$0056 | 85-86 | Execution address of current BASIC function. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0055 | SIZE | 85 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0056 | OLDOV | 86 | The old overflow. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0057-$0060 | 87-96 |
BASIC Numeric Work AreaThis is a very busy work area, used by many routines. |
Arbeitsspeicher für diverse Arithmetik-Routinen des Basic-ÜbersetzersDiese zehn Speicherplätze werden von verschiedenen Teilprogrammen (Routinen), besonders bei arithmetischen Operationen, als Zwischenspeicher verschiedener Werte, Flaggen und Zeiger benutzt. |
Misc numeric work area | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0057-$005B | TEMPF1 | 87-91 |
Register für Arithmetik, Akku #3Die Register werden für die Zwischenspeicherung von Polynomauswertungen (TAN) benÖtigt. |
Arithmetic register #3 (5 bytes). | Temporary storage for FLPT value. | Temporary storage for FLPT value. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0058 | HIGHDS | 88 | Destination of highest element in BLT. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$005A | HIGHTR | 90 | Source of highest element to move. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$005C-$0060 | TEMPF2 | 92-96 |
Register für Arithmetik, Akku #4siehe oben |
Arithmetic register #4 (5 bytes). | Temporary storage for FLPT value. | Temporary storage for FLPT value. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$005D | LOWDS | 93 | Location of last byte transferred into. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$005F | LOWTR | 95 | Last thing to move in BLT. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0058 | ARYPNT | 88 | A pointer used in array building. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$005F | GRBTOP | 95 | A pointer used in garbage collection. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$005D | DECCNT | 93 | Number of places before decimal point. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$005E | TENEXP | 94 | Has a DPT been input? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$005F | DPTFLG | 95 | Base ten exponent. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0060 | EXPSGN | 96 | Sign of base ten exponent. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0061-$0066 | FAC | 97-102 |
Floating Point Accumulator #1The Floating Point Accumulator is central to the execution of any BASIC mathematical operation. It is used in the conversion of integers to floating point numbers, strings to floating point numbers, and vice versa. The results of most evaluations are stored in this location. The internal format of floating point numbers is not particularly easy to understand (or explain). Generally speaking, the number is broken into the normalized mantissa, which represents a number between 1 and 1.99999..., and an exponent value, which represents a power of 2. Multiplying the mantissa by 2 raised to the value of the exponent gives you the value of the floating point number. Fortunately, the BASIC interpreter contains many routines for the manipulation and conversion of floating point number, and these routines can be called by the user. See the entries for locations 3 and 5 Floating Point Accumulator #1 can be further divided into the following locations: |
Gleitkomma-Akkumulator Nr.1»Akkumulator« heißt seit der Zeit der mechanischen Rechenmaschinen eine Speicherzelle, welche bei Rechenoperationen dadurch im Mittelpunkt steht, daß laufend Daten in sie hineingeschrieben beziehungsweise aus ihr herausgelesen werden. Normalerweise trägt diesen Namen das zentrale Rechenregister des Mikroprozessors. Leser des Assembler-Kurses kennen diesen Akkumulator inzwischen zur Genüge. Die Speicherzellen 97 bis 102 werden deswegen ebenfalls Akkumulator genannt, weil sie bei der Verarbeitung von Gleitkommazahlen eine ähnliche zentrale Rolle spielen. Zelle 97 enthält den Exponenten. Die Zellen 98 bis 101 enthalten die Mantisse. Zelle 102 enthält das Vorzeichen der Gleitkommazahl. Eine 0 bedeutet ein positives, die Zahl 255 ein negatives Vorzeichen. Mit dem Gleitkomma-Akkumulator Nr. 1 sind zwei weitere Speicherzellen eng verbunden, nämlich 104 ($68) und 112 ($70). Ganz zum Schluß ist noch erwähnenswert, daß nach der Umwandlung einer Gleitkommazahl in eine ganze Zahl diese als Low-/High-Byte in den beiden Speicherzellen 98 und 99 steht, was für Maschinenprogramme vielleicht recht nützlich sein kann. |
Fließkommaakku #1, FACDiese Register werden für die Berechnung von Fließkommazahlen verwendet. |
FAC, arithmetic register #1 (5 bytes). | The floating accumulator | Main Floating point Accumulator. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0061 | FACEXP | 97 |
Floating Point Accumulator #1: ExponentThis exponent represents the closest power of two to the number, with 129 added to take care of the sign problem for negative exponents. An exponent of 128 is used for the value 0; an exponent of 129 represents 2 to the 0 power, or 1; an exponent of 130 represents 2 to the first power, or 2; 131 is 2 squared, or 4; 132 is 2 cubed, or 8; and so on. |
Floating-Point Accumulator #1: Exponent | FAC Exponent. | Accum#l : Exponent | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DSCTMP | This is where temp descs are built. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0062-$0065 | FACHO | 98-101 |
Floating Point Accumulator #1: MantissaThe most significant digit can be assumed to be a 1 (remember that the range of the mantissa is from 1 to 1.99999...) when a floating point number is stored to a variable. The first bit is used for the sign of the number, and the other 31 bits of the four-byte mantissa hold the other significant digits. The first two bytes (98-99, $62-$63) of this location will hold the signed integer result of a floating point to integer conversion, in high-byte, low- byte order. |
Floating Accum. #1: Mantissa | FAC Mantissa. | Accum#l : Mantissa | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0062 | FACHO | 98 | Most significant byte of mantissa. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0063 | FACMOH | 99 | One more. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0064 | FACMO | 100 | Middle order of mantissa. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
INDICE | Indice is set up here by "QINT". | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0065 | FACLO | 101 | Least sig byte of mantissa. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0066 | FACSGN | 102 |
Floating Point Accumulator #1: SignA value of 0 here indicates a positive number, while a value of 255 ($FF) indicates a negative number. |
Vorzeichen von FACDer Zeiger gibt an, ob der Wert, der im FAC steht, positiv oder negativ ist. |
Sign of FACBits:
|
Sign of FAC (0 or -1) when unpacked. | Floating Accum. #1: Sign | FAC Sign. | Accum#l : Sign | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0067 | SGNFLG | 103 |
Number of Terms in a Series EvaluationThis location is used by mathematical formula evaluation routines. It indicates the number of separate evaluations that must be done to resolve a complex expression down to a single term. |
Zwischenspeicher beziehungsweise ZählregisterDiese Adresse wird von zwei Routinen verwendet. Der Basic-Übersetzer benutzt sie als Vorzeichenspeicher bei der Umwandlung von Zahlen aus dem ASCII-Format in Gleitkommazahlen. Das Betriebssystem verwendet diese Adresse als Zähler der Abarbeitungsschritte bei der Berechnung eines Polynoms der Form y=a0+a1x+a2x^2+a3*x^3+... |
Zähler für PolynomauswertungDiese Speicherzelle dient als Zähler für die Polynomauswertung. |
Number of degrees during polynomial evaluation. | Sign of FAC is preserved bere by "FIN". | Pointer: Series Evaluation Constant | Pointer: Series Evaluation Constant. | Series evaluation constant pointer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DEGREE | A count used by polynomials. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0068 | BITS | 104 |
Floating Point Accumulator #1: Overflow DigitThis location contains the overflow byte. The overflow byte is used in an intermediate step of conversion from an integer or text string to a floating point number. |
Überlauf-Speicher des Gleitkomma-Akkumulators Nr. 1Wenn eine Zahl so groß wird, daß sie mit den zur Verfügung stehenden Stellen nicht mehr dargestellt werden kann, sprechen wir von einem »Überlauf«. Bei Gleitkommazahlen liegt diese Überlaufgrenze bei 1,70141183 * 10^38. Während einer mathematischen Berechnung kann es intern im Computer vorkommen, daß ein Überlauf eintritt, der aber am Ende der Operation wieder verschwinden würde. Der Akkumulator Nr. 1 benutzt in einem derartigen Fall die Speicherzelle 104, um die verfügbare Stellenzahl um 8 Bit zu vergrößern. Für endgültige Resultate steht diese Erweiterung natürlich nicht zur Verfügung. Dieser Vorgang tritt besonders häufig bei der Umwandlung von ganzen Zahlen oder Zeichenketten in Gleitkommazahlen auf. |
Rundungsbyte für FACHier wird angegeben, ob der Wert, der im FAC steht, auf- oder abgerundet werden soll. |
Temporary area for various operations. | Something for "SHIFTR" to use. | Floating Accum. #1: Overflow Digit | Bit Overflow Area during normalisation Routine. | Accum#l hi-order (over flow) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0069-$006E | ARG | 105-110 |
Floating Point Accumulator #2A second Floating Point Accumulator, used in conjunction with Floating Point Accumulator #1 in the evaluation of products, sums, differences--in short, any operation requiring more than one value. The format of this accumulator is the same as FAC1. |
Gleitkomma-Akkumulator Nr. 2Spätestens jetzt verstehen Sie, warum der Akkumulator der Speicherzellen 97 bis 102 die Nr. 1 hat. Es gibt hier noch einen zweiten Gleitkomma-Akkumulator, der ein identischer Zwilling ist. Zwei Akkumulatoren sind immer dann notwendig, wenn mathematische Operationen ablaufen, welche mehr als einen Operanden verarbeiten, wie zum Beispiel Multiplikation, Division und so weiter. Aufgrund der Identität der beiden Akkumulatoren kann ich mir eine weitere Beschreibung ersparen. |
Fließkommaakku#2, ARGDiese Register werden für die Berechnung von Fließkommazahlen verwendet. |
ARG, arithmetic register #2 (5 bytes). | The floating argument (unpacked) | Auxiliary Floating point Accumulator. | Accum#2 : Exponent, etc. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0069 | ARGEXP | 105 | Floating Point Accumulator #2: Exponent | Floating-Point Accumulator #2: Exponent | AFAC Exponent. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006A-$006D | 106-109 | Floating Point Accumulator #2: Mantissa | Floating Accum. #2: Mantissa | AFAC Mantissa. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006A | ARGHO | 106 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006B | ARGMOH | 107 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006C | ARGMO | 108 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006D | ARGLO | 109 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006E | ARGSGN | 110 | Floating Point Accumulator #2: Sign |
Vorzeichen von ARGHier wird angegeben, ob der Wert, der im ARG steht, positiv oder negativ ist. |
Sign of ARGBits:
|
Floating Accum. #2: Sign | AFAC Sign. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006F-$0070 | STRNG1 | 111-112 | Pointer to first string expression during string comparison. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006F | ARISGN | 111 |
Result of a Signed Comparison of Accumulator #1 to Accumulator #2Used to indicate whether the two Floating Point Accumulators have like or unlike signs. A 0 indicates like signs, a 255 ($FF) indicates unlike signs. |
Flagge für Vorzeichenvergleich der Gleitkomma-Akkumulatoren Nr. 1 und Nr. 2Wenn die Zahl in beiden Akkumulatoren gleiche Vorzeichen hat, steht in Speicherzelle 111 eine 0, bei verschiedenen Vorzeichen eine 255. |
Vergleichsbyte der Vorzeichen von FAC und ARGDiese Speicherzelle gibt dem Interpreter an, ob die Vorzeichen der beiden Akkus übereinstimmen. |
A sign reflecting the result. | Sign Comparison Result: Accum. # 1 vs #2 | Sign of result of Arithmetic Evaluation. | Sign comparison, Acc#l vs #2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$006F-$0070 | STRNG1 | 111-112 | Pointer to a string or descriptor. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0070 | FACOV | 112 |
Low Order Mantissa Byte of Floating Point Accumulator #1 (For Rounding)If the mantissa of the floating point number has more significant figures than can be held in four bytes, the least significant figures are placed here. They are used to extend the accuracy of intermediate mathematical operations and to round to the final figure. |
Rundungsspeicher des Gleitkomma-Akkumulators Nr. 1Es kann vorkommen, daß die Mantisse einer Gleitkommazahl mehr Stellen hat, als mit den vier Mantissen-Bytes des Akkumulators Nr. 1 (Zelle 97 bis 102) dargestellt werden können. In diesem Fall werden die hintersten, das heißt die unwichtigsten Stellen hinter dem Komma in der Zelle 112 abgelegt. Von dort werden sie geholt, um die Genauigkeit von mathematischen Operationen zu erhöhen und auch um Endresultate abrunden zu können. |
FAC-Rundungsbyte | Overflow byte of the FAC. | Floating Accum. #1. Low-Order (Rounding) | FAC low-order rounding. | Accum#l lo-order (rounding) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0071-$0072 | FBUFPT | 113-114 |
Series Evaluation PointerThis location points to the address of a temporary table of values built in the free RAM area for the evaluation of formulas. It is also used for such various purposes as a TI$ work area, string setup pointer, and work space for the evaluation of the size of an array. Although this is labeled a pointer to the tape buffer in the Programmer's Reference Guide, disassembly of the BASIC ROM reveals no reference to this location for that purpose (see 178 ($B2) for pointer to tape buffer). |
Zwischenspeicher für verschiedene RoutinenDiese Speicherzellen werden von sehr vielen Routinen des Übersetzers und des Betriebssystems, wie zum Beispiel Zeichenkettenverarbeitung, interne Uhr (TI$), Bestimmung der Größe von Feldern (Arrays) und etlichen anderen verwendet. |
Zeiger für PolynomauswertungHier ist in LOW- und HIGH-Byte angegeben, was ausgewertet werden sol 1. |
Pointer into FBUFFR used by FOUT. | Pointer: Cassette Buffer | Pointer: Used during CRUNCH/ASCII conversion. | Cassette buff len/Series pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
STRNG2 | Temporary area for saving original pointer to current BASIC instruction during VAL(). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
POLYPT | Pointer to current item of polynomial table during polynomial evaluation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CURTOL | Auxiliary pointer during array operations. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BUFPTR | Pointer to buf used by "CRUNCH". | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
STRNG2 | Pointer to string or desc. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
POLYPT | Pointer into polynomial coefficients. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CURTOL | Absolute linear index is formed here. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0073-$008A | CHRGET | 115-138 |
Subroutine: Get Next BASIC Text CharacterThis is actually a machine language subroutine, which at the time of a BASIC cold start (such as when the power is turned on) is copied from MOVCHG (58274, $E3A2) in the ROM to this zero page location. CHRGET is a crucial routine which BASIC uses to read text characters, such as the text of the BASIC program which is being interpreted. It is placed on zero page to make the routine run faster. Since it keeps track of the address of the character being read within the routine itself, the routine must be in RAM in order to update that pointer. The pointer to the address of the byte currently being read is really the operand of a LDA instruction. When entered from CHRGET, the routine increments the pointer by modifying the operand at TXTPTR (122, $7A), thus allowing the next character to be read. Entry at CHRGOT (121, $79) allows the current character to be read again. The CHRGET routine skips spaces, sets the various flags or the status register (.P) to indicate whether the character read was a digit, statement terminator, or other type of character, and returns with the retrieved character in the Accumulator (.A). Since CHRGET is used to read every BASIC statement before it is executed, and since it is in RAM, and therefore changeable, it makes a handy place to intercept BASIC to add new features and commands (and in the older PET line, it was the only way to add such features). Diversion of the CHRGET routine for this purpose is generally referred to as a wedge. Since a wedge can greatly slow down execution speed, mose of the time it is set up so that it performs its preprocessing functions only when in direct or immediate mode. The most well-known example of such a wedge is the "Universal DOS Support" program that allows easier communication with the disk drive command channel. As this is such a central routine, a disassembly listing is given below to provide a better understanding of how it works.
The Accumulator (.A register) holds the character that was read on exit from the routine. Status register (.P) bits which can be tested for on exit are:
One wedge insertion technique is to change CHRGET's INC $7A to a JMP WEDGE, have your wedge update TXTPTR itself, and then JSR CHRGOT. Another is to change the CMP #$3A at location 124 ($7C), which I have labeled POINTB, to a JMP WEDGE, do your wedge processing, and then exit through the ROM version of POINTB, which is located at 48283 ($E3AB). For more detailed information about wedges, see Programming the PET/CBM, Raeto Collin West, pages 365-68. While the wedge is a good, quick technique for adding new commands, a much more elegant method exists for accomplishing this task on the VIC-20 and 64 withouth slowing BASIC down to the extent that the wedge does. See the entries for the BASIC RAM vector area at 768-779 ($0300-$030B) for more details. |
Teilprogramm »Nächstes Zeichen eines Basic-Textes holen« (CHRGET-Routine)Die Problematik der Übersetzung von Basic-Befehlen und Anweisungen besteht darin, daß die Übersetzungsschritte durch entsprechende Programmteile des Basic-Übersetzers im Computer fest vorprogrammiert sein müssen, was bedeutet, daß diese Programme natürlich im - nicht veränderbaren - ROM stehen. Auf der anderen Seite verlangt aber der Übersetzungsvorgang, daß gewisse Teile dieser Programme sich laufend verändern. Als Beispiel soll der Zeiger herhalten, der angibt, in welcher Speicherzelle das nächste zu bearbeitende Zeichen steht. Dieser Zeiger und die zusammengehörigen Programmschritte dürfen natürlich nicht im ROM stehen, denn da sind sie ja nicht änderbar. Dieser Konflikt wird dadurch gelöst, daß dieses »variable« Teilprogramm des Übersetzers zwar im ROM steht (im C 64 ab 58274 oder $E3A2, im VC 20 ab 58247 oder $E387), von wo es aber direkt nach dem Einschalten des Computers in das RAM, und zwar in die Speicherzellen 115 bis 138, umgeladen wird. Dieses Teilprogramm, welches die Zeichen zur Übersetzung herbeiholt und deswegen »Character-Get« oder kurz CHARGET-Routine genannt wird, ist wegen seiner Veränderbarkeit natürlich ein beliebtes Objekt aller möglichen Manipulationen. Es ist deshalb im Assembler-Kurs, Teil 5, im 64’er, Ausgabe 1/85, im Detail beschrieben worden, allerdings mit Schwerpunkt auf Assembler- Maschinensprache. Für Basic-Programmierer möchte ich hier deshalb eine kurze Beschreibung der CHARGET-Routine einfügen. Die Routine beginnt mit einem Sprung auf den oben schon erwähnten Zeiger in Adresse 122 und 123, welcher seinerseits auf die Adresse zeigt, in welcher das nächste zu übersetzende Zeichen steht. Das Zeichen wird entsprechend dem Hinweis des Zeigers geholt, in den Akkumulator des Mikroprozessors geladen und dort verschiedenen Prüfungen unterzogen. Ist das Zeichen ein Gänsefuß, erkennt das Programm, wie es das nächste Zeichen interpretieren und behandeln muß. Ein Doppelpunkt leitet einen neuen Befehl ein, eine Leerstelle wird unterdrückt und so weiter. Mit dem Befehl
können wir innerhalb eines Programms ausdrucken, wohin der Zeiger nach dem letzten Basic-Zeichen deutet. Eine Überprüfung mit den Methoden, die ich bei der Besprechung der Speicherzellen 43 bis 56 genannt habe, zeigt Ihnen den Zusammenhang. Normalerweise wird der Zeiger in 122 und 123 nach jedem Zeichen um 1 erhöht, da ja die Zeichen einer Basic-Zeile hintereinander im Speicher stehen. Ein GOTO- oder GOSUB-Befehl kann diese Folge natürlich unterbrechen, ebenso wie eine willkürliche Änderung durch einen Eingriff von außen. Ein derartiger Eingriff, auch »wedge« (Keil) genannt, öffnet natürlich Tür und Tor für Programmiertricks, insbesondere für Einbau von neuen, selbsterfundenen Befehlen. Man kann entweder den allerersten Sprungbefehl auf den Zeiger so umlenken, daß er auf ein eigenes Maschinenprogramm springt, oder man kann den Zeiger selbst »verbiegen«, so daß er auf eine andere Adresse und damit auf ein anderes Zeichen zeigt. Es gibt dafür viele Möglichkeiten, die aber alle nur in Maschinencode funktionieren. Theoretisch können wir natürlich den Inhalt des Zeigers in 122 und 123 durch POKE verändern. Aber was dann? Jeder nachfolgende Basic-Befehl löst natürlich wieder die normale Übersetzungsroutine aus und unser schöner POKE ist für die Katz. Wie ein Wedge in Maschinensprache gemacht wird, hat Christoph Sauer im VC 20- Kurs - 64’er, Ausgabe 9/84 beschrieben. Allerdings ist das Beispiel für Anfänger nicht verständlich, was mich zu der Überzeugung bringt, daß die CHARGET-Routine und ihre Anwendung einen eigenen Aufsatz wert wäre. |
CHRGET-RoutineDiese Routine holt ein Zeichen aus dem BASIC-Text. |
CHRGET. Machine code routine to read next byte from BASIC program or direct command (24 bytes). |
RAM code.This code gets changed throughout execution. It is made to be fast this way. Also, [X] and [Y] are not disturbed. "CHRGET" using [TXTPTR] as the current text pntr, fetches a new character into ACCA after incrementing [TXTPTR] and sets condition codes according to what's in ACCA.
[ACCA] = new char. [TXTPTR]=[TXTPTR]+1 The following exists in ROM if ROM exists and is loaded down here by init. Otherwise it is just loaded into this RAM like all the rest of RAM is loaded. |
Subroutine: Get Next Byte of BASIC Text | CHRGET subroutine; get Basic char | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0079 | CHRGOT | 121 |
CHRGOT. Read current byte from BASIC program or direct command.Pointer to current byte in BASIC program or direct command. |
Entry to Get Same Byte of Text Again | Entry to Get same Byte again. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$007A-$007B | TXTPTR | 122-123 |
ProgrammzeigerIn diesen Speicherzellen wird in LOW- und HIGH-Byte die Anfangsadresse des als nächstes auszuführenden Befehls im BASIC-RAM angegeben. |
Pointer: Current Byte of BASIC Text | Pointer: Current Byte of BASIC Text. | Basic pointer (within subrtn) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$008B-$008F | RNDX | 139-143 |
RND Function Seed ValueThis location holds the five-byte floating point value returned by the RND function. It is initially set to a seed value copied from ROM (the five bytes are 128, 79, 199, 82, 88--$80, $4F, $C7, $52, $58). When the function RND(X) is called, the numeric value of X does not affect the number returned, but its sign does. If X is equal to 0, RND generates a seed value from chip-level hardware timers. If X is a positive number, RND(X) will return the next number in an arithmetic sequence. This sequence continues for such a long time without repeating itself, and gives such an even distribution of numbers, that it can be considered random. If X is negative, the seed value is changed to a number that corresponds to a scrambled floating point representation of the number X itself. Given a particular seed value, the same pseudorandom series of numbers will always be returned. This can be handy for debugging purposes, but not where you wish to have truly random numbers. The traditional Commodore method of selecting a random seed is by using the expression RND(-TI), mostly because RND(0) didn't function correctly on early PETs. While the RND(0) form doesn't really work right on the 64 either (see location 57495 ($E097)), the expression RND(-RND(0)) may produce a more random seed value. |
Wert der RND-Funktion als GleitkommazahlMit dem Befehl RND(X) kann bekanntlich eine Zufallszahl erzeugt werden. Was das bedeutet und wie »zufällig« diese Zahlen sind, können Sie dem Texteinschub Nr. 13 »Wie zufällig sind Zufallszahlen?« entnehmen. Beim Einschalten des Computers werden die Zahlen 128, 79, 199, 82 und 88 in diese Speicherzellen geschrieben. Mit der folgenden Zeile können Sie das gleich nach dem Einschalten des Computers leicht überprüfen.
Nach den Manipulationen des RND-Befehls wird das Resultat wieder in die Zellen 139 bis 143 als neuer Ausgangswert (seed) für den nächsten RND-Befehl gebracht. Diese fünf Zahlen stellen eine Gleitkommazahl dar. Ihre Form entspricht dabei der Aufteilung, wie sie auch im Gleitkomma-Akkumulator (97 bis 101) verwendet wird. Eine Abfrage dieser Zahlen aus den Zellen 139 bis 143 ist natürlich möglich, aber nicht ergiebig, weil das Resultat von RND(X) direkt als Zahl verfügbar ist, während die 5 Byte erst in eine brauchbare Zahl umgerechnet werden müßten. Eine Änderung durch POKEn neuer Werte in diese Speicherzellen geht leider nicht. |
letzter RND-WertIn diesen Registern wird der letzte RND-Wert im Fließkommaformat abgelegt. |
Previous result of RND(). | Floating RND Function Seed Value | Floating RND Function Seed Value. | RND seed value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0090 | STATUS | 144 |
Kernal I/O Status Word (ST)The Kernal routines which open I/O channels or perform input/output functions check and update this location. The value here is almost always the same as that returned to BASIC by use of the reserved variable ST. Note that BASIC syntax will not allow an assignment such as ST=4. A table of status codes for cassette and serial devices follows below:
Probably the most useful bit to test is Bit 6 (end of file). When using the GET statement to read in individual bytes from a file, the statement IF ST AND 64 will be true if you have got to the end of the file. For status codes for the RS-232 device, see the entry for location 663 ($0297). |
Statusvariable STDiese Adresse enthält ein Byte, welches mit der Statusvariablen ST von Basic identisch ist. Diese reservierte Variable ist im Texteinschub Nr. 14 »ST-atus« näher beschrieben. Alle Routinen des Betriebssystems, die mit Ein- und Ausgabe zu tun haben, benutzen diese Speicherzelle zum Abspeichern und Abfragen des Status der Ein-/ Ausgabeoperationen. Genauer gesagt, alle Ein-/Ausgabeoperationen, die mit der Datasette und mit dem Floppy-Gerät beziehungsweise dem Drucker zu tun haben, benutzen die Adresse 144. Im Fachjargon sprechen wir vom Kassetten-Port und vom seriellen Port. Der dritte Anschluß des Computers, nämlich der RS232 oder User-Port, benutzt für den Status die Speicherzelle 663. Jedes Bit der Zelle 144 hat eine eigene Bedeutung wie folgt.
Alle nicht aufgeführten Bits sind nicht benutzt. Diese Speicherzelle beziehungsweise die Statusvariable ST kann recht nützlich sein. Einige Kochrezepte dafür werden im Texteinschub Nr. 14 behandelt. |
Statuswort STIn dieser Speicherzelle, die auch mit der BASIC-Variable ST identisch ist, sind die Fehlermeldungen der Datasette und der Floppy verzeichnet:
|
Value of ST variable, device status for serial bus and datasette input/outputSerial bus bits:
Datasette bits:
|
I/O operation status byte | Kernal I/O Status Word: ST | Kernal I/O Status Word ST. | Status word ST | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0091 | STKEY | 145 |
Flag: Was STOP Key Pressed?This location is updated every 1/60 second during the execution of the IRQ routine that reads the keyboard and updates the jiffy clock. The value of the last row of the keyboard matrix is placed here. That row contains the STOP key, and although this location is used primarily to detect when that key has been pressed, it can also detect when any of the other keys in that row of the matrix have been pressed. In reading the keyboard matrix, a bit set to 1 means that no key has been pressed, while a bit reset to 0 indicates that a key is pressed. Therefore, the following values indicate the keystrokes detailed below:
VIC owners will notice that the 64's keyboard matrix is very different from the VIC's. One of the advantages of this difference is that you can test for the STOP key by following a read of this location with a BPL instruction, which will cause a branch to occur anytime that the STOP key is pressed. |
Zwischenspeicher für Abfrage der STOP-TasteIn den Bildern 13 und 14 ist dargestellt, wie die Tasten des VC 20 und des C 64 miteinander über eine Matrix verbunden sind. 60mal in der Sekunde unterbricht der Computer seine Arbeit, merkt sich, wo er gerade ist und fragt dann unter anderem, ob die STOP-Taste gedrückt worden ist. Dadurch wird erreicht, daß die STOP-Taste jederzeit Priorität hat. Die Abfrage geht so vonstatten, daß das Betriebssystem über das im Bild 13 und 14 gezeigte Spaltenregister 56320 (beim VC 20: 37152) diejenige Tastenspalte anwählt, in welcher sich die STOP-Taste befindet. Aus Bild 13 und 14 sehen wir, daß dies die Spalte mit der Codenummer 127 beziehungsweise 247 ist. Ist in dieser Spalte eine Taste gedrückt, wird an ihrer Stelle eine Null in das Auslese-Register 56321 (VC 20: 37153) geschrieben. Die dadurch entstandene Dualzahl wird in die Speicherzelle 145 gebracht. Es ist sicher verständlich, daß auf diese Weise nicht nur die STOP-Taste, sondern alle Tasten der Spalte 127 (247) abgefragt werden können. Ein kleines Demonstrationsprogramm kann das beweisen:
Beim VC 20 ist statt 56321 natürlich 37153 einzusetzen. Das Zahlenband kann durch die Tasten der genannten Spalte - und nur durch diese - beeinflußt werden. |
Flag für STOP-TasteIn dieser Speicherzelle wird vermerkt, ob die Stoptaste gedrückt worden ist oder nicht. |
Stop key indicatorValues:
|
STOP key flag | Flag: STOP key / RVS key | Flag: $7F = STOP key. | Keyswitch PIA : STOP and RVS flags | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0092 | SVXT | 146 |
Timing Constant for Tape ReadsThis location is used as an adjustable timing constant for tape reads, which can be changed to allow for the slight speed variation between tapes. |
Zeltkonstante beim Lesen vom BandDie Speicherzelle enthält eine vom Betriebssystem einstellbare Zahl, welche die kleinen Unterschiede in der Aufnahmegeschwindigkeit ausgleicht, die bei verschiedenen Datasetten vorkommen können. Diese Zeitkonstante steht im Zusammenhang mit der Zahl, die in den Speicherzellen 176 und 177 steht. Eine Veränderung der Konstante in Basic ist nicht möglich. |
Zeitkonstante für BandDieses Register hat die Aufgabe, kleine Unterschiede bei der Aufnahmegeschwindigkeit auszugleichen. |
Unknown. (Timing constant during datasette input.) | Cassette: temp used to adjust software servo | Timing Constant for Tape | Timing Constant for Tape. | Timing constant for tape | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0093 | VERCK | 147 |
Flag for Load Routine: 0=LOAD, 1=VERIFYThe same Kernal routine can perform either a LOAD or VERIFY, depending on the value stored in the Accumulator (.A) on entry to the routine. This location is used to determine which operation to perform. |
Flagge für LOAD oder VERIFYDiese Flagge dient dem Betriebssystem, um zu unterscheiden, ob eine LOAD- Operation nur LOADen oder aber VERIFYen soll. Sie ist identisch mit der Flagge des Basic-Übersetzers in Speicherzelle 10. Genauere Hinweise bitte ich der Beschreibung von Zelle 10 zu entnehmen. |
Flag für LOAD $00, oder für VERIFY $01Dieses Flag dient dem Betriebssystem dazu, um zu unterscheiden, ob eine LOAD oder eine VERIFY Operation erfolgt. |
LOAD/VERIFY switchValues:
|
Cassette: verify or load flag (Z - loading) | Flag: 0 = Load, 1 = Verify | Flag: 0 = Load, 1 = Verify. | Load = 0, Verify = l | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0094 | C3P0 | 148 |
Flag: Serial Bus--Output Character Was BufferedThis location is used by the serial output routines to indicate that a character has been placed in the output buffer and is waiting to be sent. |
Flagge für Floppy/Drucker-AusgangDas Betriebssystem benutzt diese Speicherzelle, um anzuzeigen, daß ein Zeichen im Ausgabepuffer steht, welches zum Floppy-Gerät oder zum Drucker geleitet werden soll. Diese Flagge setzt alle am seriellen Port angeschlossenen Geräte in den Zustand »Listen«, das heißt bereit zu sein, Daten aufzunehmen. |
Flag bei IEC-AusgabeDiese Adresse setzt bei Floppy und Drucker den "LISTEN" Zustand. |
Serial bus output cache statusBits:
|
IEEE buffered char flag | Flag: Serial Bus-Output Char. Buffered | Flag: Serial Bus - Output Character buffered. | Serial output : deferred char flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0095 | BSOUR | 149 |
Buffered Character for Serial BusThis is the character waiting to be sent. A 255 ($FF) indicates that no character is waiting for serial output. |
Zeichen im AusgabepufferIn dieser Speicherzelle wird das Zeichen abgelegt, welches als nächstes über den Serial-Port zum Floppy-Gerät oder zum Drucker transportiert wird, sobald die Flagge in 148 die Bereitschaft anzeigt. |
Ausgabepuffer für IEC-BusHier wird das Zeichen abgelegt, welches über den seriellen Port zur Floppy oder zum Drucker geschickt werden soll, sobald die Adresse $94 Bereitschaft zeigt. |
Serial bus output cache, previous byte to be sent to serial bus. | Char buffer for IEEE | Buffered Character for Serial Bus | Buffered Character for Serial Bus. | Serial deferred character | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0096 | SYNO | 150 | Cassette Block Synchronization Number |
Arbeitsspeicher für die Band-LeseroutineDiese Speicherzelle wird zur Zwischenspeicherung von Daten beim Lesen einer Kassette benutzt. |
Flag für EOT vom Band empfangenIn $96 werden die Daten zwischengespeichert, die vom Band gelesen werden. |
Unknown. (End of tape indicator during datasette input/output.) | Cassette: flags if we have block SYNC (16 zero dipoles) | Cassette Sync No. | Cassette Sync. number. | Tape EOT received | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0097 | XSAV | 151 |
Temporary .X Register Save AreaThis .X register save area is used by the routines that get and put an ASCII character. |
Zwischenspeicher des X-RegistersMaschinen-Programmierer kennen das X-Register des Mikroprozessors. Beim Lesen eines Zeichens von der Datasette wird der Inhalt des X-Registers in dieser Adresse zwischengespeichert. |
Zwischenspeicher für RegisterBeim Lesen von Band wird hier das X-Register zwischengespeichert. |
Temporary area for saving original value of Y register during input from RS232. Temporary area for saving original value of X register during input from datasette. |
Temp for BASIN | Temp Data Area |
Temporary storage of X Register during CHRIN. Temporary storage of Y Register during RS232 fetch. |
Register save | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0098 | LDTND | 152 |
Number of Open I/O Files/Index to the End of File TablesThe number of currently open I/O files is stored here. The maximum number that can be open at one time is ten. The number stored here is used as the index to the end of the tables that hold the file numbers, device numbers, and secondary address numbers (see locations 601-631 ($0259-$0277) for more information about these tables). CLOSE decreases this number and removes entries from the tables referred to above, while OPEN increases it and adds the appropriate information to the end of the tables. The Kernal routine CLALL closes all files by setting this number to 0, which effectively empties the table. |
Anzahl der offenen FilesEin File, oder auf Deutsch gesagt, eine Datei, wird mit dem Befehl OPEN eröffnet. Nach OPEN folgt die Nummer der Datei; sie ist beliebig wählbar bis maximal 255. Als zweites folgt die Nummer des Gerätes, mit dem die Verbindung hergestellt werden soll. Es ist erlaubt, mehrere Dateien gleichzeitig geöffnet zu halten, vorausgesetzt die Nummern der Dateien sind verschieden. In Speicherzelle 152 wird festgehalten, wieviel Dateien gleichzeitig geöffnet sind. Dieses kleine Programm zeigt es uns deutlich:
Mit der FOR...NEXT-Schleife der Zeilen 10 und 40 eröffnen wir 13 Dateien hintereinander, und zwar - wie Zeile 30 uns deutlich macht - mit der Tastatur. Die Tastatur hat die Nummer 0, der Drucker die Nummer 4, das Floppy-Gerät die Nummer 8 und die Datasette die Nummer 1. Ich habe die Tastatur gewählt, obwohl es keinen Sinn ergibt, weil sie die vielen Eröffnungen ohne zu unterbrechen akzeptiert. Nach RUN sehen wir links untereinander den Inhalt von 152, also die Anzahl der eröffneten Dateien. Rechts steht jeweils die Nummer der eröffne- In der 10. Zeile sehen wir jetzt die 10 als Inhalt von 152 und als neue Dateinummer (Schleifenvariable K) wieder die 10. Das Programm bleibt aber stehen und meldet FILE OPEN. Es hat recht, denn die Datei 10 ist bereits als erste eröffnet, aber nicht wieder geschlossen worden. Das Betriebssystem macht das so, daß jede der Dateinummern in eine Tabelle geschrieben wird, die in den Speicherzellen 601 bis 610 stehen. Bei jedem OPEN- Befehl wird dort nachgeschaut, ob die Filenummer existiert. Wenn ja, wird die Fehlermeldung FILE OPEN ERROR ausgegeben. Bei jedem CLOSE-Befehl wird die entsprechende Nummer aus der Tabelle gelöscht. Wir können aber auch eine 0 in die Speicherzelle 152 POKEn, wodurch dem Betriebssystem vorgegaukelt wird, daß keine Datei eröffnet ist. Schieben Sie im Programm einfach die Zeile ein:
und das Programm läuft ewig weiter. Die Speicherzelle 152 ist also der Wächter über die Anzahl der eröffneten Dateien. Steht sie auf 0, dann wird eine Neueröffnung am Anfang der Tabelle ab 601 eingetragen. Die Tabelle ihrerseits ist der Wächter über Exklusivität der Dateinummern. Ich zeige Ihnen das noch genauer, wenn wir zu 601 kommen. Sie werden vielleicht fragen, warum ich das so ausführlich beschreibe. Nun, in einem Programm kann es sicher sehr nützlich sein, dieZelle 152 mit PEEK nach der Datei-Lage abzufragen und entsprechend Maßnahmen zu treffen, ehe die Fehlermeldung das Programm abbricht. Mit POKE 152,0 aber müssen Sie aufpassen. Es ersetzt nämlich nicht (!!) den CLOSE-Befehl. Probieren Sie es aus: Um das kleine Programm oben per Drucker auszudrucken, brauchen wir:
Wenn Sie jetzt die Zeile 152 auf 0 POKEn und dann LIST eintippen, wird trotzdem wieder auf dem Drucker gelistet und nicht auf dem Bildschirm. Die vorgeschriebene Schließmethode mit
geht jetzt aber auch nicht mehr, denn das Betriebssystem ist ja im Glauben, daß keine Datei eröffnet ist - schöner Schlamassel! Erst eine Neueröffnung bringt alles wieder in die Reihe. Also Vorsicht mit der Anwendung der Speicherzelle 152. Eine Möglichkeit, alle Dateien auf einen Schlag zu schließen, gibt es aber doch. SYS 65511 besorgt das sowohl beim C 64 als auch beim VC 20. |
Anzahl der offenen FilesIn dieser Speicherzelle wird festgehalten, wie viele Files gleichzeitig geöffnet sind. |
Number of files currently openValues: $00-$0A, 0-10. |
Index to logical file | No. of Open Files / Index to File Table | Number of Open Files/Index to File Table. | How many open files | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0099 | DFLTN | 153 |
Default Input Device (Set to 0 for Keyboard)The default value of this location is 0, which designates the keyboard as the current input device. That value can be changed by the Kernal routine CHKIN (61966, $F20E), which uses this location to store the device number of the device whose file it defines as an input channel. BASIC calls CHKIN whenever the command INPUT# or GET# is executed, but clears the channel after the input operation has been completed. |
Nummer des Eingabe-GerätesDas Betriebssystem verwendet diese Speicherzelle, um festzuhalten, welches Gerät zur Eingabe verwendet werden soll. Die Nummern sind wie folgt festgelegt:
Nach dem Einschalten oder nach RESET des Computers steht in 153 eine 0 (Tastatur). Nach jedem Einsatz eines anderen Gerätes wird diese Speicherzelle wieder auf 0 gesetzt, so daß wir immer die Tastatur zur Verfügung haben. Für Maschinenprogrammierer ist diese Adresse sicherlich wertvoll. Die Routine, welche die Eingabegeräte festlegt, sobald der Befehl INPUT# beziehungsweise GET# ausgeführt wird, heißt CHKIN und beginnt beim C 64 ab Adresse 61966 ($F20E), beim VC 20 ab 62151 ($F2C7). Für Basic-Programmierer habe ich in der Literatur nur eine Anwendung gefunden, und die wurde bereits bei der Besprechung der Speicherzelle 19 angekündigt. Es ist dies eine MERGE-Routine. Leider funktioniert dieses Verfahren nicht bei dem 1541-Floppy-Laufwerk. Erfunden wurde die Routine von Brad Templeton und ist von Jim Butterfield unter dem Namen »Magic Merge« für den VC 20/ C 64 adaptiert worden. Ich gebe zu, in der Zwischenzeit sind noch andere, vielleicht auch kürzere MERGE-Routinen veröffentlicht worden. Aber diese hier verwendet gleich drei interessante Ingredienzen, nämlich die Speicherzellen 19 und 153 und außerdem die sogenannte »Dynamische Tastenabfrage«. Wer die letztere nicht kennt, sollte sich zum Verständnis den Texteinschub Nr. 15 gleichen Namens ansehen. Ein MERGE (deutsch: zusammenführen, verschmelzen) besteht darin, ein auf Band gespeichertes Programm zu einem im Computer stehenden anderen Programm so dazuzuladen, daß dieses nicht überschrieben, sondern ergänzt wird. Wichtig ist dabei, daß das Programm vom Band höhere Zeilennummern hat als das Programm im Computer. Außerdem muß das Programm auf dem Band als Datei gespeichert sein. Das wird so erreicht:
Damit ist das Programm auf dem Band gespeichert. Nun kommt der eigentliche MERGE-Vorgang.
Wie gesagt, Schritt 6 verwendet Zeile 19 (bitte dort nachlesen), Schritte 8 und 9 sind die »Dynamische Tastenabfrage«, und Schritt 9 verwendet zusätzlich die hier zur Diskussion stehende Speicherzelle 153, um die Datasette als Eingabegerät zu definieren. |
aktives EingabegerätIn dieser Speicherzelle wird festgehalten, welches Gerät zur Eingabe verwendet werden soll. Die Nummern sind folgendermaßen festgelegt:
|
Current input device number.Default: $00, keyboard. |
Default input device # | Default Input Device (0) | Default Input Device (0). | Input device, normally 0 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$009A | DFLTO | 154 |
Default Output (CMD) Device (Set to 3 for the Screen)The default value of this location is 3, which designates the screen as the current output device. That value can be changed by the Kernal routine CHKOUT (62032, $F250), which uses this location to store the device number of the device whose file it defines as an output channel. BASIC calls CHKOUT whenever the command PRINT# or CMD is executed, but clears the channel after the PRINT# operation has been completed. |
Nummer des Ausgabe-GerätesDiese Speicherzelle entspricht der Zelle 153, nur steht hier die Nummer des Gerätes, über das die Ausgabe läuft. Nach dem Einschalten und nach Ausgabeoperationen wird der Wert immer auf 3 gesetzt. Das ist entsprechend der oben genannten Zuordnung der Bildschirm. Für Maschinenprogrammierer sei erwähnt, daß Basic bei den Befehlen PRINT# oder CMD die Routine CHKOUT einsetzt, welche die Adresse 154 belegt. Sie steht im C 64 ab Adresse 62032 ($F250), im VC 20 ab 62217 ($F309). |
aktives AusgabegerätDiese Speicherzelle ist mit der vorherigen zu vergleichen, nur steht hier die Nummer des Geräts, über das die Ausgabe erfolgt. |
Current output device number.Default: $03, screen. |
Default output device # | Default Output (CMD) Device (3) | Default Output Device (3). | Output CMD device, normally 3 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$009B | PRTY | 155 |
Tape Character ParityThis location is used to help detect when bits of information have been lost during transmission of tape data. |
Fehlerkontrolle bei BandoperationenDie Commodore-Datasette ist deswegen so zuverlässig, weil sie mehrere Methoden zur Fehlererkennung beziehungsweise Korrektur von Lese- und Schreibfehlern verwendet. Eine der Methoden ist die sogenannte Parity-Prüfung. Sie ist nichts anderes als eine Quersummenbildung der einzelnen Stellen jedes Bytes, deren Resultat überprüft wird. Die Speicherzelle 155 wird bei dieser Parity-Prüfung eingesetzt. |
Parität für BandÜber diese Speicherzelle findet eine Parity-Prüfung (Quersummenbildung) statt. Dies dient dazu, um Lese- und Schreibfehler zu vermeiden. |
Unknown. (Parity bit during datasette input/output.) | Cassette: holds current calculated parity bit | Tape Character Parity | Parity of Byte Output to Tape. | Tape character parity | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$009C | DPSW | 156 |
Flag: Tape Byte ReceivedThis location is used as a flag to indicate whether a complete byte of tape data has been received, or whether it has only been partially received. |
Flagge für korrektes Byte vom BandIn dieser Speicherzelle wird zwischengespeichert, ob das vom Band gelesene Byte die Prüfungen bestanden hat, also richtig ist oder nicht. |
Flag für Byte empfangenHier wird festgelegt, ob das gelesene Byte die Quersumme richtig gebildet hat oder nicht. |
Unknown. (Byte ready indicator during datasette input/output.) | Cassette: if NZ then expecting LL/L combination that ends a byte | Flag: Tape Byte-Received | Flag: Byte received from Tape. | Byte-received flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$009D | MSGFLG | 157 |
Flag: Kernal Message ControlThis flag is set by the Kernal routine SETMSG (65048, $FE18), and it controls whether or not Kernal error messages or control messages will be displayed. A value of 192 ($C0) here means that both Kernal error and control messages will be displayed. This will never normally occur when using BASIC, which prefers its own plain text error messages over the Kernal's perfunctory I/O ERROR (number). The Kernal error messages might be used, however, when you are SAVEing or LOADing with a machine language monitor. A 128 ($80) means that control messages only will be displayed. Such will be the case when you are in the BASIC direct or immediate mode. These messages include SEARCHING, SAVING, FOUND, etc. A value of 64 means that Kernal error messages only are on. A 0 here suppresses the display of all Kernal messages. This is the value placed here when BASIC enters the program or RUN mode. |
Flagge für MeldungenMan muß zwischen zwei Arten von Meldungen unterscheiden: Meldungen des Betriebssystems Meldungen des Basic-Übersetzers Die Meldungen des Betriebssystems kennen wir als Angaben zum Ablauf, wie SEARCHING FOR, FOUND, PRESS PLAY ON TAPE und so weiter. Normalerweise nicht bekannt ist die Meldung I/O ERROR #, wobei nach dem Zeichen # Zahlen von 0 bis 29 stehen können. Diese Zahlen beziehen sich auf Meldungen des Übersetzers (Interpreter), die ausschließlich Fehlermeldungen sind. Das mag verwirrend klingen, klärt sich aber sofort. Die Flagge in 157 kann vier Werte annehmen: 0,64,128 und 192.
Das folgende Beispiel macht das deutlich. Geben Sie direkt ein:
Wir versuchen, vom Gerät mit der Nummer 9, das ist eine zweite Floppy, die Directory zu laden. Wir erhalten entsprechend Punkt 1 nur die Meldung des Übersetzers
Verändern wir den POKE-Befehl für Punkt 2:
Wir erhalten jetzt
ergibt die Meldung
Schließlich nehmen wir noch den letzten Fall:
Jetzt erhalten wir alles:
Da die Fehlermeldung des Betriebssystems und die zugehörigen Nummern in keinem Handbuch erwähnt sind, habe ich sie interessehalber in der folgenden Tabelle zusammengefaßt.
|
Flag für Direktmodus $80, Programm $00In dieser Speicherzelle wird angegeben, welche Fehlermeldungen zugelassen werden und welche nicht. $00 unterdrückt alle Fehlermeldungen, $80 kommt dem normalen Eingabemodus gleich und $C0 läßt alle Fehlermeldungen zu. Diese Zustände können alle künstlich erzeugt werden. |
System error display switchBits:
|
OS message flag | Flag: $80 = Direct Mode, $00 = Program | Flag: $00 = Program mode: Suppress Error Messages, $40 = Kernal Error Messages only, $80 = Direct mode: Full Error Messages. | Direct = $80/RUN = 0 output control | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$009E-$009F | 158-159 |
Zwischenspeicher bei KassettenoperationenDiese beiden Speicherzellen werden von Routinen des Betriebssystems verwendet, welche bei Kassettenoperationen die Zeichen überprüfen, ob sie richtig sind, und welche bei aufgetretenen Fehlern Korrekturen durchführen. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$009E | PTR1 | 158 |
Tape Pass 1 Error Log IndexThis location is used in setting up an error log of bytes in which transmission parity errors occur the first time that the block is received (each tape block is sent twice to minimize data loss from transmission error). |
Bandpass 1 ChecksummeDiese Speicherzelle wird zur Überprüfung von Bytes bei Kassettenoperationen benutzt. |
Error counter during LOAD from datasette.Values: $00-$3E, 0-62. |
Cassette: count of read locations in error (pointer into bad, max 61) | Tape Pass 1 Error Log | Tape Error log pass 1. | Tp Pass 1 error log/char buffer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
T1 |
Block header type during datasette input/output. Length of file name during datasette input/output. Byte to be put into output buffer during RS232 and datasette output. |
Temporary 1 | Index to Cassette File name/Header ID for Tape write. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$009F | PTR2 | 159 |
Tape Pass 2 Error Log Correction IndexThis location is used in correcting bytes of tape data which were transmitted incorrectly on the first pass. |
Bandpass 2 FehlerkorrekturHier werden die Fehler korrigiert, die bei Kassettenoperationen aufgetreten sind. |
Error correction counter during LOAD from datasette.Values: $00-$3E, 0-62. |
Cassette: count of re-read locations (pointer into bad, during re-read) | Tape Pass 2 Error Log | Tape Error log pass 2. | Tp Pass 2 err log corrected | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
T2 |
Auxiliary counter for writing file name into datasette buffer. Auxiliary counter for comparing requested file name with file name read from datasette during datasette input. |
Temporary 2 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A0-$00A2 | TIME | 160-162 |
Software Jiffy ClockThese three locations are updated 60 times a second, and serve as a software clock which counts the number of jiffies (sixtieths of a second) that have elapsed since the computer was turned on. The value of location 162 ($A2) is increased every jiffy (0.1667 second), 161 ($A1) is updated every 256 jiffies (4.2267 seconds), and 160 ($A0) changes every 65536 jiffies (or every 18.2044 minutes). After 24 hours, these locations are set back to 0. The jiffy clock is used by the BASIC reserved variables TI and TI$. These are not ordinary variables that are stored in the RAM variable area, but are functions that call the Kernal routines RDTIM (63197, $F6DD), and SETTIM (63204, $F6E4). Assigning the value of TI or TI$ to another variable reads these locations, while assigning a given value to TI$ alters these locations. To illustrate the relationship between these locations and TI$, try the following program. The program sets the jiffy clock to 23 hours, 50 minutes. After the program has been running for one minute, all these locations will be reset to 0.
Since updating is done by the IRQ interrupt that reads the keyboard, anything which affects the operation of that interrupt routine will also interfere with this clock. A typical example is tape I/O operations, which steal the IRQ vector for their own use, and restore it afterwards. Obviously, user routines which redirect the IRQ and do not send it back to the normal routine will upset software clock operation as well. |
Interne Uhr für TI und TI$Das Basic der Commodore-Computer kennt neben der Variablen ST (siehe Speicherzelle 144) noch zwei weitere »reservierte« Variable, nämlich TI und TI$. Beide bieten eine interne Uhr, welche aus dem Inhalt der Speicherzellen 160 bis 162 abgeleitet wird. Diese drei Zellen funktionieren wie der Kilometerzähler eines Autos, halt nur mit drei Stellen. Die hinterste Stelle ist die Zelle 162. Ihr Inhalt wird beim Einschalten des Computers auf 0 gesetzt, dann aber 60mal in der Sekunde um 1 erhöht. Das erfolgt durch die automatische Interrupt-Routine, welche auch die STOP-Taste abfragt und noch andere Hausaufgaben 60mal in der Sekunde ausführt. Da i60 = 0,01667 ist, zählt also dle Zelle 162 in 0,01667 Sekunden um 1 weiter. Sie kann wie alle Speicherzellen maximal nur die Zahl 255 enthalten, danach kommt wieder eine 0. Das heißt aber, daß sie nach 256 * 0,01667 = 4,267 Sekunden einmal durchgelaufen ist. Nach jedem Durchlauf wird die davorliegende Speicherzelle 161 um 1 erhöht. Sie zählt also in 4,267 Sekunden um 1 weiter und ist nach 256 * 4.067 = 1 092,26 Sekunden oder besser nach 18,2044 Minuten einmal durchgelaufen. Nach dem Kilometerzähler-Prinzip wird nach jedem Durchlauf von 161 der Inhalt der davorliegenden Zelle 160 um 1 erhöht. Die Zelle 160 zählt also in 18,2044 Minuten um 1 weiter und ist nach 256 * 18, 2044 = 4660,34 Minuten, das sind 77.67 Stunden, einmal durchgelaufen. Diese Stundenzahl wird allerdings niemals erreicht, da das Betriebssystem nach Erreichen des Wertes für 24 Stunden alle drei Zellen wieder auf 0 zurücksetzt. Wir werden das gleich nachprüfen. Zuerst aber wollen wir uns den dreizelligen Zähler anschauen:
Nach RUN sehen wir den Inhalt der drei Zellen sich entsprechend der oben angegebenen Zeiten verändern. Die Zahlen sind nicht vorherbestimmbar, denn der Zähler ist ja nach dem Einschalten des Computers schon losgelaufen. Er kann aber auf 0 gesetzt werden durch Einfügen der Zeile 5:
Jetzt beginnt der Zähler immer ab 0. Ich habe gerade gesagt, daß der Zähler auf 0 gesetzt wird, wenn er 24 Stunden lang gelaufen ist. Der Inhalt in den drei Speicherzellen, der 24 Stunden entspricht, ist nach der oben angegebenen Umrechnungsart 79-26-0. Diesen Wert, oder besser noch ein Wert kurz davor, in die Zellen 160 bis 162 gePOKEt, zeigt uns den Nullsetzvorgang. Ersetzen Sie bitte die obige Zeile 5 durch eine neue Zeile:
Nach vier Sekunden Laufzeit schalten alle drei Zellen in der Tat auf 0 zurück. Die Umsetzung der Zahlen aus 160 bis 162 in die Variablen TI und TI$ sowie deren Wirkungsweise entnehmen Sie bitte dem Texteinschub Nr. 16 »Die eingebaute Uhr«. Abschließend muß eines noch warnend erwähnt werden. Alle Operationen, welche den Interrupt-Vektor verwenden beziehungsweise verändern, stören oder verzögern die normale Interrupt-Routine, die ja den Zähler weiterstellt. So zählt der Zähler nicht gleichmäßig und die daraus abgeleitete Uhr geht nicht mehr richtig. Ein Beispiel dafür sind alle Ein- und Ausgaben über die Datasette, welche über einen Interrupt laufen. |
TimeIn diesen Speicherzellen wird die Uhrzeit über die Interruptroutine erhöht. |
Value of TI variable, time of day, increased by 1 every 1/60 second (on PAL machines)Values: $0000-$4F19FF, 0-518399 (on PAL machines). |
24 hour clock in 1/60th seconds | Real-Time Jiffy Clock (approx) 1/60 Sec | Real-time jiffy Clock (Updated by IRQ Interrupt approx. every 1/60 of Second); Update Routine: UDTIMK ($F69B). | Jiffy Clock HML | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A3-$00A4 | 163-164 |
Temporary Data Storage AreaThese locations are used temporarily by the tape and serial I/O routines. |
ZwischenspeicherDiese beiden Speicherzellen werden von den Ein- und Ausgabe-Routinen des Betriebssystems für Kassetten, Floppy-Laufwerk und Drucker als Zwischenspeicher für alle möglichen Werte benutzt. |
Temp Data Area | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A3 | R2D2 | 163 |
Bitzähler für serielle AusgabeDieses Register wird als Zwischenspeicher von Ein-/Ausgaberoutinen benutzt. |
EOI switch during serial bus outputBits:
Bit counter during datasette output. |
Serial bus usage | Bit Counter Tape Read or Write/Serial Bus EOI (End Of Input) Flag. | Serial bit count/EOI flag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PCNTR | Cassette: counts down from 8-0 for data then to ff for parity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A4 | FIRT | 164 |
Zähler für Bandsiehe oben |
Byte buffer during serial bus input. Parity during datasette input/output. |
Pulse Counter Tape Read or Write/Serial Bus shift Counter. | Cycle count | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
BSOUR1 | Temp used by serial routine | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FIRT | Cassette: used to indicate which half of dipole we're in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A5 | CNTDN | 165 |
Cassette Synchronization Character CountdownUsed to count down the number of synchronization characters that are sent before the actual data in a tape block. |
Bit-Zähler für Kassetten-SynchronisierungBeim Abspeichern eines Programms auf ein Band werden vor den eigentlichen Daten mehrere Bits zusätzlich gespeichert, die beim Einlesen dieses Bandes zur Synchronisierung dienen, das heißt zum Übereinstimmen der Geschwindigkeit der Datenübertragung. Die Speicherzelle 165 wird als Zähler dieses Synchron-Bits verwendet. |
Zähler für Band schreibenDiese Speicherzelle wird als Zähler des Synchron-Bits verwendet. |
Bit counter during serial bus input/output. Counter for sync mark during datasette output. |
Cassette Sync Countdown | Tape Synchronising count down. | Countdown, tape write/bit count | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
COUNT | Temp used by serial routine | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CNTDN | Cassette sync countdown | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A6 | BUFPT | 166 |
Count of Characters in Tape I/O BufferThis location is used to count the number of bytes that have been read in or written to the tape buffer. Since on a tape write, no data is sent until the 192 byte buffer is full, you can force output of the buffer with the statement POKE 166,191. |
Zahler der bearbeiteten Bytes im Kassetten-PufferDiese Speicherzelle wird als Zähler benutzt, welcher angibt, wieviele Bytes gerade in den Kassetten-Puffer eingeschrieben oder aus ihm ausgelesen worden sind. Der Kassetten-Puffer besteht aus den Speicherzellen 828 bis 1 019 und kann somit 191 Byte aufnehmen, was zugleich die höchste Zahl ist, welche sinnvollerweise in der Zelle 166 stehen kann. Nähere Erklärungen und ein paar Experimente mit Zelle 166 finden Sie in dem Texteinschub 17 »Experimente mit dem Kassetten-Puffer«. Die meisten der nächsten 20 Speicherzellen werden bei Operationen mit der RS232-Schnittstelle, die über den User-Port den Computer mit anderen Geräten verbindet, eingesetzt. Da die Programmierung der RS232-Schnittstelle noch andere Speicherzellen benötigt, die später an der Reihe sind, gehe ich auf die RS232-Schnittstelle erst bei der Behandlung der Speicherzelle 659 bis 673 näher ein. |
Zeiger in BandpufferDieses Register wird als Zähler benutzt, welcher angibt, wie viele Bytes aus dem Bandpuffer gelesen oder in den Bandpuffer geschrieben worden sind. |
Offset of current byte in datasette buffer. | Cassette buffer pointer | Pointer: Tape I/O Buffer | Pointer: Tape I/O buffer. | Tape buffer pointer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A7-$00AB | 167-171 |
Arbeitsspeicher für Ein-/AusgabeDiese Register werden häufig von Kassettenoperationen und der RS-232 Schnittstelle als Zwischenspeicher benutzt. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A7 | INBIT | 167 |
RS-232 Input Bits/Cassette Temporary Storage AreaThis location is used to temporarily store each bit of serial data that is received, as well as for miscellaneous tasks by tape I/O. |
Zwischenspeicher für Kassetten-Operationen und für Eingabe über die RS232-SchnittsteileDiese Speicherzelle wird verwendet, um jedes Bit, welches von einem RS232-Kanal über den User-Port eingelesen wird, zwischenzuspeichern. Außerdem verwenden mehrere Kassetten-Routinen diese Adresse als Zwischenspeicher. |
Bit buffer during RS232 input. | RS-232 rcvr input bit storage | RS-232 Input Bits / Cassette Temp | RS232 temporary for received Bit/Tape temporary. | Tp Wrt ldr count/Rd pass/inbit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SHCNL | Cassette: holds FSBLK, used to direct routines, because of exit case | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A8 | BITCI | 168 |
RS-232 Input Bit Count/Cassete Temporary StorageThis location is used to count the number of bits of serial data that has been received. This is necessary so that the serial routines will know when a full word has been received. It is also used as an error flag during tape loads. |
Bitzähler für RS232-Eingabe und bei Band-Ein-/AusgabeDie Speicherzelle 168 wird als Zähler verwendet, der dies mal nicht die Bytes, sondern die Anzahl der Bits zählt, die sowohl über den User-Port als auch über den Kassetten-Port geleitet werden. Das dient dem Betriebssystem dazu, zu wissen, wann ein volles Wort abgearbeitet worden ist. |
Bit counter during RS232 input. | RS-232 rcvr bit count in | RS-232 Input Bit Count / Cassette Temp | RS232 Input Bit count/Tape temporary. | Tp Wrt new byte/Rd error/inbit cnt | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RER | Cassette: flags errors (if Z then no error) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00A9 | RINONE | 169 |
RS-232 Flag: Check for Start BitThis flag is used when checking for a start bit. A 144 ($90) here indicates that no start bit was received, while a 0 means that a start bit was received. |
RS232-Flagge für Startbit-PrüfungEin RS232-Datentransfer prüft, ob ein Start-Bit empfangen worden ist. Im positiven Fall steht in Zelle 169 die Zahl 144, im negativen Fall eine 0. |
Stop bit switch during RS232 inputValues:
|
RS-232 rcvr flag for start bit check | RS-232 Flag: Check for Start Bit | RS232 Flag: Start Bit check/Tape temporary. | Wrt start bit/Rd bit err/stbit | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
REZ | Cassette: counts zeros (if Z then correct # of dipoles) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00AA | RIDATA | 170 |
RS-232 Input Byte Buffer/Cassette Temporary StorageSerial routines use this area to reassemble the bits received into a byte that will be stored in the receiving buffer pointed to by 247 ($F7). Tape routines use this as a flag to help determine whether a received character should be treated as data or as a synchronization character. |
RS232-Eingabe- und Zwischenspeicher für Kassetten-RoutinenBei der Speicherzelle 165 haben wir gesehen, daß ein Band Synchronisationsbits enthält. Die Speicherzelle 170 wird dabei als Flagge benutzt, die angibt, ob ein gelesenes Zeichen Synchronisierungs-Bits oder ein Datenwort darstellt. Die RS232-Routinen verwenden Zelle 17 0 dagegen als Speicher, in welchem die eingelesenen Bits zu einem Byte zusammengefaßt werden, bevor sie im Eingabepuffer am oberen Ende des Programmspeichers abgelegt werden (siehe auch Speicherzellen 55/56). |
Byte buffer during RS232 input. | RS-232 rcvr byte buffer | RS-232 Input Byte Buffer/Cassette Temp | RS232 Input Byte Buffer/Tape temporary. | Tp Scan; Cnt; Ld; End/byte assy | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RDFLG |
Cassette: holds function modeMI - waiting for block SYNC VS - in data block reading data NE - waiting for byte SYNC |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00AB | RIPRTY | 171 |
RS-232 Input Parity/Cassete Leader CounterThis location is used to help detect if data was lost during RS-232 transmission, or if a tape leader is completed. |
Quersummenprüfung und Zähler für Band-Header bei RS232- und Kassetten-OperationenDiese Speicherzelle wird vom Betriebssystem benutzt, um festzustellen, ob während einer RS232-Datenübertragung Bits verloren gingen. Da derartige Prüfungen mit Parity-Bits (Quersummenprüfung) des öfteren erwähnt werden, gebe ich eine kurze Beschreibung des Prüfprinzips im Texteinschub 18 »Fehlererkennung mit Parity-Bits«. Zusätzlich wird in 171 die Länge des Band-Vorspanns bei seiner Erzeugung gezählt. |
Parity during RS232 input. Computed block checksum during datasette input. |
RS-232 rcvr parity storage | RS-232 Input Parity / Cassette Short Cnt | RS232 Input parity/Tape temporary. | Wr lead length/Rd checksum/parity | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SHCNH | Cassette: short cnt; left over from debugging | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00AC-$00AD | 172-173 |
Pointer to the Starting Address of a Load/Screen ScrollingThe pointer to the start of the RAM area to be SAVEd or LOADed at 193 ($C1) is copied here. This pointer is used as a working version, to be increased as the data is received or transmitted. At the end of the operation, the initial value is restored here. Screen management routines temporarily use this as a work pointer. |
Zeiger auf die Anfangsadresse für Ein-/Ausgabe, Zwischenspeicher für den BildschirmeditorIn den Speicherzellen 193 und 194 steht ein Zeiger, der auf die Adresse im Programmspeicher zeigt, wo das Programm beginnt beziehungsweise beginnen soll, welches abgespeichert beziehungsweise geladen werden soll. Dieser Zeiger wird am Anfang einer Lade- oder Abspeicher-Operation in die Zellen 172 und 173 gebracht, wo er während der Operation laufend erhöht wird, bis das Ende des Programms erreicht ist; dann wird er wieder auf seinen ursprünglichen Wert gesetzt. Der Zeiger dient außerdem noch dem Bildschirmeditor als Zwischenspeicher während des Scrollens (Hochschieben) des Bildschirms und beim Einfügen zusätzlicher Zeilen. Dieser Zeiger kann sehr nützlich sein, um Programme entweder schon beim SAVEn oder aber erst beim LOADen gezielt auf andere als ursprünglich verwendete Speicherbereiche zu bringen. Dazu sind aber noch einige andere Zellen notwendig, bis hin zu dem schon erwähnten Zeiger in 193 und 194. |
Zeiger für Bandpuffer und ScrollingDiese Speicherzellen dienen in erster Linie als Zeiger auf die Adresse, ab welcher ein Programm geladen oder gespeichert werden soll. Zweitens dienen sie auch als Zwischenspeicher während des Scrollings des Video-RAM und beim Einfügen zusätzlicher Zeilen. |
Start address for SAVE to serial bus. Pointer to current byte during SAVE to serial bus or datasette. Pointer to line in screen memory to be scrolled during scrolling the screen. |
Pointer: Tape Buffer/ Screen Scrolling | Pointer: Tape Buffer/Screen scrolling. | Pointer : tape bufr, scrolling | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00AC | SAL | 172 | Cassette: indirect to data storage area | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00AD | SAH | 173 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00AE-$00AF | 174-175 |
Pointer to Ending Address of Load (End of Program)This location is set by the Kernal routine SAVE to point to the ending address for SAVE, LOAD, or VERIFY. |
Zeiger auf die Endadresse für Ein-/Ausgabe, Zwischenspeicher für den BildschirmeditorDieser Zeiger ist der Zwilling zu 172 und 173, nur zeigt er seinerseits auf die letzte Adresse des zu bewegenden Programms. |
Load address read from input file and pointer to current byte during LOAD/VERIFY from serial bus. End address after LOAD/VERIFY from serial bus or datasette. End address for SAVE to serial bus or datasette. Pointer to line in Color RAM to be scrolled during scrolling the screen. |
Tape End Addresses/End of Program | Tape End Address/End of Program. | Tape end adds/End of program | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00AE | EAL | 174 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00AF | EAH | 175 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B0-$00B1 | 176-177 |
ZeitkonstanteDer Wert in dieser Speicherzelle wird verwendet, um die Zeitkonstante zum Lesen vom Band in der Zelle 146 einzustellen. |
Zeitkonstante beim Lesen von BandDer Wert in den Speicherzellen wird benutzt, um die Zeitkonstante beim Lesen von Band einzustellen. |
Unknown. | Tape Timing Constants | Tape timing Constants. | Tape timing constants | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B0 | CMP0 | 176 | Cassette: software servo (+/- adjust to time calcs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B1 | TEMP | 177 | Cassette: used to hold dipole time during type calculations | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B2-$00B3 | TAPE1 | 178-179 |
Zeiger auf den Kassetten-PufferBeim Einschalten des Computers werden diese Speicherzellen in Low-/High-Byte- Darstellung auf die Anfangsadresse des Kassetten-Puffers gesetzt. Beim VC 20 und C 64 ist dies die Adresse 828 ($033C). Durch Verbiegen dieses Zeigers kann der Kassettenpuffer auf beliebige Plätze des Speichers, aber nicht unterhalb der Adresse 512 verschoben werden. Das kann durchaus sinnvoll sein, um im Kassettenpuffer abgelegte Maschinenprogramme vor Überschreiben durch Kassettenoperationen zu schützen. |
Zeiger auf BandpufferDiese beiden Speicherzellen zeigen auf den Bandpuffer ($033C) |
Pointer to datasette buffer.Default: $033C, 828. |
Address of tape buffer #1y. | Pointer: Start of Tape Buffer | Pointer: Start Address of Tape Buffer ($033C). | Pntr : start of tape buffer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B4 | BITTS | 180 |
RS-232 Output Bit Count/Cassette Temporary StorageRS-232 routines use this to count the number of bits transmitted, and for parity and stop bit manipulation. Tape load routines use this location to flag when they are ready to receive data bytes. |
RS232-Bit-Zähler und -Zwischenspeicher für Kassetten-OperationenDie RS232-Routinen verwenden die Speicherzelle 180, um die Zahl der übertragenen Bits zu zählen, außerdem für Parity-Berechnung (siehe Texteinschub 18) und Stop-Bit-Bearbeitung. Die Lade-Routinen für Kassettenbetrieb benutzen diese Zelle als Flagge, die angibt, ob der Computer bereit ist, Daten zu übernehmen. |
Bitzähler für BandHier wird die Anzahl der übertragenden Bits gezählt. |
Bit counter and stop bit switch during RS232 outputBits:
Bit counter during datasette input/output. |
RS-232 trns bit count | RS-232 Out Bit Count / Cassette Temp | RS232 Write bit count/Tape Read timing Flag. | l = Tp timer enabled; bit count | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
SNSW1 | Cassette: flags if we have byte SYNC (a longlong) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B5 | NXTBIT | 181 |
RS-232 Next Bit to Send/Tape EOT FlagThis location is used by the RS-232 routines to hold the next bit to be sent, and by the tape routines to indicate what part of a block the read routine is currently reading. |
RS232-Anzeige für nächstes Bit, Flagge für End-of-TapeBei RS232-Operationen enthält die Zelle 181 das jeweils nächste Bit, welches übertragen werden soll. Bandoperationen entnehmen dieser Speicherzelle, welcher Block gerade gelesen wird. |
nächstes Bit für RS-232Diese Speicherzelle enthält immer das nächste Bit, das bei RS-232 Operationen übertragen werden soll. |
Bit buffer (in bit #2) during RS232 output. | RS-232 trns next bit to be sent | RS-232 Next Bit to Send/ Tape EOT Flag | RS232 Next Bit to send/Tape Read - End of Tape. | Tp EOT/RS232 next bit to send | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
DIFF | Cassette: used to preserve SYNO (outside of bit routines) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B6 | RODATA | 182 |
RS-232 Output Byte BufferRS-232 routines use this area to disassemble each byte to be sent from the transmission buffer pointed to by 249 ($F9). |
Ausgabe-Zwischenspeicher für RS232 und KassetteBei Ausgabe von Daten über die RS232-Schnittstelle wird jedes Byte in seine Einzelteile zerlegt, bevor es über den Ausgabepuffer seriell übertragen wird. DerAusgabepufferwird im obersten Teil des Programmspeichers angelegt (siehe auch Speicherzellen 55 und 56); die genaue Anfangsadresse steht in Speicherzelle 248. Auch die Ausgabe von Daten auf die Kassette verwendet Zelle 182 als Ausgabe-Zwischenspeicher. |
Puffer für auszugebendes ByteDieses Register wird als Ausgabezwischenspeicher benutzt. |
Byte buffer during RS232 output. | RS-232 trns byte buffer | RS-232 Out Byte Buffer | RS232 Output Byte Buffer/Tape Read Error Flag. | Read character error/outbyte buf | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PRP | Cassette: has combined error values from bit routines | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B7 | FNLEN | 183 |
Length of Current FilenameThis location holds the number of characters in the current filename. Disk filenames may have from 1 to 16 characters, while tape filenames range from 0 to 187 characters in length. If the tape name is longer than 16 characters, the excess will be truncated by the SEARCHING and FOUND messages, but will still be present on the tape. This means that machine language programs meant to run in the cassette buffer may be saved as tape filenames. A disk file is always referred to be a name, whether full or generic (containing the wildcard characters * or ?). This location will always be greater than 0 if the current file is a disk file. Tape LOAD, SAVE, and VERIFY operations do not require that a name be specified, and this location can therefore contain a 0. If this is the case, the contents of the pointer to the filename at 187 will be irrelevant. An RS-232 OPEN command may specify a filename of up to four characters. These characters are copied to locations 659-662 ($0293-$0296), and determine baud rate, word length, and parity. |
Länge des derzeitigen File-NamensDie LOAD-, SAVE- und VERIFY-Befehle für Disketten verlangen die Angabe eines Programm- oder Dateinamens, auf Computerdeutsch »File-Name«. Nähere Angaben dazu finden Sie im Texteinschub Nr. 19 »Files - Geräte - Namen - Nummern«. Auch der OPEN-Befehl kann einen File-Namen haben. Bei Kassettenoperationen kann der File-Name weggelassen werden. In der Speicherzelle 183 steht während und nach der Verwendung eines der oben genannten Befehle eine Zahl, die angibt, aus wie vielen Zeichen der File-Name besteht. Bei Disketten sind File-Namen möglich, die aus maximal 16 Zeichen bestehen. Bei Kassetten dagegen sind Namenslängen von maximal 187 Zeichen erlaubt. Allerdings werden vom Computer auf dem Bildschirm nur 16 Zeichen ausgedruckt (siehe dazu den Texteinschub 20 »Tape-Header«). Für die Längenangabe in Zelle 183 gilt dabei nur die Anzahl derjenigen Zeichen, die zwischen den Gänsefüßchen stehen. Diese Zahl kann nach einer Ein-/Ausgabeoperation, auch nach einer ungültigen oder abgebrochenen, durch PEEK (183) ausgelesen werden. Ein File-Name wird übrigens auch bei einem OPEN-Befehi der RS232-Schnittstelle angegeben. Dieser Name, der bis zu vier Zeichen lang sein kann, wird in die Speicherzellen 659 bis 662 übertragen und gibt dort die Übertragungsrate, Wortlänge und Parity-Prüfung an. |
Länge des FilenamensIn dieser Speicherzelle wird angegeben, aus wie vielen Zeichen der Filename besteht. |
Length of file name or disk command; first parameter of LOAD, SAVE and VERIFY or fourth parameter of OPENValues:
|
Length current file n str | Length of Current File Name | Number of Characters in Filename. | # characters in file name | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B8 | LA | 184 |
Current Logical File NumberThis location holds the logical file number of the device currently being used. A maximum of five disk files, and ten files in total, may be open at any one time. File numbers range from 1 to 255 (a 0 is used to indicate system defaults). When printing to a device with a file number greater than 127, an ASCII linefeed character will be sent following each carriage return, which is useful for devices like serial printers that require linefeeds in addition to carriage returns. The BASIC OPEN command calls the Kernal OPEN routine, which sets the value of this location. In the BASIC statement OPEN 4,8,15, the logical file number corresponds to the first parameter 4. |
Nummer der derzeitigen Datei (File)Hinter jedem OPEN-Befehl steht eine Zahl, die der durch diesen Befehl angefangenen Datei zugeordnet wird. Diese Datei- oder File-Nummer gilt als Referenz für alle anderen Ein- und Ausgabebefehle derselben Datei. Nähere Angaben dazu können Sie dem Texteinschub Nr. 19 »Files - Geräte - Namen - Nummern« entnehmen. Ein OPEN-Befehl ruft die entsprechende Routine des Betriebssystems auf, welche die File-Nummer in die Speicherzelle 184 schreibt. Von dort kann sie mit PEEK(184) ausgelesen werden. Geben Sie die folgende Zeile direkt ein:
Um verschiedene File-Nummern auszuprobieren, definieren wir sie als Variable A. Nach dem »A« des OPEN-Befehls steht die Zahl 3. Damit wird der Bildschirm angewählt (siehe »Sekundär-Adresse« im schon erwähnten Texteinschub). Das Anwählen des Bildschirms vermeidet eine störende Meldung des Betriebssystems. Mit RETURN nach der obenstehenden Zeile wird der jeweilige Wert von A als Inhalt der Zelle 184 ausgedruckt. |
logische FilenummerIn dieser Speicherzelle wird die logische Filenummer verzeichnet. |
Logical number of current file. | Current file logical addr | Current Logical File Number | Current File - Logical File number. | Current logical file | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00B9 | SA | 185 |
Current Secondary AddressThis location holds the secondary address of the device currently being used. The range of valid secondary address numbers is 0 through 31 for serial devices, and 0 through 127 for other devices. Secondary device numbers mean something different to each device that they are used with. The keyboard and screen devices ignore the secondary address completely. But any device which can have more than one file open at the same time, such as the disk drive, distinguishes between these files by using the secondary address when opening a disk file. Secondary address numbers 0, 1, and 15-31 have a special significance to the disk drive, and therefore device numbers 2-14 only should be used as secondary addresses when opening a disk file. OPENing a disk file with a secondary address of 15 enables the user to communicate with the Disk Operating System through that channel. A LOAD command which specifies a secondary address of 0 (for example, LOAD "AT BASIC",8,0) results in the program being loaded not to the address specified on the file as the starting address, but rather to the address pointed to by the start of BASIC pointer (43, $2B). A LOAD with a secondary address of 1 (for example, LOAD "HERE",8,1) results in the contents of the file being loaded to the address specified in the file. A disk file that has been LOADed using a secondary address of 1 can be successfully SAVEd in the same manner (SAVE "DOS 5.1",8,1). LOADs and SAVEs that do not specify a secondary address will default to a secondary address of 0. When OPENing a Datasette recorder file, a secondary address of 0 signifies that the file will be read, while a secondary address of 1 signifies that the file will be written to. A value of 2 can be added to indicate that an End of Tape marker should be written as well. This marker tells the Datasette not to search past it for any more files on the tape, though more files can be written to the tape if desired. As with the disk drive, the LOAD and SAVE commands use secondary addresses of 0 and 1 respectively to indicate whether the operation should be relocating or nonrelocating. When the 1515 or 1525 Printer is opened with a secondary address of 7, the uppercase/lowercase character set is used. If it is openend with a secondary address of 0, or without a secondary address, the uppercase/graphics character set will be used. |
Derzeitige Sekundär-AdresseDie Sekundär-Adresse steht als dritte Angabe hinter den Ein- und Ausgabe- Befehlen LOAD, SAVE, VERIFY und OPEN. Sie hat bei den verschiedenen Peripheriegeräten spezielle Funktionen. Diese Funktionen sind im Texteinschub 19 näher erläutert. Der jeweilige Wert der Sekundär-Adresse steht in der Speicherzelle 185, allerdings um 96 erhöht. Für Sekundär-Adressen stehen, über die Standardwerte der einzelnen Peripheriegeräte hinaus, die Zahlen von 0 bis 31 zur Verfügung. Ab 32 fängt in Zelle 185 wieder der Zyklus ab 0 an. Das können wir uns anschauen. Ich wähle zur Eröffnung einer Datei wieder den Bildschirm als »nicht-störendes« Empfangsgerät.
Durch Verändern des Wertes von A können Sie alle Möglichkeiten durchspielen. |
SekundäradresseHier steht die jeweilige Sekundäradresse. |
Secondary address of current file. | Current file 2nd addr | Current Secondary Address | Current File - Secondary Address. | Current secndy address | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00BA | FA | 186 |
Current Device NumberThis location holds the number of the device that is currently being used. Device number assignments are as follows:
|
Derzeitige Geräte-NummerJedes an den Computer anschließbare Gerät hat eine eigene Nummer, die zusammen mit den Ein-/Ausgabe-Befehlen LOAD, SAVE, VERIFY und OPEN angegeben werden muß. Wird keine Nummer angegeben, nimmt der Computer automatisch an, daß die Datasette gemeint ist. Alle von Commodore vorgegebenen Geräte-Nummern sind in der folgenden Tabelle 5 aufgelistet.
Tabelle 5. Von Commodore vorgegebene Geräte-Nummern Die normale Geräte-Nummer eines Druckers ist 4, die eines Disketten-Laufwerks 8. Die zusätzlichen Nummern müssen gesondert am betreffenden Gerät eingestellt werden. Nach der Ausführung eines der oben genannten Befehle steht die entsprechende Geräte-Nummer in der Speicherzelle 186, aus der sie mit PEEK(186) ausgelesen werden kann. |
GerätenummerEntsprechend ist auch in dieser Speicherzelle die Gerätenummer zu finden. |
Device number of current file. | Current file primary addr | Current Device Number |
Current File - First Address (Device number). OPEN LA,FA,SA; OPEN 1,8,15,"I0":CLOSE 1 |
Current device | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00BB-$00BC | FNADR | 187-188 |
Pointer: Current FilenameThis location holds a pointer to the address of the current filename. If an operation which OPENs a tape file does not specify a filename, this pointer is not used. When a disk filename contains a shifted space character, the remainder of the name will appear outside the quotes in the directory, and may be used for comments. For example, if you SAVE "ML[shifted space]SYS828", the directory entry will read "ML"SYS 828. You may reference the program either by the portion of the name that appears within quotes, or by the full name, including the shifted space. A program appearing later in the directory as "ML"SYS 900 would not be found just by reference to "ML", however. A filename of up to four characters may be used when opening the RS-232 device. These four characters will be copied to 659-662 ($0293-$0296), where they are used to control such parameters as baud rate, parity, and word length. |
Zeiger auf Adresse des derzeitigen File-NamensDie Bedeutung eines Programm- oder Dateinamens - normalerweise kurz »File-Name« genannt - ist im Texteinschub Nr. 19 »File - Geräte - Namen - Nummern« näher beschrieben. In den Speicherzellen 187 und 188 steht in der Low-/High-Byte- Darstellung ein Zeiger auf diejenige Adresse im Programm-Speicher, wo dieser Name gespeichert ist. Eine Ausnahme ist hier der OPEN-Befehl der RS232-Schnittstelle. Ihr File-Name wird in die Speicherzellen 659 bis 662 gebracht, wo er verschiedene Parameter dieser Schnittstelle steuert. |
Zeiger auf FilenamenIn diesen Speicherzellen steht ein Zeiger, der in LOW- und HIGH-Byte- Darstellung auf den Filenamen zeigt. |
Pointer to current file name or disk command; first parameter of LOAD, SAVE and VERIFY or fourth parameter of OPEN. | Addr current file name str | Pointer: Current File Name | Pointer: Current File name Address. | Pointer to file name | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00BD | ROPRTY | 189 |
RS-232 Output Parity/Cassette Temporary StorageThis location is used by the RS-232 routines as an output parity work byte, and by the tape as temporary storage for the current character being read or sent. |
Zwischenspeicher für RS232-Parity-Prüfung und für KassettenoperationenDie RS232-Routinen benutzen diese Speicherzellen als Zwischenspeicher für ein Prüf-Byte (Parity-Prüfung) bei der Ausgabe. Die Parity-Prüfung habe ich kurz im Texteinschub Nr. 18 erklärt. Auch die Kassetten-Routinen bedienen sich dieser Speicherzelle. Sie verwenden sie als Zwischenspeicher für das gerade gesendete oder empfangene Zeichen. |
Arbeitsspeicher serielle Ein-/AusgabeHier wird von den RS-232-Routinen ein Prüfbyte abgelegt (Parity-Prüfung). |
Parity during RS232 output. Byte buffer during datasette input/output. |
RS-232 trns parity buffer | RS-232 Out Parity / Cassette Temp | RS232 Output Parity/Tape Byte to be Input or Output. | Wr shift word/Rd input char | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
OCHAR | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00BE | FSBLK | 190 |
Cassette Read/Write Block CountUsed by the tape routines to count the number of copies of a data block remaining to be read or written. |
Blockzähler für Kassetten-Ein-/AusgabeDas Betriebssystem des Computers schreibt bei SAVE ein Programm zweimal auf das Band der Datasette. Beim LOAD-Befehl wird der erste Block in den Arbeitsspeicher des Computers geladen; der zweite - identische - Block wird dann mit dem ersten Block Byte für Byte verglichen, um Datenfehler auf dem nicht immer ganz zuverlässigen Bandmaterial zu erkennen. In derSpeicherzelle 190 wird dem Betriebssystem angezeigt, wie viele Blockteile bei diesem Prozeß noch gelesen oder gespeichert werden müssen. Vom Basic- Programm aus ist diese Speicherzelle nicht zugänglich. |
Passzähler für BandIn dieser Speicherzelle ist angegeben, wie viele Blockteile von Band gelesen oder auf Band geschrieben werden sollen. |
Block counter during datasette input/output. | Cassette: indicate which block we're looking at (0 to exit) | Cassette Read / Write Block Count | Tape Input/Output Block count. | # blocks remaining to Wr/Rd | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00BF | MYCH | 191 |
Tape Input Byte BufferThis is used by the tape routines as a work area in which incoming characters area assembled. |
Zwischenspeicher für LOAD-Operationen vom BandDiese Speicherzelle wird beim Laden eines Programms vom Band dazu benutzt, um Zeichen aus einzelnen Bits zusammenzusetzen. |
Puffer für serielle AusgabeBeim Laden eines Programms von Band wird diese Speicherzelle dazu benutzt, um die einzelnen Bits zu einem Byte zusammenzusetzen. |
Unknown. | Cassette: holds input byte being built | Serial Word Buffer | Serial Word Buffer. | Serial word buffer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C0 | CAS1 | 192 |
Tape Motor InterlockThis location is maintained by the IRQ interrupt routine that scans the keyboard. Whenever a button is pressed on the recorder, this location is checked. If it contains a 0, the motor is turned on by setting Bit 5 of location 1 to 0. When the button is let up, the tape motor is turned off, and this location is set to 0. Since the interrupt routine is executed 60 times per second, you will not be able to keep the motor bit set to keep the motor on if no buttons are pushed. Likewise, if you try to turn the motor off when a button is pressed and this location is set to 0, the interrupt routine will turn it back on. To control the motor via software, you must set this location to a nonzero value after one of the buttons on the recorder has been pressed. |
Motorsperre der DatasetteDie Tasten der Datasette werden 60mal in der Sekunde von der »Interrupt- Routine« des Betriebssystem überprüft, ob eine von ihnen gedrückt worden ist. Die Speicherzelle 192 spielt dabei eine entscheidende Rolle, beim C 64 allerdings in einer anderen Weise als beim VC 20. Wie sie diese Rolle beim C 64 spielt, ist im Zusammenhang mit der Speicherstelle 1 ganz am Anfang dieses Kurses beschrieben worden. Ich habe dabei in zwei Beispielen gezeigt, wie durch Abfrage des vierten Bits von Adresse 1 geprüft werden kann, ob eine Taste der Datasette gedrückt ist und wie der Motor durch Setzen und Löschen des Bit 5 der Zelle 1 ein- und ausgeschaltet werden kann. Vorausgesetzt, der Inhalt der Speicherzelle 192 ist ungleich Null und eine Taste der Datasette ist gedrückt. Nun will ich, wie versprochen, denselben Vorgang für den VC 20 beschreiben. Wie Sie sich vielleicht noch erinnern, wird die Speicherzelle 1 beim VC 20 nicht für die Steuerung der Ein- und Ausgänge des Mikroprozessors verwendet. Diese Rolle wird beim VC 20 durch zwei Register des »Versatile Interface Adapter« (VIA 6522-A) ausgefüllt. Für die Abfrage der Datasetten-Tasten ist das sechste Bit des VIA-Registers 37151 zuständig. Bei gedrückter Taste steht es auf 1, sonst auf 0. Ein kleines Programm zeigt es Ihnen:
Wenn keine Taste gedrückt ist, läuft ein Zahlenband mit 126 ab. Die entsprechende Darstellung als Dualzahl lautet 1111 1110. Bei einer gedrückten Taste steht in 37151 die Zahl 62, als Dualzahl 0011 1110. Wichtig, wie gesagt ist nur das zweithöchste Bit. Mit der Abfrage der Zeile 30 springt beim Drücken einer Taste das Programm auf die Zeile 50 und druckt den Text aus. Den Motor der Datasette können wir mit Hilfe des Registers 37184 schalten. Wie beim C 64 gilt auch jetzt, daß dazu die hier angesprochene Speicherzelle 192, auch Interlock-Register genannt, eine Zahl größer als 0 enthält und daß außerdem eine Taste der Datasette gedrückt ist. Drücken Sie auf PLAY und geben Sie direkt ein:
Bestimmend sind hier Bit 2, 3 und 4. Zum Ausschalten muß lediglich Bit 2 auf 1 stehen, zum Einschalten die drei Bits auf 110. Jede Zahl, die als Dualzahl diese Bedingungen erfüllt, kann dafür hergenommen werden. Um unabhängig von den anderen Bits des Registers 37148 zu bleiben, die ja auch ganz bestimmte andere Funktionen haben, empfiehlt es sich, über Boole’sche Verknüpfungen nur die wichtigen drei Bits zu verändern. Die beiden POKE-Befehle sehen dann so aus: Ausschalten:
Einschalten:
|
Flag für BandmotorDer Motor der Datasette kann nur eingeschaltet werden, wenn die Speicherzelle ungleich Null ist. |
Datasette motor switchValues:
|
Cassette manual/controlled switch | Tape Motor Interlock | Tape Motor Switch. | Tape motor interlock | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C1-$00C2 | STAL | 193-194 |
I/O Start AddressThis location points to the beginning address of the area in RAM which is currently being LOADed or SAVEd. For tape I/O, it will point to the cassette buffer, and the rest of the data is LOADed or SAVEd directly to or from RAM. This location points to the beginning address of the area of RAM to be used for the blocks of data that come after the initial header. |
Anfangsadresse für Ein-/Ausgabe-OperationenIn diesen Speicherzellen steht in Low-/High-Byte-Darstellung die Adresse, ab der ein Programm gerade geladen oder gespeichert wird. Diese Adresse wird übrigens von hier auch in die Speicherzellen 172 und 173gebracht, die wir schon früher besprochen haben. Bei LOAD und SAVE auf Band steht hier die Anfangsadresse des Bandpuffers (828). Im Bandpuffer steht allerdings nur der sogenannte Bandvorspann (auf englisch »Tape Header«), während der Hauptteil des Programms im Programmspeicher ab einer Adresse steht, auf die der Zeiger in den Speicherzellen 195 und 196 hinweist. |
Startadresse für Ein-/AusgabeIn diesen Registern ist in LOW- und HIGH-Byte-Darstellung angegeben, ab welcher Adresse ein Programm geladen oder gespeichert wird. |
Start address during SAVE to serial bus, LOAD and VERIFY from datasette and SAVE to datasette. Pointer to current byte during memory test. |
I/O Start Address | Start Address for LOAD and Cassette Write. | I/O start address | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C1 | TMP0 | 193 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
STAL | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C2 | STAH | 194 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C3-$00C4 | MEMUSS | 195-196 |
Zeiger auf den Anfang des Programms hinter dem Tape HeaderBei jedem LOAD- und SAVE-Befehl für Kassetten wird der Vorspann (Tape Header), in dem Programmtyp, Anfangs- und Endadresse aufgezeichnet sind, im Kassettenpuffer ab Adresse 828 gespeichert. Der eigentliche Teil des Programms steht dann im Programmspeicher. In den Speicherzellen 195 und 196 steht in der Low-/High-Byte-Darstellung diese Adresse, ab der das Programm beginnt. Ich habe für alle diejenigen, die mit der Datasette arbeiten, im Texteinschub Nr. 20 »Tape-Header« die Zusammenhänge mit einem Beispiel dargestellt. |
Endadresse für Ein-/AusgabeHier steht in LOU- und HIGH-Byte der Zeiger auf den Tape-Header im Bandpuffer. |
Start address for a secondary address of 0 for LOAD and VERIFY from serial bus or datasette. Pointer to ROM table of default vectors during initialization of I/O vectors. |
Cassette load temps (2 bytes) | Tape Load Temps | Pointer: Type 3 Tape LOAD and general use. | Kernel setup pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TMP2 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C5 | LSTX | 197 |
Matrix Coordinate of Last Key Pressed, 64=None PressedDuring every normal IRQ interrput this location is set with the value of the last keypress, to be used in keyboard debouncing. The Operating System can check if the current keypress is the same as the last one, and will not repeat the character if it is. The value returned here is based on the keyboard matrix values as set forth in the explanation of location 56320 ($DC00). The values returned for each key pressed are shown at the entry for location 203 ($CB). |
Tasten-Code der zuletzt gedrückten TasteBei der Behandlung der Speicherzelle 145 habe ich Ihnen mit Wort und Bild beschrieben, wie die Tasten des Computers abgefragt werden. Die dabei für jede Taste entstehende Dualzahl wird in eine Dezimalzahl (0 bis 63) umgewandelt und zuerst in die Speicherzellen 203 beziehungsweise 653 gebracht. Zur Umwandlung und Abfrage der Zellen 203 und 653 bringe ich bei diesen Speicherzellen mehr Details. Nach der Prüfung, welche Taste gedrückt worden ist, wird die Codezahl von 203 in die Speicherzelle 197 gebracht und dort »aufgehoben«. Diese vermeintliche Verdoppelung wird vom Betriebssystem dafür gebraucht, um zu erkennen, ob die nächste gedrückte Taste mit der vorhergehenden identisch ist. Ist sie identisch, dann entscheidet der Inhalt der Speicherzelle 650, ob das Zeichen dieser Taste mehrfach ausgedruckt wird. In 650 steht die sogenannte Wiederholfunktion. Aber ich will nicht vorgreifen. Die Codezahlen der einzelnen Tasten werde ich bei der Besprechung der Zelle 203 auflisten. |
Nummer der gedrückten TasteHier wird die Nummer der gedrückten Taste gespeichert (64= keine Taste). |
Matrix code of key previously pressedValues:
|
Key scan index | Current Key Pressed: CHR$(n) 0 = No Key | Matrix value of last Key pressed; No Key = $40. | Last key pressed | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C6 | NDX | 198 |
Number of Characters in Keyboard Buffer (Queue)The value here indicates the number of charracters waiting in the keyboard buffer at 631 ($0277). The maximum number of characters in the keyboard buffer at any one time is determined by the value in location 649 ($0289), which defaults to 10. If INPUT or GET is executed while there are already characters in the buffer, those characters will be read as part of the data stream. You can prevent this by POKEing a 0 to this location before those operations, which will always cause any character in the buffer to be ignored. This technique can be handy when using the joystick in Controller Port #1, which sometimes causes fake keypresses to be registered, placing unwanted characters in the keyboard buffer. Not only is this location handy for taking unwanted characters out of the keyboard buffer, but it can also be used to put desired characters into the buffer, and thus to program the keyboard buffer. This technique (dynamic keyboard) allows you to simulate keyboard input in direct mode from a program. The dynamic keyboard technique is an extremely useful one, as it enables you to add, delete, or modify program lines while the program is running. The basic scheme is to POKE the PETASCII character values that you wish to be printed (including cursor control characters and carriage returns) into the buffer. Then, when an END statement is executed, the characters in the buffer will be printed, and entered by the carriage return. This technique can help with the problem of trying to use data separation and terminator characters with INPUT statements. If you try to INPUT a string that has a comma or colon, the INPUT will read only up to that character and issue an EXTRA IGNORED error message. You can avoid this by entering the input string in quotes, but this places on the user the burder of remembering the quote marks. One solution is to use the statements:
before the input. This will force two quote marks and a delete into the buffer. The first quote mark allows the comma or colon to be INPUT, the second is used to get the editor out of quote mode, and the delete removes that second quote. For more specific information and programming examples, see the description of location 631 ($0277), the keyboard buffer. |
Anzahl der Zeichen im TastaturpufferDie Funktion des Tastaturpuffers, zu dem wir bei den Speicherzellen 631 und 640 noch kommen werden, habe ich bereits in diesem Kurs, und zwar im Texteinschub Nr. 15 »Dynamische Tastenabfrage« erklärt. Dabei habe ich damals schon sozusagen im Vorgriff die Zelle 198 verwendet. In dieser Speicherzelle steht die jeweilige Anzahl der Zeichen, die im Tastaturpuffer gespeichert sind und darauf warten, weiterverarbeitet zu werden. Das folgende kleine Programm zeigt es.
Der GET-Befehl holt ein Zeichen aus dem Tastaturpuffer - sofern eines dort zu finden ist. Die Zeile 20 druckt die Anzahl derZeichen im Pufferaus, daneben das erste dieser Zeichen. Dann folgt eine Warteschleife, die uns erlaubt, ganz schnell ein paarTasten zu drücken. Danach springt das Programm an den Anfang zurück und arbeitet diese eingegebenen Zeichen ab. Es ist dabei deutlich zu sehen, wie durch den GET-Befehl bereits ein Zeichen aus dem Puffer genommen und dadurch der Inhalt der Zelle 198 sofort um 1 reduziert wird. Der Inhalt der Speicherzelle 198 kann mit POKE auch verändert werden. Eine sinnvolle Anwendung dieser Beeinflussung erlaubt der nicht gerade sehr populäre WAIT-Befehl. Ersetzen Sie bitte im obigen Programm die Warteschleife der Zeile 30 durch:
Zuerst wird dem Computer vorgegaukelt, daß der Tastaturpuffer leer sei. Durch den WAIT-Befehl wartet das Programm danach so iange, bis ein Zeichen im Tastaturpuffer erscheint und springt erst dann auf die nächste Zeile 40. Wenn Sie nach dem WAIT-Befehl statt der 1 eine 2 eingeben, wartet diese Zeile entsprechend auf zwei Tasteneingaben. Allerdings wird in der Zeile 20 dann nur jedes zweite Zeichen ausgedruckt. |
Anzahl der gedrückten TastenHier steht die jeweilige Anzahl der Zeichen, die im Tastaturpuffer gespeichert sind. |
Length of keyboard bufferValues:
|
Index to keyboard q | No. of Chars. in Keyboard Buffer (Queue) | Number of Characters in Keyboard Buffer queue. | # chars in keybd buffer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C7 | RVS | 199 |
Flag: Print Reverse Characters? 0=NoWhen the [CTRL][RVS-ON] characters are printer (CHR$(18)), this flag is set to 18 ($12), and the print routines will add 128 ($80) to the screen code of each character which is printed, so that the caracter will appear on the screen with its colors reversed. POKEing this location directly with a nonzero number will achieve the same results. You should remember, however, that the contents of this location are returned to 0 not only upon entry of a [CTRL][RVS-OFF] character (CHR$(146)), but also at every carriage return. When this happens, characters printed thereafter appear with the normal comination of colors. |
Flagge für reverse Darstellung der ZeichenNormalerweise steht in dieser Speicherzelle eine 0, was mit PRINT PEEK(199) leicht nach geprüft werden kann. Sobald in der Zelle 199 eine andere Zahl als 0 steht, werden alle Zeichen in der reversen Darstellung gedruckt. Das Betriebssystem des Computers erhöht nämlich in diesem Fall den jeweiligen Bildschirmcode der Zeichen um 128. Ein Blick in eine Tabelle der Biidschirmcodes bestätigt, daß die Codes aller reversen Zeichen um genau 128 höher sind als die der normalen Zeichen. Den reversen Modus können wir bekanntlich direkt mit der Kombination der CTRL- und der RVS-ON-Taste oder aber mit PRINT CHR$(18) herstellen. Wenn Sie aber versuchen sollten, das direkt einzugeben, um dann wieder mit PRINT PEEK(199) nachzuschauen, was jetzt in der Speicherzelle 199 steht, dann werden Sie Schiffbruch erleiden. Das Betriebssystem setzt den Inhalt der Zelle 199 nach einem »Wagenrücklauf«, hervorgerufen zum Beispiel durch die RETURN-Taste oder nach einem PRINT-Befehl, der nicht mit einem Komma oder Semikolon abgeschlossen ist, sogleich auf 0 zurück. Natürlich erfolgt das auch durch Drücken der CTRL- und RVS-OFF-Taste. Wir vermeiden die Rücksetzung durch einen Einzeiler:
Wir erhalten drei reverse As und als Inhalt der Zelle 199auch die Zahl 18. Dasselbe Ergebnis erhalten wir durch POKEn einer Zahl größer als 0 in die Zelle 199:
Das Ergebnis beweist, daß diese Adresse sehr nützlich sein kann, zumal ihre Abfrage beziehungsweise Beeinflussung auch innerhalb eines Programms erfolgen kann. |
Flag für RVS-ModusDiese Speicherzelle gibt an, ob die auszugebenden Zeichen revers oder normal dargestellt werden sollen (0= normal, 1= revers). |
Reverse mode switchValues:
|
RVS field on flag | Flag: Reverse Chars. - 1=Yes, 0=No Used | Flag: Reverse On/Off; On = $01, Off = $00. | Screen reverse flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C8 | INDX | 200 |
Pointer: End of Logical Line for InputThis pointer indicates the column number of the last nonblank character on the logical line that is to be input. Since a logical line can be up to 80 characters long, this number can range from 0-79. |
Zeiger auf das Ende der eingegebenen logischen ZelleEine echte Zeile faßt beim C 64 maximal 40 Zeichen, beim VC 20 nur 22. Eine Zeile mit Anweisungen darf beim C 64 insgesamt 80 Zeichen, beim VC 20 sogar 88 Zeichen enthalten. Diese »verlängerte« Programmzeile nennt man »logische Zeile«. Der Zeiger in Speicherzelle 200 gibt dem Betriebssystem an, auf welcher Position das letzte Zeichen einer eingegebenen logischen Zeile sitzt. Löschen Sie den Bildschirm und geben Sie direkt irgendwo auf dem Bildschirm den Befehl ein:
Sie erhalten die Zahl der Spalte des letzten Zeichens dieses Direkt-Befehls. |
Zeilenende für EingabeDieses Register enthält die Position des letzen Zeichens in einer Zeile. |
Length of line minus 1 during screen input. Values: $27, 39; $4F, 79. | Pointer: End of Logical Line for INPUT | Pointer: End of Line for Input (Used to suppress trailing spaces). | End-of-line for input pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C9-$00CA | 201-202 |
Cursor X,Y Position at Start of InputThese locations keep track of the logical line that the cursor is on, and its column position on that logical line (in line, column format). Each logical line may contain one or two 40-column physical lines. Thus there may be as many as 25 logical lines, or as few as 13 at any one time. Therefore, the logical line number might be anywhere from 1-25. Depending on the length of the logical line, the cursor column may be from 1-40 or 1-80. For a more detailed exaplanation of logical lines, see the description of the screen line link talbe, 217 ($D9). |
Zeiger auf Zeilen- und Spaltenposition des letzten Zeichens einer ZeileDiese beiden Speicherzellen werden bei GET und INPUT verwendet, um die Zeile und Spalte des letzten Zeichens einer eingegebenen Zeile festzustellen. Die Spalten (in Zelle 201 angegeben) zählen von 1 bis 40 (1 bis 22 beim VC 20). Die Zeilen (in Zelle 202 enthalten) zählen dagegen in Paaren von 0 bis 12, identisch mit der bei Zelle 200 erläuterten »logischen« Zweierzeile. Da dies nicht ganz einsichtig ist, gebe ich einen Bildschirmausschnitt wieder (Bild 20), der den Sachverhalt verdeutlichen soll. Der erste Direktbefehl steht in der zweiten Zeile, das letzte Zeichen in der Spalte 30. Der zweite Befehl steht in der ersten Sechserzeile. Das heißt also, daß die Zeilenangabe dieselbe ist, egal, um welchen Teil der logischen Zeile es sich handelt. Das können Sie leicht nachprüfen, indem Sie den ersten Direktbefehl eine Zeile höher schreiben. Das Resultat ist dasselbe. Die Unterscheidung, um welche der beiden Zeilenteile es sich handelt, wird in den Speicherzellen 217 bis 242 getroffen. Beim VC 20 sieht der Bildschirmausdruck etwas anders aus (Bild 21), auch die Befehlseingabe habe ich der Zeilenlänge wegen verändert. Interessant ist beim VC 20 allerdings, daß.dort trotz der Länge der logischen Zeile auch nur Zeilenpaare verwendet werden, deren Länge natürlich auf 22 Spalten reduziert ist. |
Cursor X-Y Pos. at Start of INPUT | Cursor X/Y (Line/Column) position at start of Input. | Input cursor log (row, column) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00C9 | LSXP | 201 |
Cursorzeile für EingabeDiese Speicherzelle dient dazu, um die Zeile des letzten eingegebenen Zeichens festzustellen. |
Cursor row during screen input. Values: $00-$18, 0-24. | X pos at start | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00CA | LSTP | 202 |
Cursorspalte für EingabeDiese Speicherzelle dient dazu, um die Spalte des letzten eingegebenen Zeichens festzustellen. |
Cursor column during screen input. Values: $00-$27, 0-39. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00CB | SFDX | 203 |
Matrix Coordinate of Current Key PressedThe keyscan interrupt routine uses this location to indicate which key is currently being pressed. The value here is then used as an index into the appropriate keyboard table to determine which character to print when a key is struck. The correspondence between the key pressed and the number stored here is as follows:
The RESTORE key is not accounted for, because it is not part of the normal keyboard matrix. Instead, it is connected directly to the microprocessor NMI line, and causes an NMI interrupt whenever it is pressed. |
Tastencode der gerade gedrückten TasteBei der Speicherzelle 145 habe ich beschrieben, wie die Tasten des Computers abgefragt werden. Die dabei für jede der 64 Tasten (mit Ausnahme der RESTORE- und der SHIFT-LOCK-Tasten) entstehende Dualzahl wird in eine Dezimalzahl (0 bis 63) umgewandelt und in der Speicherzelle 203 gespeichert, einige auch in der Zelle 653. Diese Zahl steht auch in Speicherzelle 197, um sie mit der vorher gedrückten Taste vergleichen zu können. Die Codezahlen jeder Taste lassen sich mit folgendem Programm abfragen:
Nach RUN sehen wir ein laufendes Zahlenband, zuerst mit der Zahl 64. Das ist die Codezahl für »keine Taste gedrückt«. Die X-Taste ergibt 23 (26 beim VC 20), die W-Taste ergibt 9. Auch die Funktionstasten haben ihren Tastencode. F1 ergibt 4 (39 beim VC 20) und so weiter. Nur die Steuertasten CTRL, SHIFT, und C= (Commodore-Taste) zeigen keine Reaktion. Deren Tastencode steht nämlich in Speicherzelle 653. Den Grund für diesen Separatismus erfahren Sie bei der Besprechung dieser Zelle. Hier ist nur interessant, daß nicht nur jede einzelne dieser drei Tasten einen eigenen Code hat, sondern auch alle machbaren Kombinationen von gleichzeitig gedrückten Steuertasten. Um das zu sehen, ändern Sie bitte die Zeile 10 so ab:
Tabelle 9 gibt Ihnen die volle Übersicht. Wenn Sie sich die Mühe machen, die Zahlenreihen der Zelle 203 auf Vollständigkeit zu prüfen, dann werden Sie feststellen, daß vier Zahlen fehlen. Es sind die Werte, die eigentlich den vier Steuertasten CTRL, C=, rechte und linke SHIFT-Taste zugewiesen sind. Aber wie gesagt, sie werden gleich nach 653 umgeleitet, wobei allerdings kein Unterschied mehr zwischen der linken und rechten SHIFT-Taste gemacht wird. Einige Anwendungsbeispiele der Tastencodes sowie der Kombinationen der drei Steuertasten finden Sie im Texteinschub Nr. 21 »Abfrage der Tastencodes«. Wie schon erwähnt, haben die RESTORE-Taste und die SHIFT-LOCK-Taste keinen eigenen Code. Die RESTORE-Taste ist überhaupt nicht an die Tastatur-Matrix angeschlossen, sondern ist direkt mit der RESTORE-Leitung des Computers verbunden. Dort löst sie einen sogenannten NMI-Interrupt aus. Die SHIFT-LOCK-Taste ist lediglich eine mechanische Verriegelung der SHIFT-Taste. |
gedrückte TasteHier steht der jeweilige Code der gedrückten Taste. (64= keine Taste). |
Matrix code of key currently being pressedValues:
|
SHIFT mode on print | Flag: Print Shifted Chars. | Flag: Print shifted Characters. | Which key : 64 if no key | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00CC | BLNSW | 204 |
Cursor Blink Enable: 0=Flash CursorWhen this flag is set to a nonzero value, it indicates to the routine that normally flashes the cursor not to do so. The cursor blink is turned off when there are characters in the keyboard buffer, or when the program is running. You can use this location to turn the cursor on during a program (for a series of GET operations, for example, to show the user that input is expected) by using the statement POKE 204,0. |
Schalter für Cursor blinkenEin Wert größer 0 in dieser Speicherzelle schaltet das Blinken des Cursors ab. Diese Abschaltung erfolgt durch das Betriebssystem immer dann, wenn sich Zeichen im Tastaturpuffer befinden und wenn ein Programm ausgeführt wird. Im folgenden Beispiel einer Eingabe mit dem GET-Befehl, bei dem bekannterweise der Cursor nicht blinkt, wird demonstriert, daß durch POKE 204,0 der Cursor trotzdem blinkt. Das kann für selbstgeschriebene Eingabe-Routinen interessant sein.
Umgekehrt kann man durch POKE 204,1 das Blinken des Cursors abschalten. Es bleibt dabei allerdings dem Zufall überlassen, ob er in der Einoder Aus-Phase abgeschaltet wird. Wenn Sie Pech haben, dann bleibt der Cursor bewegungslos stehen. |
Flag für CursorDer Cursor wird ausgeschaltet, wenn in dieser Speicherzelle ein größerer Wert als Null steht. |
Cursor visibility switchValues:
|
Cursor blink enab | Cursor Blink enable: 0 = Flash Cursor | Flag: Cursor blink; $00 = Enabled, $01 = Disabled. | 0 = flash cursor | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00CD | BLNCT | 205 |
Timer: Countdown to Blink CursorThe interrupt routine that blinks the cursor uses this location to tell when it's time for a blink. First the number 20 is put here, and every jiffy (1/60 second) the value here is decreased by one, until it reaches zero. Then the cursor is blinked, the number 20 is put back here, and the cycle starts all over again. Thus, under normal circumstances, the cursor blinks three times per second. |
Zähler für Blinkfrequenz des CursorsDas Blinken des Cursors besorgt die Interrupt-Routine. 60mal in jeder Sekunde unterbricht sie den normalen Programmablauf. Während dieser Zeit führt sie mehrere »Haushalt«-Arbeiten durch. So wird hier die Tastatur abgefragt und das Cursorblinken gesteuert. Dazu wird die Zahl 20 in die Speicherzelle 205 geschrieben und bei jeder Unterbrechung dann um 1 reduziert. Wenn die Zahl in 205 den Wert 0 erreicht hat, wird der Cursor eingeschaltet. Nach Adam Riese erfolgt das also 60/20 = 3mal pro Sekunde. Im Texteinschub Nr. 22 »Cursor-Spiele oder der INPUT-Befehl einmal etwas anders« wird mit diesem Zähler für die Blinkfrequenz experimentiert. |
Zähler für Cursor blinkenDiese Speicherzelle dient als Zähler für die Cursor-Blinkphase. Wenn der Wert 20 in dieser Speicherzelle abgezählt ist, wird der Cursor eingeschaltet. |
Delay counter for changing cursor phaseValues:
|
Count to toggle cur | Timer: Countdown to Toggle Cursor | Timer: Count down for Cursor blink toggle. | Cursor timing countdown | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00CE | GDBLN | 206 |
Character Under CursorThe cursor is formed by printing the inverse of the character that occupies the cursor position. If that characters is the letter A, for example, the flashing cursor merely alternates between printing an A and a reverse-A. This location keeps track of the normal screen code of the character that is located at the cursor position, so that it may be restored when the cursor moves on. |
Bildschirmcode des Zeichens unter dem CursorIm Prinzip ist der Cursor nichts anderes als das wiederholte Drucken eines Zeichens in reverser Form, das gerade unter dem Cursor steht. Normalerweise ist dies das Leerzeichen, deshalb sehen wir meistens das ausgefüllte Viereck. Fahren Sie aber mit dem Cursor auf einen Buchstaben, dann erscheint dieser wechselweise normal und revers. In Speicherzelle 206 steht jeweils der Bildschirmcode des Zeichens unter dem Cursor. Geben Sie die folgende Anweisung direkt ein, fahren aber noch vor dem Drücken der RETURN-Taste mit dem Cursor zurück auf eines der Zeichen, zum Beispiel auf ein P:
Nach RETURN erscheint die Zahl 16. Das ist also der Bildschirmcode des Zeichens, auf dem der Cursor saß, als die RETURN-Taste gedrückt wurde. Sie können das mit allen anderen Zeichen dieser Zeile wiederholen. Ich kann mir vorstellen, daß eine derartige Abfrage in einem Programm, welches mit dem Bildschirm arbeitet, sinnvoll sein kann. Die Speicherzelle 206 wird allerdings nach jedem Blinken auf den neuesten Stand gebracht. |
Zeichen unter dem CursorHier ist jeweils der Bildschirmcode eines Zeichens angegeben, das sich gerade unter dem Cursor befindet. |
Screen code of character under cursor. | Char before cursor | Character Under Cursor | Character under Cursor while Cursor Inverted. | Character under cursor | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00CF | BLNON | 207 |
Flag: Was Last Curson Blink on or off?This location keeps track of whether, during the current cursor blink, the character under the cursor was reversed, or was restored to normal. This location will contain a 0 if the character is reversed, and a 1 if the character is restored to its nonreversed status. |
Flagge für Blinkzustand des CursorsIn dieser Speicherzelle wird festgehalten, in welcher der beiden Blink-Phasen - normal oder revers - der Cursor sich gerade befindet. Eine 0 bedeutet reverses Zeichen, eine 1 bedeutet ein normales Zeichen. Die Abfrage innerhalb eines Basic-Programms funktioniert nicht. Denn die Interrupt-Routine steuert den Phasenwechsel. |
Flag für CursorIn diesem Register wird festgehalten, in welcher Blink-Phase sich der Cursor gerade befindet. |
Cursor phase switchValues:
|
On/off blink flag | Flag: Last Cursor Blink On/Off | Flag: Cursor Status; $00 = Off, $01 = On. | Cursor in blink phase | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D0 | CRSW | 208 |
Flag: Input from Keyboard or ScreenThis flag is used by the Kernal CHRIN (61783, $F157) routine to indicate whether input is available from the screen (3), or whether a new line should be obtained from the keyboard (0). |
Flagge für Eingabe von Tastatur oder BildschirmDiese Speicherzelle wird von einer Routine des Betriebssystems verwendet, die das jeweils nächste Zeichen in den Arbeitsspeicher holt. Für sie ist wichtig zu wissen, von welchem Eingabegerät dieses Zeichen geholt werden soll. Wenn in der Zelle 208 eine 0 steht, wird damit die Tastatur als Eingabegerät bestimmt. Das ist der Normalfall, mit dem wir per Tastendruck Zeichen auf den Bildschirm tippen. Sobald aber statt einem Zeichen die RETURN-Taste gedrückt wird, ändert sich der Inhalt der Speicherzelle 208. Die oben genannte Routine überträgt nämlich jetzt den Inhalt der Zelle 213, in welcher die Länge der derzeitigen logischen Zeile steht, nach 208. Dann holt sie das nächste Zeichen, allerdings nicht von der Tastatur, sondern vom Bildschirm, und zwar das erste Zeichen der gerade abgeschlossenen logischen Zeile. Auf diese Weise gelangen die Anweisungen einer Zeile in den Arbeitsspeicher, wo sie im Direkt-Modus sofort ausgeführt, im Programm-Modus aber gespeichert und erst nach RUN ausgeführt werden. Den Unterschied zwischen »logischer« und »echter« Zeile habe ich in dem Texteinschub Nr. 23 näher beschrieben. |
Flag für Eingabe von Tastatur oder BildschirmHier wird die Länge der zu übertragenden Zeichen gespeichert. |
End of line switch during screen inputValues:
|
INPUT vs GET flag | Flag: INPUT or GET from Keyboard | Flag: Input from Screen = $03, or Keyboard = $00. | Input from screen/from keyboard | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D1-$00D2 | PNT | 209-210 |
Pointer to the Address of the Current Screen LineThis location points to the address in screen RAM of the first column of the logical line upon which the cursor is currently positioned. |
Zeiger auf den Anfang der Bildschirmzeile, auf welcher der Cursor gerade stehtDieser Zeiger in Low-/High-Byte-Darstellung zeigt auf die Adresse im Bildschirmspeicher, in welcher diejenige Zeile beginnt, auf der der Cursor gerade steht. Das läßt sich leicht nachprüfen durch folgende Programmzeile:
Nach RUN wird erst der Bildschirm gelöscht, der Cursor in die HOME-Position gebracht und dann der Inhalt der beiden Zellen ausgedruckt. Da dies alles in der ersten Zeile passiert, sehen wir als Resultat eine 0 und eine 4. Die beiden Zahlen ergeben zusammen die Adresse, in der die erste Zeile des Bildschirmspeichers beginnt. Erweitern Sie die Zeile 10 um ein Komma und die Low-/High-Byte-Berechnung:
Jetzt sehen wir als Resultat:
Beim VC 20 erscheinen die der verwendeten Speichererweiterung entsprechenden Zahlen. Wir können durch einen TAB-Befehl den zweiten Teil der PRINT-Anweisung in die nächste Zeile schieben und sehen, was dann herauskommt:
Das Resultat ist jetzt:
Einen entsprechenden Zeiger für die Adresse der dazugehörigen Zeile im Farbspeicher werden wir in den Speicherzellen 243 und 244 antreffen. Durch POKEn können wir die Cursorposition leider nicht beeinflussen, aber Abfragen geht, wenn es uns interessiert. |
Zeiger auf Start der BildschirmzeileIn diesen Speicherzellen wird in LOW- und HIGH-Byte-Darstellung angezeigt, wo sich im Video-RAM die Zeile befindet, auf der der Cursor gerade steht. |
Pointer to current line in screen memory. | Pointer to row | Pointer: Current Screen Line Address | Pointer: Current Screen Line Address. | Pointer to screen line | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D3 | PNTR | 211 |
Cursor Column on Current LineThe number contained here is the cursor column position within the logical line pointed to by 209 ($D1). Since a logical line can contain up to two physical lines, this value may be from 0 to 79 (the number here is the value returned by the POS function). |
Position des Cursors innerhalb einer logischen ZeileDen Inhalt der Speicherzelle 211 könnte man auch die Spaltenposition des Cursors nennen, wenn es sich nicht um die Position in der logischen Zeile handelte (siehe Texteinschub Nr. 23). Beim C 64 sind daher die Werte von 0 bis 79, beim VC 20 von 0 bis 87 möglich. Diese Speicherzelle zusammen mit Zelle 214 wird von den Befehlen POS, TAB, SPC und vom Komma innerhalb einer PRINT-Anweisung verwendet, um den Cursor zu positionieren. Das können wir auch. Um den Cursor auf Platz 5 in der Bildschirmzeile 18 zu bringen, geben wir folgende Programmzeile ein:
Aus innerbetrieblichen Gründen muß der Wert, den wir als Zeile erzielen wollen, um 1 verringert in die Zelle 214 gePOKEt werden. Mit der Zahl 17 wird also der Cursor zuerst auf die Zeile 18 gebracht, dann in Spalte 5, ab der dann das Wort »C 64« gedruckt wird. Auf diese Weise erhalten wir einen Befehl, der in anderen Basic-Formen unter dem Namen PRINT AT sehr verbreitet ist, der bei den kleinen Commodore-Computern aber fehlt. Der Vorgang dabei besteht darin, daß die Inhalte von 211 und 214 in das X- Register beziehungsweise in das Y-Register des Mikroprozessors gebracht werden. Von dort können die Werte dann von einer Routine des Betriebssystems abgerufen werden. Das klingt alles sehr nach Maschinensprache. Aber wir haben Glück, denn sowohl die beiden Register als auch die besagte Routine sind von Basic aus ansprechbar. Das X-Register steht in Speicherzelle 781, das Y-Register in Speicherzelle 782, die Routine beginnt sowohl beim C 64 als auch beim VC 20 ab der Adresse 68634, wo wir sie mit dem SYS-Befehl starten können. Für unser Beispiel sieht das dann so aus:
Wir erhalten dasselbe Ergebnis, nur mit dem Unterschied, daß die Zeile jetzt wirklich die Zeile 18 ist. Mit dieser Methode ist jetzt auch die Zeile 0 erreichbar. Die Speicherzellen 781 und 782 bieten natürlich noch andere Anwendungen, auf die wir noch kommen werden. |
CursorspalteHier wird die Spaltenposition des Cursors festgehalten. |
Current cursor column. Values: $00-$27, 0-39. | Pointer to column | Cursor Column on Current Line | Cursor Column on current Line, including Wrap-round Line, if any. | Position of cursor on above line | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D4 | QTSW | 212 |
Flag: Editor in Quote Mode? 0=NoA nonzero value in this location indicates that the editor is in quote mode. Quote mode is toggled every time that you type in a quotation mark on a given line--the first quote mark turns it on, the second turns it off, the third turns it back on, etc. If the editor is in this mode when a cursor control character or other nonprinting character is entered, a printed equivalent will appear on the screen instead of the cursor movement or other control operation taking place. Instead, that action is deferred until the string is sent to the string by a PRINT statement, at which time the cursor movement or other control operation will take place. The exception to this rule is the DELETE key, which will function normally within quote mode. The only way to print a character which is equivalent to the DELETE key is by entering insert mode (see loctaion 216 ($D8)). Quote mode may be exited by printing a closing quote, or by hitting the RETURN or SHIFT-RETURN keys. Sometimes, it would be handy to be able to escape from quote mode or insert mode without skipping to a new line. The machine language program below hooks into the keyscan interrupt routine, and allows you to escape quote mode by changing this flag to 0 when you press the f1 key:
|
Flagge für Gänsefuß-ModusSteht in dieser Speicherzelle eine 0, dann befindet sich der Computer im Gänsefuß-Modus, andere Zahlen bedeuten den Normal-Modus. Selbst Anfängern ist der Gänsefuß-Modus sehr rasch geläufig, bietet er doch die Möglichkeit, Zeichen mit der PRINT-Anweisung auszudrucken. Genauso bekannt sind aber auch die Tücken der Gänsefüße. Die Cursor-Tasten reagieren nicht wie gewohnt. Auch die Farbumschaltung und andere Steuertasten zeigen nicht die übliche Wirkung, sondern drucken - allzu oft unerwartet - ein reverses Zeichen auf den Bildschirm. Eingeschaltet wird der Gänsefuß-Modus durch Drücken der geSHIFTeten 2-Taste oder der geSHIFTeten INST/DEL-Taste. Abgeschaltet wird er nach jedem 2., 4., 6., also nach jeder geradzahligen Wiederholung der Gänsefuß-Taste innerhalb einer Zeile. Abgeschaltet wird er auch durch die RETURN-Taste. Das spezielle Verhalten der Steuertasten zwischen Gänsefüßen läßt sich für faszinierende Effekte ausnutzen. Leider läßt sich der Inhalt der Speicherzelle 212 und damit der Status des Gänsefuß-Modus von Basic aus nicht beeinflussen. Doch in Maschinensprache unter Verwendung der Interrupt-Routine geht es, und einige Vorschläge zum Abschalten des Gänsefuß-Modus per Tastendruck sind schon veröffentlicht worden. |
Flag für HochkommamodusFalls in dieser Speicherzelle eine Null steht, dann befindet sich der Computer im Normalmodus. Andere Werte bewirken den Hochkommamodus. |
Quotation mode switchValues:
|
Quote switch | Flag: Editor in Quote Mode, $00 = NO | Flag: Editor in Quote Mode; $00 = Not. | 0 = direct cursor, else programmed | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D5 | LNMX | 213 |
Maximum Length of Physical Screen LineThe line editor uses this location when the end of a line has been reached to determine whether another physical line can be added to the current logical line, or if a new logical line must be started. |
Länge der BildschirmzeileIm Texteinschub 23 »Logische und echte Zeilen« ist der Unterschied zwischen den beiden Zeilentypen beschrieben. Der Inhalt dieser Speicherzelle entscheidet, wann eine neue logische Zeile begonnen werden muß oder ob die laufende logische Zeile um eine weitere echte Zeile erweitert werden kann. Der Bildschirm-Editor verwendet diese Speicherzelle, um komplette logische Zeilen nach oben zu verschieben. Einige andere Routinen benutzen den Wert der Zelle bei der Rückwärtsüberprüfung einer Zeile, bei der die Endposition der Zeile bekannt sein muß. Schließlich bezieht noch die bereits behandelte Speicherzelle 200 Ihren Wert von der Zelle 213. |
Länge der BildschirmzeileDer Inhalt dieser Speicherzelle entscheidet, ob eine neue Zeile angefangen werden muß oder nicht. |
Length of current screen line minus 1. Values: $27, 39; $4F, 79. | 40/80 max positon | Physical Screen Line Length | Current logical Line length: 39 or 79. | Current screen line length | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D6 | TBLX | 214 |
Current Cursor Physical Line NumberThis location contains the current physical screen line position of the cursor (0-24). It can be used in a fashion to move the cursor vertically, by POKEing the target screen line (1-25) minus 1 here, followed by a PRINT command. For example,
prints the message on line 11. The first PRINT statement allows the system to update the other screen editor variables so that they will also show the new line. The cursor can also be set or read using the Kernal PLOT routine (58634, $E50A) as explained in the entry from locations 780-783 ($030C-$030F). |
Nummer der echten Zelle, auf der sich der Cursor gerade befindetDiese Speicherzelle ist zusammen mit der Speicherzelle 211 beschrieben. |
CursorzeileHier wird die Zeilenposition des Cursors festgehalten. |
Current cursor row. Values: $00-$18, 0-24. | Current Cursor Physical Line Number | Current Screen Line number of Cursor. | Row where curosr lives | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D7 | DATA | 215 |
Temporary Storage Area for ASCII Value of Last Character PrintedThe ASCII value of the last character printed to the screen is held here temporarily. |
Zwischenspeicher für den ASCII-Codewert der zuletzt gedrückten TasteBei der Tastaturabfrage werden die Tastencodes (siehe Speicherzelle 203) in ASCII-Codewerte umgewandelt und in den Tastaturpuffer gebracht. Die Speicherzelle 215 dient dabei als Zwischenspeicher. Kassettenoperationen speichern hier auch Prüfsummen ab. |
Speicher für ASCII-Tasten-CodeBevor ein Zeichen in den Tastaturpuffer gebracht wird, wird es vorher hier zwischengespeichert. |
PETSCII code of character during screen input/output. Bit buffer during datasette input. Block checksum during datasette output. |
Cassette: holds most recent dipole bit value | Temp Data Area | Screen value of current Input Character/Last Character Output. | Last inkey/checksum/buffer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D8 | INSRT | 216 |
Flag: Insert Mode (Any Number Greater Than 0 Is the Number of Inserts)When the INST key is pressed, the screen editor shifts the line to the right, allocates another physical line to the logical line if necessary (and possible), updates the screen line length in 213 ($D5), and adjusts the screen line link table at 217 ($D9). This location is used to keep track of the number of spaces that has been opened up in this way. Until the spaces that have been opened up are filled, the editor acts as if in quote mode (see location 212 ($D4), the quote mode flag). This means that cursor control characters that are normally nonprinting will leave a printed equivalent on the screen when entered, instead of having their normal effect on cursor movement, etc. The only difference between insert and quote mode is that the DELETE key will leave a printed equivalent in insert mode, while the INST key will insert spaces as normal. |
Flagge für INSERT-ModusImmer wenn die geSHIFTete INST/DEL-Taste gedrückt wird, um in einer Zeile Platz für ein einzufügendes Zeichen zu schaffen, wird der Inhalt der Speicherzelle 216 um 1 erhöht. Dann wird die Zeile ab dem Freiplatz nach rechts verschoben, der Inhalt der Speicherzelle 213 erhöht und schließlich der entsprechende Wert der Link-Tabelle für Bildschirmzeilen ab Speicherzelle 217 bis 242 verändert. Bei jedem Tippen eines Zeichens in den freigewordenen Platz wird der Inhalt von 216 wieder um 1 reduziert, bis mit der 0 das Ende des INSERT-Modus angezeigt wird. |
Anzahl der InsertsHier wird die Anzahl der Inserts festgelegt. |
Number of insertionsValues:
|
Insert mode flag | Flag: Insert Mode, >0 = # INSTs | Count of number of inserts outstanding. | # of INSERTs outstanding | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00D9-$00F2 | LDTB1 | 217-242 |
Screen Line Link Table/Editor Temporary StorageThis table contains 25 entries, one for each row of the screen display. Each entry has two functions. Bits 0-3 indicate on which of the four pages of screen memory the first byte of memory for that row is located. This is used in calculating the pointer to the starting address of a screen line at 209 ($D1). While earlier PETs used one table for the low bytes of screen rows and another for the high bytes, this is not possible on the 64, where screen memory is not fixed in any one spot. Therefore, the Operating System uses a table of low bytes at 60656 ($ECF0), but calculates the high byte by adding the value of the starting page of screen memory held in 648 ($0288) to the displacement page held here. The other function of this table is to establish the makeup of logical lines on the screen. While each screen line is only 40 characters long, BASIC allows the entry of program lines that contain up to 80 characters. Therefore, some method must be used to determine which pairs of physical lines are linked into a longer logical line, so that this longer logical line may be edited as a unit. The high bit of each byte here is used as a flag by the screen editor. That bit is set (leaving the value of the byte over 128 ($80)) when a line is the first or only physical line in a logical line. The high bit is reset to 0 only when a line is the second half of a logical line. |
Link-Tabellen der Bildschirm-ZeilenDiese 26 Speicherzellen enthalten Angaben für jede Zeile des Bildschirms. Jedes dieser Bytes hat zwei Funktionen. Die ersten 4 Bit, also Bit 0 bis 3, geben an, in welchem Speicherblock, man sagt auch »page« dazu, das erste Byte der betreffenden Bildschirmzeile sich befindet. Diese Angabe wird zur Berechnung des Zeigers in der Speicherzelle 209 (siehe dort) verwendet. Sie ist in dieser Form notwendig, da der Bildschirmspeicher beim C 64 überall in den Arbeitsspeicher gelegt werden kann. Um die Position eines Zeichens oder besser gesagt eines Bytes davon im Bildschirmspeicher genau positionieren zu können, braucht das Betriebssystem noch die genaue Lage innerhalb des Speicherblocks. Das Low-Byte dieser Zahl steht in einer Tabelle ab Speicherzelle 60656 (60952 beim VC 20). Das High-Byte wird berechnet, und zwar durch Addition des Wertes der Speicherzelle 648 mit dem Wert der ersten 4 Bit in Tabelle 217 bis 242. Der Wert in Zelle 648 gibt die Anfangsadresse des Bildschirmspeichers an. Der zweite Teil jedes Bytes in der Tabelle 217 bis 242 hat eine andere Funktion. Wie im Texteinschub 23 beschrieben ist, kann eine logische Zeile aus ein oder zwei (beim VC 20 sogar bis zu 4) echten Zeilen bestehen. Das Betriebssystem braucht daher eine Angabe, welche echten Zeilen zu einer logischen Zeile verbunden sind. Dieses Verbinden heißt auf englisch »link«, daher heißt der Speicherbereich 217 bis 242 »Link-Tabelle«. Diese oberen 4 Bit zeigen mit irgendeinem Wert über 0 an, daß die betreffende echte Zeile die erste oder einzige einer logischen Zeile ist. Sind die 4 Bit alle 0, dann ist sie eine 2., 3. und 4. Zeile der logischen Zeile. |
MSB der BildschirmzeilenanfängeAlle 25 Speicherzellen enthalten Informationen über die Zeilen des Bildschirms. |
High byte of pointers to each line in screen memory (25 bytes)Values:
|
Line flags+endspace | Screen Line Link Table / Editor Temps |
Screen Line link Table/Editor temporaries. High Byte of Line Screen Memory Location. |
Screen line link table | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00F3-$00F4 | USER | 243-244 |
Pointer to the Address of the Current Screen Color RAM LocationThis poitner is synchronized with the pointer to the address of the first byte of screen RAM for the current line kept in location 209 ($D1). It holds the address of the first byte of color RAM for the corresponding screen line. |
Zeiger auf Position des Cursors im FarbspeicherJedem Platz im Bildschirmspeicher, in dem der Codewert für ein Zeichen steht, entspricht ein Platz im Farbspeicher, in dem der Codewert für die Farbe dieses Zeichens steht. Das heißt, daß den Bildschirm-Werten der Speicherzellen 209 bis 210 die Farbspeicher-Werte der Zellen 243 bis 244 entsprechen. Dieser Zeiger bestimmt also in der Low-/High-Byte-Darstellung die Adresse im Farbspeicher, ab der die echte Zeile beginnt, auf welcher der Cursor gerade steht. |
Zeiger in Farb-RAMDiese Speicherzellen zeigen auf die Stelle im Farb-RAM, an der der Cursor auf der Zeile steht. |
Pointer to current line in Color RAM. | Screen editor color IP | Pointer: Current Screen Color RAM loc. | Pointer: Current Colour RAM Location. | Screen color pointer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00F5-$00F6 | KEYTAB | 245-246 |
Vector: Keyboard Decode TableKEYTAB points to the address of the keyboard matrix lookup table currently being used. Although there are only 64 keys on the keyboard matrix, each key can be used to print up to four different characters, depending on whether it is struck by itself or in combination with the SHIFT, CTRL, or Commodore logo keys. The tables pointed to y this address hold the ASCII value of each of the 64 keys for one of these possible combinations of keypresses. When it comes time to print the character, the table that is used determines which character is printed. The addresses of the four tables are:
The concept of the keyboard matrix tables should not be confused with changing the character sets from uppercase/graphics to upper/lowercase. The former involves determining what character is to be placed into screen memory, while the latter involves determining which character data table is to be used to decode the screen memory into individual dots for the display of characters on the screen. That character base is determined by location 53272 ($D018) of the VIC-II chip. |
Vektor auf die Decodiertabelle für ASCII-Codewerte der TastenBei der Diskussion der Speicherzelle 145 habe ich Ihnen gezeigt, wie das Drücken einer der 64 Tasten entschlüsselt wird. Ein entschlüsselter Wert wird in Speicherzelle 145 zwischengespeichert und gelangt dann als Tastencode in die Speicherzelle 203. Bei der Besprechung der Zelle 203 wurden die Codewerte aufgelistet. Ich habe auch darauf hingewiesen, daß die Codes der drei Steuertasten SHIFT, CTRL und COMMODORE (C=) separat in der Zelle 653 stehen. Diese Tastencodes sind sehr nützlich und vom Basic aus gut verwendbar. Im Verkehr mit anderen Geräten sind sie aber nicht einsetzbar, da sie keiner internationalen Norm entsprechen. Eine derartige Norm bietet der sogenannte ASCII-Code. Deshalb rechnet, wo notwendig, das Betriebssystem die Tastencodes in den ASCII-Code um. Dazu stehen im Speicher des Betriebssystems vier Tabellen (Bild 22), die die ASCII-Codewerte enthalten (in Klammern für den VC 20). Die Umrechnung der Tastencodes in ASCII-Code ist sehr einfach. Der Tastencode wird lediglich zu der Anfangsadresse der entsprechenden Tabelle hinzugezählt. Die Summe ergibt die Adresse in derTabelle, in der der ASCII-Code für das gedrückte Zeichen steht. Als Beispiel nehmen wir das normale »G«, sein Tastencode ist 26 (VC 20:19). Zur Anfangsadresse der normalen Tabelle 60289 (60510) dazugezählt, ergibt das 60315 (60529). Schauen wir in dieser Speicherzelle nach:
In beiden Fällen erhalten wir die Zahl 71. Ein Blick in die ASCII-Tabelle des Handbuchs bestätigt die Richtigkeit. Der Vektor in den vorliegenden Speicherzellen 245/246 zeigt auf den Anfang der vier Tabellen, und zwar in Abhängigkeit davon, ob und welche der drei Steuertasten zusammen mit einer anderen Taste gedrückt worden ist. Auch das kann ich Ihnen zeigen mit einer Programmzeile, welche ein Zahlenband erzeugt, dessen Zahl durch die Steuertasten verändert wird. Sie werden sehen, es sind die Anfangsadressen der vier Tabellen.
|
Zeiger auf Tastatur-DekodiertabelleDiese Speicherzellen zeigen auf die Tastatur-Dekodiertabelle. |
Pointer to current conversion table during conversion from keyboard matrix codes to PETSCII codes. | Keyscan table indirect | Vector Keyboard Decode Table |
Vector: Current Keyboard decoding Table. ($EB81) |
Keyboard pointer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00F7-$00F8 | RIBUF | 247-248 |
Pointer: RS-232 Input BufferWhen device number 2 (the RS-232 channel) is opened, two buffers of 256 bytes each are created at the top of memory. This location points to the address of the one which is used to store characters as they are received. A BASIC program should always OPEN device 2 before assigning any variables to avoid the consequences of overwriting variables which were previously located at the top of memory, as BASIC executes a CLR after opening this device. |
Zeiger auf den Anfang des RS232-Eingabe-PuffersImmer wenn ein Kanal mit der Geräte-Nummer 2 (User-Port) eröffnet wird, werden am oberen Ende des Arbeitsspeichers zwei Pufferspeicher mit je 256 Byte reserviert (siehe auch die Beschreibung der Speicherzellen 55 bis 56). Der Zeiger, der in Low-/High-Byte-Darstellung in 247 und 248 steht, zeigt auf die Anfangsadresse desjenigen Pufferspeichers, der die ankommenden Zeichen aufnimmt. Ein Programm, das den User-Port benutzen will, sollte übrigens immer zuerst die Gerätenummer 2 eröffnen, bevor irgendwelche Variable definiert werden. Dadurch wird vermieden, daß die Puffer-Reservierung eventuelle Variablenwerte überschreibt, die bereits in diesen 512 Byte angesiedelt worden sind. |
Zeiger auf RS-232 EingabepufferDiese Register zeigen auf die Anfangsadresse des Eingabepuffers. |
RS-232 input buffer pointer | RS-232 Input Buffer Pointer | RS232 Input Buffer Pointer. | RS-232 Rev pntr | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00F9-$00FA | ROBUF | 249-250 |
Pointer: RS-232 Output BufferThis location points to the address of the 256-byte output buffer which is used for transmitting data to RS-232 devices (device number 2)l |
Zeiger auf den Anfang des RS232-Ausgabe-PuffersDieser Zeiger ist der Zwilling zu dem in den Zellen 247/248 stehenden Zeiger, diesmal aber für den Ausgabe-Puffer. |
Zeiger auf RS-232 AusgabepufferDiese Register zeigen auf die Anfangsadresse des Ausgabepuffers. |
RS-232 output buffer pointer | RS-232 Output Buffer Pointer | RS232 Output Buffer Pointer. | RS-232 Tx pntr | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00FB-$00FE | FREKZP | 251-254 |
Four Free Bytes of Zero Page for User ProgramsThese locations were specifically set aside for user-written ML routines that require zero-page addressing. While other zero-page locations can be used on a noninterference basis, it is guaranteed that BASIC will not alter these locations. |
Vier freie Byte für AnwenderprogrammeDiese 4 Byte sind frei, und da sie von Basic nicht gestört beziehungsweise verändert werden, eignen sie sich in idealer Weise für Flaggen, Register oder andere Zwischenspeicher. |
unbenutzt | Unused (4 bytes). | Free KERNAL zero page 9/24/80 | Free 0-Page Space for User Programs | Free Zero Page space for User Programs. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$00FF-$010A | BASZPT | 255-266 |
BASIC Temporary Data for Floating Point to ASCII ConversionThis location is used for temporary storage in the process of converting floating point numbers to ASCII characters. |
Arbeitsspeicher für Umwandlung von Gleitkomma-Zahlen in ASCII-Werte, auch FAC (Fließkomma-Akku) genanntDiese 12 Byte werden von einer Routine des Betriebssystems verwendet, um Werte zwischenzuspeichern, die bei der Umwandlung von Gleitkomma-Zahlen in ASCII- Werte oder in Werte der Funktion TI$ anfallen. Eine andere Routine verwendet den Bereich, um Zeichenketten (Strings) zu untersuchen. |
Puffer für Umwandlung Fließkomma nach ASCIIDiese Register werden für die Zwischenspeicherung von Fließkommazahlen benutzt. |
Buffer for conversion from floating point to string (12 bytes.) | Location ($FF) used by BASIC | Floating to String Work Area | Assembly Area for Floating point to ASCII conversion. | Floating to ASCII work area | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0100-$01FF | 256-511 |
Microprocessor Stack AreaLocations 256-511 are reserved for the 6510 microprocessor hardware stack. The organization of this temporary storage area has often been compared to that of a push-down stack of trays at a cafeteria. The first number placed on the stack goes to the bottom, and subsequent entries are placed on top of it. Then you pull a number off the stack, you come up with the last number that was pushed on (such a stack is called a Last In, First Out, or LIFO stack). The stack is controlled by one of the microprocessor registers called the Stack Pointer, which keeps track of the last stack location used. The first number placed on the stack goes to location 511 ($01FF), and subsequent entries are built downward toward 256 ($0100). If more than 256 numbers are pushed onto the stack, the Stack Pointer will start counting from 0 again, and an overflow error will result. Likewise, if you try to pull more items off the stack than have been pushed on, an underflow error will result. Most often, such errors will cause the system to go haywire, and nothing will operate until you turn the power off and on again. The stack is used by the system to keep track of the return addresses of machine language subroutines and interrupt calls and to save the contents of internal registers. The stack can also be used by the programmer for temporary storage. BASIC and the Kernal make heavy use of the stack. Microsoft BASIC uses part of the stack for a temporary work area. Therefore, the stack may be broken down into the following subregions: |
Processor stack. Also used for storing data related to FOR and GOSUB. | Micro-Processor System Stack Area | 6510 Hardware Stack Area. | Processor stack area | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0100-$013E | BAD | 256-318 |
Tape Input Error LogEach tape block is saved twice consecutively, in order to minimize loss of data from transmission errors. These 62 bytes serve as indices of which bytes in the tape block were not received corectly during the first transmission, so that corrections might be made on the second pass. |
Arbeitsspeicher für Fehler bei der Eingabe vom BandAlle Daten, die auf Band gespeichert werden, stehen dort doppelt in zwei identischen Blöcken hintereinander. Beim Laden in den Computer werden beide Blöcke miteinander verglichen, um Fehler zu finden und, wo möglich, sie zu korrigieren. In diesem Bereich, der übrigens auch bei der Speicherzelle 256 anfängt, aber 63 Byte in Anspruch nimmt, werden beim Laden Angaben gespeichert, aus denen das Betriebssystem erkennen kann, welche Bytes fehlerhaft sind. |
Speicher für Korrektur bei BandeingabeBeim Laden von Band werden hier die Daten zwischengespeichert, aus denen das Betriebssystem erkennen kann, welche Bytes fehlerhaft sind. |
Cassette: storage space for bad read locations (bottom of stack) | Tape Input Error Log | Tape Input Error log. | Tape error log | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0100-$013D | BAD | 256-317 | Pointers to bytes read with error during datasette input (62 bytes, 31 entries). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$013F-$01FF | 319-511 |
…This area is exclusively for the microprocessor stack. Some BASIC commands, such as FOR-NEXT loops require many stack entries at a time. Therefore, BASIC frequently checks the stack before pushing entries on, and returns an OUT OF MEMORY error if an operation would result in less than 62 bytes of available stack memory. Each FOR statement causes 18 bytes to be pushed onto the stack, which come off in the following order: First comes a one-byte constant of 129 ($81). Next is a two-byte pointer to the address of the subject variable (the X of FOR X=1 to 10). This is followed by the five-byte floating point representation of the TO value. Finally comes the two-byte line number of the line to which the program returns after a NEXT, and the two-byte address of the next character to read in that line after the FOR statement. Each GOSUB call places five bytes on the stack. The first byte to come off is a one-byte constant of 141 ($8D). The next two bytes contain the line number of the statement to which the program will RETURN after the subroutine ends. And the final two bytes are a pointer to the address of the BASIC program text for that statement in which the program RETURNs. DEF also leaves a five-byte entry on the stack. It is the same as that described for GOSUB, except that instead of a constant byte of 141, the first number is a dummy byte, whose value has no significance. |
Stapelspeicher (Stack) des MikroprozessorsDie Funktionsweise eines Stapelspeichers, auf englisch »stack«, ist im Texteinschub Nr. 24 erklärt. Der Stapelspeicher hat prinzipiell die Aufgabe, bei allen Sprüngen oder Unterbrechungen innerhalb eines normalen Programmablaufs alle Adressen und Daten so zu speichern, daß am Ende der Unterbrechung das Programm wieder fortgesetzt werden kann. Derartige Unterbrechungen und Sprünge treten in Basic bei den Befehlen GOSUB- RETURN und FOR-NEXT auf, genauso wie bei vielen Routinen des Betriebssystems. In Maschinensprache gibt es dafür sogar eigene Befehle. Heimo Ponnath hat sie alle in seinem Assemblerkurs (Folge 7 und 8 im 64’er, Ausgabe 2/85 und 3/85) sehr ausführlich beschrieben. Da uns hier Basic mehr interessiert, gebe ich Ihnen nur kurz an, was im Stapel gespeichert wird, da der Stapelspeicher nur in Maschinensprache manipuliert werden kann. Jeder FOR-TO-NEXT-Befehl belegt 18 Byte im Stapelspeicher. Im ersten Byte steht als Kennung dieZahl 129. Byte 2 und 3 enthalten in Low/ High-Byte-Darstellung einen Zeiger auf die Adresse, in der die durch das FOR definierte Schleifen-Variable (zum Beispiel K in FOR K=0 TO 3) gespeichert ist. Die nächsten 5 Byte sind für den Gleitkommawert von STEP reserviert, das Byte danach für das Vorzeichen von STEP. Danach folgt der Gleitkommawert von TO mit 5 Byte und in zwei weiteren Byte die Nummer derjenigen Zeile, auf die nach dem NEXT zurückgesprungen wird. In den letzten beiden Bytes schließlich steht ein Zeiger auf der Adresse, in der das nächste Zeichen steht, welches nach Beendigung der FOR-TO-NEXT-Schleife gelesen werden muß. Ein GOSUB-Befehl belegt 5 Byte im Stapelspeicher. Byte 1 enthält die Kennzahl 141. Ihr folgen zwei Byte für die Nummer der Zeile, auf die nach RETURN zurückgesprungen wird. Die letzten beiden Byte enthalten wieder einen Zeiger auf die Adresse, in der das nächste Zeichen steht, mit dem nach RETURN das Programm fortgesetzt wird. Der Basic-Befehl DEF zur freien Definition von Funktionen belegt ebenfalls 5 Byte im Stapelspeicher. Ihre Verteilung ist dieselbe wie von GOSUB, mit dem einzigen Unterschied, daß statt der ersten Kennzahl irgendein anderer Wert verwendet wird, der aber keine Bedeutung hat. Wenn so viele FOR...NEXT-Schleifen oder GOSUB-Sprünge gleichzeitig im Programm vorkommen, daß der Stapelspeicher voll wird, steigt das Programm mit OUT OF MEMORY aus. |
ProzessorstackDer Stack ist generell ein Zwischenspeicher, in dem der Programmierer Daten ablegen kann. Außerdem wird er vom Prozessor dazu benutzt, bei einem Interrupt oder einem Unterprogrammaufruf die Adresse, von der aus verzweigt wurde, zwischenzuspeichern. Dies geschieht in der Reihenfolge HIGH- und LOW-Byte. Die Daten werden im Stack von der Adresse $01FF zur Adresse $0100 hin abgelegt. Bei einem BREAK wird zusätzlich der Prozessorstatus im Stack abgelegt. |
BASIC Stack Area. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0200-$0258 | BUF | 512-600 |
BASIC Line Editor Input BufferWhen you are in the BASIC immediate mode, and type in a line of characters, those characters are stored here. BASIC then scans the string of characters, converts the text to tokenized BASIC program format, and either stores it or executes the line, depending on whether or not it started with a line number. This same area is also used to store data which is received via the INPUT and GET commands. This explains why these commands are illegal in immediate mode--they must use the same buffer space that is required by the immediate mode statement itself. It is interesting to note that this buffer is 89 bytes long. The screen editor will allow a maximum of only 80 characters in a program line, with one extra byte required for a 0 character, marking the end of the line. This presumable is a carry over from the VIC, which allows a line length of up to 88 characters. The last eight bytes of this buffer are therefore normally not used, and can be considered free space for the programmer to use as he or she sees fit. |
Eingabespeicher von BasicWenn Sie Zeichen, zum Beispiel einen Befehl oder eine Programmzeile, eingeben und mit der RETURN-Taste abschließen, werden diese Zeichen in diesen Speicherbereich von 512 bis 600 gebracht. Seine Länge von 89 Byte entspricht der Länge einer logischen Zeile des VC 20 (88 Zeichen) plus einer Abschluß- Null. Die logische Zeilenlänge des C 64 von 80 Zeichen füllt den Speicherbereich nicht ganz aus, aber das Betriebssystem des C 64 ist gegenüber dem des VC 20 nicht geändert worden. Nach RETURN sucht der Computer diesen Eingabespeicher nach Gänsefüßen, Komma und nach der Zahl für Zellenende ab. Dann wandelt der Computer die gespeicherten Zeichen in für ihn lesbare Zahlen (Token und ASCII-Werte) um und fügt am Anhang die Zeilennummer und die Anschluß-Adresse (Link) der nächsten Zeile, am Ende die Abschluß-Null hinzu. Wenn eine Zeilennummer vorhanden ist, kommt alles in den Programmspeicher. Fehlt sie jedoch, dann wird die ganze Anweisung sofort ausgeführt (Direktmodus). Eine detaillierte Beschreibung dieses Eingabe- und Umwandlungsvorganges gab Christoph Sauer im 3. Teil seines Kurses »Der gläserne VC 20« im 64’er, Ausgabe 11/84 ab Seite 126. Dieser Speicherbereich wird auch von den Befehlen INPUT und GET benutzt, um die Eingabedaten aufzunehmen. Das erklärt übrigens, warum diese beiden Befehle nur innerhalb einer Programmzeile und nicht im Direktmodus verwendet werden können. Sie verwenden ja denselben Speicherplatz, der vom Direkt-(Eingabe-)Modus verwendet wird. Es erklärt außerdem, warum eine von INPUT geforderte Eingabe maximal 88 Zeichen lang sein darf. |
BASIC-EingabepufferNach der Eingabe eines Befehls oder einer Programmzeile werden diese Daten in diesen Bereich zwischengespeichert, um dann wieder weiterverarbeitet zu werden. |
Input buffer, storage area for data read from screen (89 bytes). |
BASIC/MONITOR bufferType-in stored here. Direct statements execute out of here. Remember "INPUT" smashes buf. Must be on page zero or assignment of string values in direct statements won't copy into string space -- which it must. N.B.: Two nonzero bytes must precede "BUFLNM". |
System INPUT Buffer | BASIC Input Buffer (Input Line from Screen). | Basic input buffer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0259-$0276 | 601-630 |
Tables for File Numbers, Device Numbers, and Secondary AddressesAll three of the tables here have room for ten one-byte entries, each of which represents an active Input/Output file. When an I/O file is opened, its logical file number is put into the table at 601 ($0259), the device number of the I/O device is put into the table at 611 ($0263), and its secondary address is put into the table at 621 ($026D). The entry for any particular I/O file will occupy the same position in each of the three tables. That is, if logical file number 2 is the third entry in the file number table, its secondary address will be the third entry in the secondary address table, and its corresponding device number will occupy the third spot in the device number table. Every time a device is OPENed, its information is added as the last entry in each table, and the value at location 152 ($98) is increased by one, indicating that there is one more active I/O file. When a device is CLOSEd, the value at location 152 is decreased by one, and all entries that occupy a position in the tables that is higher than that of the closed device are moved down one position, thus eliminating the entry for that device. The Kernal CLALL routine (62255, $F32F) simply zeros location 152, which has the effect of emptying these tables. |
Tabellen für File-Nummern, Geräte-Nummern und Sekundär-Adressen von eröffneten DateienBei der Besprechung der Speicherzelle 152 habe ich diesen Speicherbereich bereits erwähnt. Ich habe damals gesagt und gezeigt, daß die Zelle 152 über die Anzahl der eröffneten Dateien (Files) Buch führt, die Tabellen in 601 bis 630 dagegen darüber, welche File-Nummern, Geräte-Nummern und Sekundär-Adressen jeder eröffneten Datei zugeordnet sind. Wer sich nochmals über diese Begriffe orientieren will, den verweise ich auf die Beschreibung im Texteinschub Nr. 19. Der Speicherbereich von 601 bis 630 ist in drei Blöcke unterteilt.
In jeder Tabelle können also maximal 10 Byte stehen. Sie haben folgende Zusammensetzung: Die drei Angaben über eine eröffnete Datei stehen in den Tabellen jeweils am gleichen Platz. Wenn also die Datei Nummer 5 als dritte Datei eröffnet worden ist, steht eine 5 in Zelle 603, ihre Gerätenummer in Zelle 613, die Sekundär- Adresse entsprechend in Zelle 623. Immer wenn eine neue Datei eröffnet wird, kommen diese Angaben auf die nächsten Plätze der Tabellen, und der Inhalt der Speicherzelle 152 wird um 1 erhöht. Wird dagegen eine Datei geschlossen, dann rücken alle Angaben dahinter um eine Stelle zurück. In diesen Tabellen kann nachgesehen werden, mit welchen Parametern Dateien eröffnet worden sind. Eine sehr interessante Anwendung, die Eintragung in den Tabellen durch POKE zu verändern, wurde von Rügheimer und Spanik veröffentlicht, welche ich hier zitieren möchte. Eine Änderung der Filenummern in Tabelle 601 bis 610 ist nicht empfehlenswert, um Verwechslungen zu vermeiden. Mit dem folgenden kleinen Programm, welches bei einer eröffneten Datei die Geräte-Nummer in Tabelle 611 bls 620 ändert, kann zwischen einem Drucker mit Geräte-Nummer 4 und einem Plotter mit Geräte-Nummer 6 umgeschaltet werden.
Ähnliches ist mit den Sekundär-Adressen möglich. Dabei muß man allerdings wissen, daß die Sekundär-Adressen nicht so wie sie sind in der Tabelle 621 bis 630 gespeichert werden, sondern mit »OR 96« verknüpft. Dasselbe müssen wir auch machen:
Mit dieser Methode können Sie sich das öffnen und Schließen vieler Dateien ersparen. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0259-$0262 | LAT | 601-610 | Kernal Table of Active Logical File Numbers |
Tabelle der logischen FilenummernIn dieser Tabelle werden die logischen Filenummern der Reihe nach, von 1-10, eingetragen. Beim Schließen einer Datei werden diese Einträge wieder entfernt. |
Logical numbers assigned to files (10 bytes, 10 entries). | Logical file numbers | KERNAL Table: Active Logical File No's. | Kernal Table: Active logical File numbers. | Logical file table | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0263-$026C | FAT | 611-620 | Kernal Table of Device Numbers for Each Logical File | Device numbers assigned to files (10 bytes, 10 entries). | Primary device numbers | KERNAL Table: Device No. for Each File | Kernal Table: Active File First Addresses (Device numbers). | Device # table | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$026D-$0276 | SAT | 621-630 | Kernal Table of Secondary Addresses for Each Logical File | Secondary addresses assigned to files (10 bytes, 10 entries). | Secondary addresses | KERNAL Table: Second Address Each File | Kernal Table: Active File Secondary Addresses. | Sec Adds table | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0277-$0280 | KEYD | 631-640 |
Keyboard Buffer (Queue)This buffer, sometimes also referred to as the keyboard queue, holds the ASCII values of the characters entered from the keyboard. The interrupt routine which scans the keyboard deposits a character here each time a key is pressed. When BASIC sees that there are characters waiting, it removes and prints them, one by one, in the order in which they were entered. This kind of a buffer is known as FIFO, for First In, First Out. The buffer will hold up to ten characters, allowing you to type faster than the computer prints characters, without losing characters. The maximum number of characters this buffer can hold at one time is ten (as determined by the value at 649 ($0289)). Characters entered after the buffer is full will be ignored. The commands GET and INPUT retrieve characters from this buffer. If one of these is executed while there are already characters waiting in the buffer, those characters will be fetched as if they were part of the data being input. To prevent this from happening, you can clear the buffer by POKEing a 0 into location 198 ($C6), which holds the number of characters that are waiting in the buffer. One of the most interesting and useful techniques for programming Commodore computers is to have a program simulate direct entry of commands from the keyboard. This dynamic keyboard trick is achieved by first POKEing PETASCII characters, usually cursor movement characters and carriage returns, into the buffer, and setting location 198 ($C6) to show how many characters are waiting in the buffer. Next, you clear the screen, and PRINT the statements that you wish to have executed on the screen, carefully positioning them so that the first statement to be entered is on the fourth line of the screen. You then home the cursor and execute an END statement. This causes the keyboard buffer to be read, and the carriage returns to be executed, thus entering the printed lines as if they had been typed in immediate or direct mode. The program can be continued by including a GOTO statement in the last line entered. Many interesting effects can be achieved using this method. Examples of a few of these are included below. For example, program lines can be added, modified, or deleted, while the program is running. The following example shows how this is done:
You can use this technique to enter numbered DATA statements automatically, using values in memory. These statements become a permanent part of the program. Another interesting application is taking ASCII program lines from a tape data file, or sequential disk file, and having them entered automatically. This can be used for merging programs, or for transferring programs between computers with a modem and a terminal program. To create the ASCII program file, you use CMD to direct a LISTing to the desired device as follows:
This file can then be uploaded using a modem and appropriate terminal software, entered by itself or merged with another program by using the following program. Be sure to save this program before you run it, because it will erase itself when it is done.
If you wish to merge additional programs at the same time, when it indicates that the file has ended, press the STOP key rather than RETURN, enter the name of the new file in line 60000, and RUN 60000 |
TastaturpufferBei der Behandlung der Speicherzelle 203 habe ich die Codezahlen beschrieben, die beim Drücken einer der 64 Tasten erzeugt werden. Bei den Speicherzellen 245 und 246 haben wir gesehen, wie aus diesen Tastencodes der ASCII-Code für die verschiedenen Zeichen einer Taste umgerechnet wird. Hier nun im Tastaturpuffer landen diese umgerechneten ASCII-Werte. Wenn Sie den Kurs schon länger verfolgen, ist Ihnen das auch nicht neu, denn ich habe die Wirkungsweise des Tastaturpuffers bei der »Dynamischen Tastenabfrage« (Texteinschub Nr. 15) sozusagen im Vorgriff, ausführlich erklärt. Zur Erinnerung sei gesagt, daß im Tastaturpuffer alle Zeichen zwischengespeichert werden, die während eines Programmlaufes eingegeben und nicht sofort vom Betriebssystem verarbeitet werden können. Sobald der Computer sich im Eingabe-Modus befindet — nach Programmende oder bei INPUT- und GET- Befehlen, werden die Zeichen in der Reihenfolge ihrer Eingabe herausgeholt und verwendet. Der Tastaturpuffer ist 10 Byte lang. In Speicherzelle 198 steht, wieviele Zeichen sich im Puffer befinden. Als Ergänzung zu den Beispielen der dynamischen Tastenabfrage zeige ich Ihnen im Texteinschub Nr. 25 »Programme, die sich selbst verändern« noch ein paar andere Anwendungen. |
TastaturpufferHier werden die Tastencodes zwischengespeichert, die nicht sofort vom Betriebssystem weiterverarbeitet werden können. |
Keyboard buffer (10 bytes, 10 entries). | IRQ keyboard buffer | Keyboard Buffer Queue (FIFO) | Keyboard Buffer Queue (FIFO). | Keybd buffer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0281-$0282 | MEMSTR | 641-642 |
Pointer: O.S. Start of MemoryWhen the power is first turned on, or a cold start RESET is performed, the Kernal routine RAMTAS (64848, $FD50) sets this location to point to address 2048 ($0800). This indicates that this is the starting address of user RAM. BASIC uses this location to set its own start of memory pointer at location 43 ($2B), and thereafter uses only its own pointer. The Kernal routine MEMBOT (65076, $FE34) may be used to read or set this pointer, or these locations may be directly PEEKed or POKEd from BASIC. |
Zeiger auf den Anfang des ProgrammspeichersWenn der Computer eingeschaltet wird oder wenn mit einer Reset-Taste beziehungsweise mit SYS 58260 (VC 20: SYS 58232) ein Kaltstart ausgelöst wird, setzt das Betriebssystem diesen Zeiger auf die Adresse des ersten freien RAM- Speicherplatzes. Beim C 64 ist dies die Adresse 2048. Beim VC 20 hängt sie von der Speichererweiterung ab; ohne Erweiterung ist es 4096, mit einer 3-KByte- Erweiterung dagegen 1024, mit 8 KByte oder mehr ist die Adresse 4608. Dieser Zeiger wird vom Basic-Übersetzer in die Speicherzelle 43 übernommen und nur von dort weiterverwendet. |
Start des BASIC-RAMNach einem Reset oder einem Kaltstart wird dieser Zeiger auf den nächsten freien Speicherplatz gesetzt. |
Pointer to beginning of BASIC area after memory test.Default: $0800, 2048. |
Start of memory | Pointer: Bottom of Memory for O.S. | Pointer: Bottom of Memory for Operating System ($0800). | Start of Basic Memory | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0283-$0284 | MEMSIZ | 643-644 |
Pointer: O.S. End of MemoryWhen the power is first turned on, or a cold start RESET is performed, the Kernal routine RAMTAS (64848, $FD50) performs a nondestructive test of RAM from 1024 ($0400) up, stopping when the test fails, indicating the presence of ROM. This will normally occur at 40960 ($A000), the location of the BASIC ROM. The top of user RAM pointer is then set to point to that first ROM location. After BASIC has been started, the system will alter this location only when an RS-232 channel (device number 2) is OPENed or CLOSEd. As 512 bytes of memory are required for the RS-232 transmission and reception buffers, this pointer, as well as the end of BASIC pointer at 55 ($37), is lowered to create room for those buffers when the device is opened. CLOSing the device resets these pointers. The Kernal routine MEMTOP (65061, $FE25) may be used to read or set this pointer. |
Zeiger auf das Ende des ProgrammspeichersDieser Zeiger ist der Zwilling zu dem anderen Zeiger in 641 und 642. Er wird vom Betriebssystem auf die Adresse gesetzt, welche beim Kaltstart beziehungsweise der dabei durchgeführten Prüfung des Speichers den letzten verfügbaren RAM-Speicherplatz angibt. Beim C 64 ist diese Adresse normalerweise 40960 ($A000), beim VC 20 ohne Erweiterung 7680. Dieser Zeiger wird vom Basic-Übersetzer in die Speicherzelle 55 übernommen. |
Ende des BASIC-RAMDieser Zeiger wird nach einem Reset oder einem Kaltstart auf den letzten verfügbaren freien RAM-Speicherplatz gesetzt. |
Pointer to end of BASIC area after memory test.Default: $A000, 40960. |
Top of memory | Pointer: Top of Memory for O.S. | Pointer: Top of Memory for Operating System ($A000). | Top of Basic Memory | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0285 | TIMOUT | 645 |
Flag: Kernal Variable for IEEE Time-OutThis location is used only with the external IEEE interface card (which was not yet available from Commodore at the time of writing). For more information, see the entry for the Kernal SETTMO routine at 65057 ($FE21). |
Flagge für Ein- und Ausschalten der IEEE-488-KarteDiese Speicherzelle ist etwas mysteriös. Sie kommt im ganzen Betriebssystem nur ein einziges Mal zum Einsatz, und zwar als Flagge beim Betrieb der sogenannten IEEE-488-Interface-Karte. Wenn diese Flagge gesetzt ist, wartet der Computer 64 Millisekunden lang, ob er von einem angeschlossenen Gerät angesprochen wird. Wenn kein Signal kommt, gibt er ein Fehlersignal aus. Zahlen in der Zelle 645, die kleiner als 128 sind, bedeuten Flagge gesetzt, größer als 128 löschen sie die Flagge. |
Timeout-Flag für seriellen IEC-BusAlle Zähler in dieser Speicherzelle, die größer als 128 sind, bedeuten, daß ein Gerät angeschlossen ist. Die kleineren Werte bedeuten das Gegenteil. |
Unused. (Serial bus timeout.) | IEEE timeout flag | Flag: Kernal Variable for IEEE Timeout | Serial IEEE Bus timeout defeat Flag. | Serial bus timeout flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0286 | COLOR | 646 |
Current Foreground Color for TextThe process of PRINTing a character to the screen consists of both placing the screen code value for the character in screen memory and placing a foreground color value in the corresponding location in color RAM. Whenever a character is PRINTed, the Operating System fetches the value to be put in color RAM from this location. The foreground color may be changed in a number of ways. Pressing the CTRL or Commodore logo key and numbers 1-8 at the same time will change the value stored here, and thus the color being printed. PRINTing the PETASCII equivalent character with the CHR$ command will have the same effect. But probably the easiest method is to POKE the color value directly to this location. The table below lists the possible colors that may be produced, and shows how to produce them using all three methods. POKE
|
Aktuelle Farbe der Zeichen (Vordergrundfarbe)Um ein bestimmtes Zeichen auf den Bildschirm zu drucken, muß vom Betriebssystem erstens der Bildschirmcode des Zeichens in den Bildschirmspeicher und zweitens der Codewert der gewünschten Farbe in den Farbspeicher gebracht werden. In der Speicherzelle 646 steht immer der Codewert derjenigen Farbe, die gerade eingestellt ist. Immer wenn ein PRINT-Befehl gegeben wird, holt das Betriebssystem den Farbwert aus der Zelle 646 und bringt ihn in den Farbspeicher, und zwar an den entsprechenden Platz, wo gerade gePRINTet werden soll. Der Codewert in der Zelle 646 kann auf drei Arten eingestellt werden:
Innerhalb eines Programms Ist das POKEn in Zelle 646 wohl die eleganteste Methode (Tabelle 10). Als Beispiel möge dieses kleine Programm dienen:
Wer mehr über Vordergrund- und Hintergrundfarben erfahren will, der lese den Texteinschub Nr. 26 »Bunte Zeichen und bunter Hintergrund«. |
augenblickliche FarbeHier wird die augenblickliche Zeichenfarbe festgelegt:
|
Current color, cursor colorValues: $00-$0F, 0-15. |
Active color nybble | Current Character Color Code | Current Character Colour code. | Current color code | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0287 | GDCOL | 647 |
Color of Character under CursorThis location is used to keep track of the original color code of the character stored at the present cursor location. Since the blinking cursor uses the current foreground color at 646 ($0286), the original value must be stored here so that if the cursor moves on without changing that character, its color code can be restored to its original value. |
Zeichenfarbe unter dem CursorDas Blinken des Cursors wird dadurch erzeugt, daß das Zeichen auf der Stelle des Bildschirms, auf der er gerade steht (meistens ist es eine Leerstelle), dauernd von »normal« auf »revers« (oder »invertiert«) und zurück geschaltet wird. Die reverse Darstellung benutzt dabei die Farbe des Zeichens. Genauso, wie sich der Computer in der Speicherzelle 206 das Zeichen merkt, mit dem er gerade blinkt, um beim Weiterwandern dieses Zeichen in seiner »normalen« Form auf dem Bildschirm zurückzulassen, merkt er sich die Farbe dieses Zeichens in der Speicherzelle 647. |
Farbe unter dem CursorIn dieser Speicherzelle merkt sich das Betriebssystem, welche Farbe gerade unter dem Cursor steht. |
Color of character under cursorValues: $00-$0F, 0-15. |
Original color before cursor | Background Color Under Cursor | Background Colour under Cursor. | Color under cursor | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0288 | HIBASE | 648 |
Top Page of Screen MemoryThis location contains the value used by the Operating System routines that print to the screen as the base address for screen RAM. The top of screen memory can be found by multiplying this location by 256. The default value for screen RAM is set on power-up to location 1024 ($0400), and this location therefore usually contains a 4. Screen display memory on the Commodore 64 can be moved to start on any 1K boundary (location evenly divisible by 1024). This is done by manipulating the VIC-II chip memory bank select at location 56576 ($DD00). It is important to note, however, that while any area may be displayed, the Operating System will look here to find out where it should PRINT characters. Therefore, if you change the screen location by altering the contents of one of the two addresses listed above, the Operating System will still not know where to PRINT characters unless you also change this address as well. The result will be that characters entered from the keyboard or PRINTed will not appear on the screen. Examples of how to properly relocate the screen can be found at the entries for location 53272 ($D018) and 43 ($2B). Since the PRINT command in essence just POKEs a lot of values to screen and color memory, by changing this pointer you can print a string of characters to memory locations other than screen RAM. For example, you could PRINT a sprite shape to memory without having to READ a lot of DATA statements. The program below PRINTs different sprite shapes into the sprite data area:
Since PRINTing also changes color memory, you can change the pointer to print the characters harmlessly to ROM, while changing a lot of screen RAM at one time, as the following program demonstrates:
|
Beginn des BildschirmspeichersIn dieser Speicherzelle steht eine Zahl, die als High-Byte dem Betriebssystem angibt, ab welcher Speicherzelle der Bildschirmspeicher beginnt. Nach einem Kaltstart (nach dem Einschalten oder nach dem Drücken der RESET-Taste) steht hier eine 4, das ergibt als Anfangsadresse 1024 (= 4256). Beim VC 20 ohne Erweiterung steht dort eine 30. Daraus folgt, daß die Anfangsadresse bei 7680 (= 30256) liegt. Der Bildschirmspeicher hat keinen absolut festen Platz. Innerhalb gewisser Grenzen kann er durch Verändern des Inhalts der Speicherzelle 53272 (36869 beim VC 20) verschoben werden. Die Methode dazu ist im Texteinschub näher beschrieben. Wichtig dabei ist, daß nach dem Verschieben der Inhalt der Speicherzelle 648 entsprechend geändert wird, damit auch das Betriebssystem die Verschiebung berücksichtigt. Umgekehrt kann aber dem Betriebssystem durch Ändern der Zahl in der Speicherzelle 648 mitgeteilt werden, daß es Zeichen in einen Speicherbereich bringen soll, der außerhalb des »offiziellen«, durch die Speicherzelle 53272 (36869) festgelegten Bildschirmspeichers liegt. Zwei Beispiele sollen das verdeutlichen. Der PRINT-Befehl macht letztlich nichts anderes, als viele Zahlen in den Bildschirm- und den Farbspeicher zu POKEn. Wenn nun der Zeiger in Zelle 648 verschoben wird, kann man mit einem PRINT-Befehl eine beliebige Zeichenkette außerhalb des Bildschirmspeichers speichern. Auf die gleiche Weise kann man beim C 64 Sprites mit einem PRINT- Befehl speichern, ohne mit READ viele lästige DATA-Zeilen lesen zu müssen. |
HIGH-Byte Video-RAMDieses HIGH-Byte gibt dem Betriebssystem an, ab welcher Adresse das Video-RAM zu finden ist. |
High byte of pointer to screen memory for screen input/output.Default: $04, $0400, 1024. |
Base location of screen (top) | Top of Screen Memory (Page) | High Byte of Screen Memory Address ($04). | Screen memory page | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0289 | XMAX | 649 |
Maximum Keyboard Buffer SizeThe value here indicates the maximum number of characters that the keyboard buffer at 631 ($0277) may hold at any one time. Anytime that the current buffer length in location 198 ($C6) matches the value here, further keypresses will be ignored. Although the maximum size of the keyboard buffer is usually 10 characters, it may be possible to extend it up to 15 characters by changing the number here. This could cause the Operating System pointers to the bottom and top of memory at 641-644 ($0281-$0284) to be overwritten, but no real harm should result. |
Maximale Länge des TastaturpuffersDer Tastaturpuffer belegt, wie schon besprochen, die Speicherzellen 631 bis 640. Er kann darin maximal 10 Zeichen Zwischenspeichern. Der Inhalt der Speicherzelle 649 legt fest, wieviele Zellen des Tastaturpuffers verwendet werden sollen, eine Zahl also, die normalerweise zwischen 0 und 10 liegen sollte. Die 10 ist übrigens der Wert, welcher nach dem Einschalten vom Betriebssystem in die Zelle 649 gebracht wird. Diese Zahl wird immer mit dem Inhalt der Speicherzelle 198 verglichen, der die aktuelle Anzahl der Zeichen im Tastaturpuffer angibt. Ist die Differenz der beiden Zahlen gleich Null, dann können keine weiteren Zeichen eingegeben werden. Es ist naheliegend, daß durch Verändern der Zahl in Zelle 649 die Länge des Tastaturpuffers verändert werden kann. Der eine Extremfall ist 0: POKE 649,0 schaltet die Tastatur aus. Nichts geht mehr. Das kann bei Programmen oder Spielen, die durch falsches oder zeitlich unpassendes Drücken von Tasten gestört werden, recht nützlich sein. Einschalten kann man dann die Tastatur nur mit RUN/STOP und RESTORE. Auch eine Erhöhung der Zahl in 649 über 10 hinaus ist möglich. Die Zeichen werden halt nur über die dafür reservierten Speicherzellen 631 bis 640 hinaus in Zellen geschrieben, die eigentlich eine andere Funktion haben. Bis zur Speicherzelle 645 geht das normalerweise ohne Probleme, da die betroffenen »fremden« Adressen nur direkt nach dem Einschalten des Computers gebraucht werden. Probieren Sie es aus, indem Sie zuerst eine Zeitschleife laufen lassen und in dieser Zeit etwa 20 Tasten drücken. Am Ende der Zeitschleife wird der Inhalt des Tastaturpuffers ausgedruckt, und Sie sehen in der Tat 15 der eingegebenen Zeichen:
Auf dem Bildschirm erscheinen die Zeichen Q bis G. Wenn Sie die Zahl in 649 noch weiter erhöhen, dringen Sie in die Zellen 646 und 647 ein und diese bestimmen bekanntlich die Zeichenfarbe. Wenn Sie aber eine unbeabsichtigte und unkontrollierbare Farbänderung nicht stört, können Sie den Tastaturpuffer auf 17 Zeichen vergrößern. Ab 18 Zeichen stürzt der Computer ab. |
Länge des TastaturpuffersDieses Register gibt an, wie viele Speicherzellen des Tastaturpuffers belegt werden sollen. |
Maximum length of keyboard bufferValues:
|
Size of Keyboard Buffer | Maximum number of Bytes in Keyboard Buffer ($0A). | Max size of keybd buffer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$028A | RPTFLA | 650 |
Flag: Which Keys Will Repeat?The flag at this location is used to determine whether to continue printing a character as long as its key is held down, or whether to wait until the key is let up before allowing it to be printed again. The default value here is 0, which allows only the cursor movement keys, insert/delete key, and the space bar to repeat. POKEing this location with 128 ($80) will make all keys repeating, while a value of 64 ($40) will disable all keys from repeating. |
Flagge für TastenwiederholungNormalerweise steht in dieser Speicherzelle eine 0. Das bedeutet, daß die Funktion der Cursor-Tasten, der Leertaste und der INST/DEL-Taste wiederholt wird, solange die entsprechende Taste gedrückt wird. Durch Verändern der Zahl in der Speicherzelle 650 kann diese Wiederholfunktion sowohl auf alle Tasten ausgedehnt als auch für alle Tasten gesperrt werden.
ist der Normalzustand, Wiederholfunktion für Cursor-, Leer- und INST/DEL-Taste
schaltet Wiederholfunktion für alle Tasten aus.
erweitert Wiederholfunktion auf alle Tasten. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
RPTFLG |
Flag für Repeatfunktion für alle TastenIn dieser Speicherzelle wird dem Betriebssystem angegeben, welche Tasten eine Repeat-Funktion haben und welche nicht:
|
Keyboard repeat switchBits:
|
Key repeat flag | Flag: REPEAT Key Used, $80 = Repeat | Flag: Repeat keys; $00 = Cursors, INST/DEL & Space repeat, $40 no Keys repeat, $80 all Keys repeat ($00). | Repeat all keys | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$028B | KOUNT | 651 |
Counter for Timing the Delay Between Key RepeatsThis location is used as a delay counter to determine how long to wait while a key is being held down until the next repeat printing of that key. The value here starts at 6. If location 652 ($028C) contains a 0, the value in this location is counted down once every 1/60 second, so long as the same key is held down. When this counter gets to 0, and if the repeat flag at 650 ($028A) allows that key to repeat, its ASCII equivalent will once again be placed in the keyboard buffer. A value of 4 is then placed in location 651, allowing subsequent repeats to occur at a rate of 15 per second. |
Zähler für Wiederholgeschwindigkeit der TastenDas Betriebssystem verwendet diese Speicherzelle als Zähler, der die Geschwindigkeit bestimmt, mit der eine Taste wiederholt wird, wenn sie länger gedrückt wird. Voraussetzung ist die durch Zelle 650 festgelegte Wiederholbarkeit der Taste. Am Anfang steht in der Zelle 651 die Zahl 6. Sobald eine wiederholbare Taste gedrückt wird, zählt das Betriebssystem diese Zahl alle 0,0167 Sekunden (60mal in der Sekunde) um 1 zurück, bis die Zahl 1 erreicht ist. Dann erst wird das Zeichen der gedrückten Taste wieder auf den Bildschirm gedruckt oder ihre Funktion wiederholt. Bei jedem folgenden Lauf steht in Zelle 651 die Zahl 4. Entsprechend verkürzt sich der Zählvorgang. Am schnellsten würde die Wiederholung natürlich mit dem Wert 1 in der Speicherzelle 651 sein. Von Basic aus mit POKE 651,1 geht das leider nicht. Im Texteinschub Nr. 27 »Turbo-Tasten« wird ein Maschinenprogramm beschrieben, welches dies kann. |
Zähler für RepeatgeschwindigkeitDiese Speicherzelle dient als Zähler, die die Repeat-Geschwindigkeit festlegt. |
Delay counter during repeat sequence, for delaying between successive repeatsValues:
|
Repeat Speed Counter | Repeat Key: Speed Counter ($04). | Repeat speed counter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$028C | DELAY | 652 |
Counter for Timing the Delay Until the First Key Repeat BeginsThis location is used as a delay counter to determine how long a key must be held down before the entry of that key should be repeated. The initial value of 16 is counted down every 1/60 second, as long as the same key remains pressed. When the value gets to 0, location 651 ($028B) is counted down from 6, and the key is repeated when the value there reaches 0. Thus a total of 22/60, or approximately 1/3, second will elapse before the first repeat of a key. The value here will be held to 0 after the first repeat, so that subsequent keystroke repititions occur much more quickly. |
Zähler für die Ansprechzeit der Wiederholfunktion von TastenDiese Speicherzelle wird vom Betriebssystem als Zähler verwendet, der festlegt, wie lange eine wiederholbare Taste gedrückt sein muß, bis die Wiederholfunktion einsetzt. Am Anfang steht in der Zelle 652 die Zahl 16. Diese Zahl wird alle 0,0167 Sekunden um 1 reduziert, bis die Zahl 0 erreicht ist. Dann wird das Zeichen der Taste auf den Bildschirm gebracht oder ihre Funktion wiederholt. Anschließend wird die Zahl 4 in die Speicherzelle 651 geschrieben (siehe dort), während die Zelle 652 so lange auf 0 stehen bleibt, bis eine andere Taste gedrückt wird. Wie diese anfängliche Verzögerung reduziert werden kann, steht im Texteinschub Nr. 27 »Turbo-Tasten«. |
Zähler für RepeatverzögerungHier wird angegeben, wie lange eine Taste gedrückt sein muß, bis die Repeat-Funktion einsetzt. |
Repeat sequence delay counter, for delaying before first repetitionValues:
|
Repeat Delay Counter | Repeat Key: First repeat delay Counter ($10). | Repeat delay counter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$028D | SHFLAG | 653 |
Flag: SHIFT/CTRL/Logo KeypressThis flag signals which of the SHIFT, CTRL, or Commodore logo keys are currently being pressed, if any. A value of 1 signifies that one of the SHIFT keys is being pressed, a 2 shows that the Commodore logo key is down, and 4 means that the CTRL key is being pressed. If more than one key is held down, these values will be added; for example, a 3 indicates that SHIFT and logo are both held down. The value here is used by the Operating System when determining how to convert a keypress into a PETASCII character. There are four different tables used to translate one of the 64 keys on the keyboard matrix into a PETASCII character, and the combination of special SHIFT keys determines which of these tables will be used (see the entry for location 245 ($F5) for more details on the keyboard tables). Pressing the SHIFT and Commodore logo keys at the same time will toggle the character set that is presently being used between the uppercase/graphics set, and the lowercase/uppercase set (provided that the flag at 657 ($0291) has not been set to disable this switch). This changes the appearance of all of the characters on the screen at once. It has nothing whatever to do with the keyboard shift tables, however, and should not be confused with the printing of SHIFTed characters, which affects only one character at a time. Rather, it is the result of the value of the character dot data table base address in 53272 ($D018) being changed. The came result may be obtained by POKEing that address directly. |
Tastencode der SHIFT-, CTRL- und Commodore-TasteIn der Speicherzelle 203 stehen die Codes aller Tasten, die gedrückt werden, außer die der drei Steuertasten SHIFT, CTRL und Commodore (oft auch CBM-, Logo- oder C=-Taste genannt). Diese drei Ausnahmen haben ihr eigenes Code-Register, eben 653. Der Grund dafür liegt in der Bedeutung der drei Tasten. Sie können ja bekanntlich verschiedene Zeichensätze einschalten:
Ich habe diese Zusammenhänge auch bei der Behandlung der Speicherzellen 245 und 246 erwähnt. Die Codezahlen selbst sind auch in der Tabelle 9 enthalten. Der Vollständigkeit halber sind sie hier noch einmal angegeben:
Mit dem folgenden kleinen Programm und mit ein wenig Fingerfertigkeit können Sie diese Codewerte nachvollziehen:
Eine interessante Anwendung habe ich im Texteinschub Nr. 21 »Abfrage der Tastencodes oder 476 Funktionstasten« gegeben. |
Flag für SHIFT, Commodore und CTRLIn diesem Register stehen die Tastencodes der Steuertasten:
|
Shift key indicatorBits:
|
SHIFT flag byte | Flag: Keyboard SHIFT Key/CTRL Key/C= Key | Flag: Shift Keys: Bit 1 = Shift, Bit 2 = CBM, Bit 3 = CTRL; ($00 = None, $01 = Shift, etc.). | Keyboard Shift/Control flag | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$028E | LSTSHF | 654 |
Last Pattern of SHIFT/CTRL/Logo KeypressThis location is used in combination with the one above to debounce the special SHIFT keys. This will keep the SHIFT/logo combination from changing character sets back and forth during a single pressing of both keys. |
Tastencode der zuletzt gedrückten SHIFT-, CTRL-oder C=-TasteDiese Speicherzelle wird zusammen mit der Zelle 653 verwendet, um zu verhindern, daß ein schlechter Tastendruck als mehrfaches Drücken derselben Taste gedeutet wird. Im Fachdeutsch nennt man das »Entprellen« einer Taste oder eines Kontaktes. Die Funktion ist vergleichbar mit der der Zelle 197 gegenüber der Zelle 203 für alle anderen Tasten. |
SHIFT-FlagHier steht die zuletzt gedrückte Steuertaste. |
Previous value of shift key indicatorBits:
|
Last SHIFT pattern | Last Keyboard Shift Pattern | Last Shift Key used for debouncing. | Last shift pattern | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$028F-$0290 | KEYLOG | 655-656 |
Vector to Keyboard Table Setup RoutineThis location points to the address of the Operating System routine which actually determines which keyboard matrix lookup table will be used. The routine looks at the value of the SHIFT flag at 653 ($028D), and based on what value it finds there, stores the address of the correct table to use at location 245 ($F5). The interrupt driven keyboard-scanning routine jumps through this RAM vector to get to the table setup routine. Therefore, it is possible to alter the address contained in this vector, and direct the keyscan routine to your own routine, which can check the keypress and SHIFT combination, and act before a character is printed. Since this routine comes after the keypress, but before it is printed, this is a very good place to have your preprocessor routine check for a particular keypress. An excellent example of such a program is the "VICword" program by Mark Niggemann, COMPUTE!'s Second Book of VIC. This program adds a machine language routine that checks if the SHIFT or Commodore logo key is pressed while not in quote mode. If it finds one of these keypresses, it substitutes an entire BASIC keyword for the letter (A-Z) of the key that was pressed. An adaptation of that program for the 64 appears below.
Commodore 64word: Keys into BASIC Commands
|
Vektor auf die Routine der Tastencode-TabellenDas Betriebssystem hat eine Routine ab Adresse 60232 (60380 beim VC 20), auf die der Vektor in 655 und 656 zeigt. Sie liest den Codewert derSHIFT-, CTRL- und C=-Taste in der Speicherzelle 653 aus und verändert entsprechend den Vektor der Zellen 245 und 246, so daß er auf die richtige Codetabelle zeigt. Es gibt Anwenderprogramme, die diesen Vektor so verbiegen, daß die Decodierung der Tasten umgangen und durch eine andere, selbstgebaute Routine ersetzt wird. So kann zum Beispiel das Drücken einer bestimmten Taste umgemünzt werden in Ausdrucken von Basic-Befehlen auf dem Bildschirm. |
Zeiger für Tastatur-DekodierungHier steht ein Zeiger, der auf die Betriebssystemroutine für die Tastatur- Dekodierung zeigt. |
Indirect for keyboard table setup | Vector: Keyboard Table Setup | Vector: Routine to determine Keyboard table to use based on Shift Key Pattern ($EB48). | Keyboard table setup pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0291 | MODE | 657 |
Flag: Enable or Disable Changing Character Sets with SHIFT/Logo KeypressThis flag is used to enable or disable the feature which lets you switch between the uppercase/graphics and upper/lowercase character sets by pressing the SHIFT and Commodore logo keys simultaneously. This flag affects only this special SHIFT key function, and does not affect the printing of SHIFTed characters. POKEing a value of 128 ($80) here will disable this feature, while POKEing a value of 0 will enable it once more. The same effect can be achieved by PRINTing CHR$(8) or CTRL-H to disable the switching of character sets, and CHR$(9) or CTRL-I to enable it. See entries for locations 53272 ($D018) and 49152 ($C000) for more information on switching character sets. |
Flagge für Verriegelung der Zeichensatz-UmschaltungDurch gleichzeitiges Drücken der SHIFT- und der Commodore-Taste wird bekanntlich der Zeichensatz 1 (Großbuchstaben und Grafik-Zeichen) umgeschaltet auf den Zeichensatz 2 (Groß- und Kleinbuchstaben), ein zweites Drücken der beiden Tasten schaltet den Zeichensatz zurück. Diese Umschaltung wird verriegelt, wenn in der Speicherzelle 657 eine 128 steht. Eine 0 läßt die Umschaltung zu. Dieser Effekt kann auf zwei, beim C 64 sogar auf drei Arten erzielt werden:
|
Flag für SHIFT/Commodore gesperrtFalls in der Speicherzelle eine 128 steht, wird eine Umschaltung mit SHIFT/Commodore verriegelt. Bei einer 0 wird die Umschaltung zugelassen. |
Commodore-Shift switchBits:
|
0-PET mode, 1-cattacanna | Flag: $00=Disable SHIFT Keys, $80=Enable | Flag: Upper/Lower Case change: $00 = Disabled, $80 = Enabled ($00). | Keyboard shift mode | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0292 | AUTODN | 658 |
Flag: Screen Scrolling EnabledThis location is used to determine whether moving the cursor past the fortieth column of a logical line will cause another physical line to be added to the logical line. A value of 0 enables the screen to scroll the following lines down in order to add that line; any nonzero value will disable the scroll. This flag is set to disable the scroll temporarily when there are characters waiting in the keyboard buffer (these may include cursor movement characters that would eliminate the need for a scroll). |
Flagge für ScrollenDie Flagge in dieser Speicherzelle legt fest, ob eine weitere echte Zeile zu einer logischen Zeile hinzugefügt wird, sobald der Cursor über das 40ste Zeichen der Zeile (22ste Zeichen beim VC 20) hinausläuft. Steht in 658 eine 0, dann werden alle Zeilen hochgeschoben (man nennt das »scrollen«), um der neuen Zeile Platz zu machen. Wenn in der Zeile irgendein Wert größer als Null steht, unterbleibt dieses Scrollen. Die Flagge wird immer dann auf den höheren Wert gesetzt, wenn Zeichen im Tastaturpuffer (631 bis 640) stehen und darauf warten, am Ende des Programms ausgedruckt beziehungsweise ausgeführt zu werden. Diese Verriegelung wird deshalb eingesetzt, weil im Tastaturpuffer Zeichen wie zum Beispiel Cursor- Bewegungen stehen können. Von Basic aus kann diese Speicherzelle nicht beeinflußt werden. |
Flag für ScrollenWenn in dieser Speicherzelle eine 0 steht, setzt der Scroll-Vorgang ein. Bei einem größeren Wert setzt dieser Vorgang nicht ein. |
Scroll direction switch during scrolling the screenValues:
|
Auto scroll down flag(=0 on,<>0 off) | Flag: Auto Scroll Down, 0 = ON | Flag: Auto scroll down: $00 = Disabled ($00). | 0 = scroll enable | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0293-$0297 | 659-663 |
RS-232 Pseudo 6551 RegistersFor serial Input/Output via the RS-232 port, the internal software of the Commodore 64 emulates the operation of a 6551 UART chip (that's Universal Asynchronous Receiver/Transmitter, for you acronym buffs), also known as an ACIA (Asynchronous Communications Interface Adapter). These RAM locations are used to mimic the functions of that chip's hardware command, control, and status registers. Although RAM locations are allocated for mimicking the 6551's ability to use either an on-board baud rate generator or an external clock crystal, this function is not implemented by the internal software. Provisions have been made for the user to communicate with these registers through the RS-232 OPEN command. When device 2 is opened, a filename of up to four characters may be appended. These four characters are copied to locations 659-662 ($0293-$0296), although the last two, which specify a nonstandard baud rate, are not used because that feature is not implemented. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0293 | M51CTR | 659 |
RS-232: Mock 6551 Control RegisterThis location is used to control the RS-232 serial I/O baud rate (speed at which data is transmitted and received), the word length (number of bits per data character), and the number of stop bits used to mark the end of a transmitted character. It uses the same format as that of the 6551 UART control register to set these parameters, although, as you will see, some of the 6551 configurations are not implemented by the software that emulates the UART device. For example, the standard baud rates which are higher than 2400 baud are not implemented, presumably because the software cannot keep up at higher rates. The meanings of the various bit patterns are as follows: Bit 7: STOP Bits
Bits 6-5: WORD LENGTH
Bit 4: Unused Bits 3-0: BAUD RATE
This register is the only one which must be set when opening RS-232 device (number 2). The first character of the filename will be stored here. For example, the statement OPEN 2,2,0,CHR$(6+32) will set the value of this location to 38. As you can see from the above chart, this sets up the RS-232 device for a data transfer rate of 300 baud, using seven data bits per character and one stop bit. |
RS232-SteuerregisterJeder OPEN-Befehl, mit dem bekanntlich eine Datei (File) eröffnet wird, kann neben File-Nummer und Geräte-Nummer auch einen File-Namen haben. Der File-Namen einer RS232-Schnittstelle hat maximal nur vierZeichen. Das erste Zeichen wird in diese Speicherzelle 659 gebracht und steuert dort Übertragungsgeschwindigkeit, die Wortlänge und die Anzahl der Stopp-Bits. Die nähere Bedeutung dieser Fachwörter können Sie dem Texteinschub Nr. 29 »Die Elemente der RS232-Schnittstelle« entnehmen. Tabelle 11 zeigt die Bedeutung jedes einzelnen Bits dieser Speicherzelle. Die praktische Anwendung dieser Bit-Werte innerhalb eines OPEN-Befehls ist ausführlich im Texteinschub Nr. 30 »Die Programmierung der RS232-Schnittstelle« beschrieben. |
RS-232 KontrollwertHier wird die Übertragungsgeschwindigkeit der RS-232 Schnittstelle festgelegt: Bits 0-3 steuern die Übertragungsgeschwindigkeit:
Bit 4 nicht belegt Die Bits 5 und 6 steuern die Länge der Übertragung:
Bit 7 gibt die Anzahl der STOP-Bits an:
|
RS232 control registerBits:
|
6551 control register | RS-232: 6551 Control Register Image | RS232 Pseudo 6551 control Register Image. | RS-232 control reg | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0294 | M51CDR | 660 |
RS-232: Mock 6551 Command RegisterThis location performs the same function as the 6551 UART chip's command register, which specifies type of parity, duplex mode, and handshaking protocol. The type of parity used determines how the 64 will check that RS-232 data is received correctly. The duplex mode can be either full duplex (the 64 will be able to transmit at the same time it is receiving) or half duplex (it will take turns sending and receiving). The handshaking protocol has to do with the manner in which the sending device lets the receiver know that it is ready to send data, and the receiver lets the sender know that it has gotten the data correctly. The meanings of the bit patterns in this register are as follows: Bits 7-5: Parity
Bit 4: Duplex
Bits 3-1: Unused Bit 0: Handshake Protocol
This register can be set at the user's option when opening RS-232 device (number 2). The second character of the filename will be stored here. For example, the statement OPEN 2,2,0,CHR$(6+32)+CHR$(32+16) will set the value of this location to 48, which is the value of the second character in the filename portion of the statement. As you can see from the above chart, this configures the RS-232 device for half duplex data transfer using odd parity and three-line handshaking. |
RS232-BefehlsregisterIn diese Speicherzelle wird, ähnlich wie bei der Zelle 659, das zweite Zeichen des File-Namens gebracht. Die einzelnen Bits steuern das Handshake-Protokoll (3-/X-Leitung), den Duplex-Modus (Halb-/Voll-Duplex) und die Parity-Prüfung (keine, gerade, ungerade). Die nähere Bedeutung dieser Fachwörter können Sie dem Texteinschub Nr. 11 »Die Elemente der RS232-Schnittstelle« entnehmen. Tabelle 12 zeigt die Bedeutungjedes einzelnen Bits dieser Speicherzelle. Wenn Sie sich für die praktische Anwendung dieser Bit-Werte innerhalb eines OPEN-Befehls interessieren, dann verweise ich an dieser Stelle auf den Texteinschub Nr. 30 »Die Programmierung der RS232-Schnittstelle«. |
RS-232 BefehlswortDie einzelnen Bits steuern das 'Handshake'-Protokol1. |
RS232 command registerBits:
|
6551 command register | RS-232: 6551 Command Register Image | RS232 Pseudo 6551 command Register Image. | RS-232 command reg | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0295-$0296 | M51AJB | 661-662 |
RS-232: Nonstandard Bit TimingThese locations are provided for storing a nonstandard user-defined baud rate, to be used when the low nybble of the control register at 659 ($0293) is set to 0. They were presumable provided to conform to the nodel of the 6551 UART device, which allows a nonstandard baud rate to be generated from an external reference crystal. However, the software emulation of that feature is not provided in the current version of the Kernal, and thus these locations are currently nonfunctional. Nonetheless, Commodore has specified that if the nonstandard baud rate feature is implemented, the value placed here should equal the system clock frequency divided by the baud rate divided by 2 minus 100, stored in low byte, high byte order. The system clock frequency for American television monitors (NTSC standard) is 1.02273 MHz, and for European monitors (PAL standard) .98525 MHz. |
RS232 frei wählbare ÜbertragungsgeschwindigkeitEs war ursprünglich vorgesehen, durch entsprechendeWahl des dritten und vierten Zeichens im File-Namen beliebige Übertragungsgeschwindigkeiten einzustellen. Die jeweiligen Werte sollten die Speicherzellen 661 und 662 enthalten. Diese Möglichkeit wurde aber nicht eingebaut. Der Grund dafür dürfte wohl der sein, daß die wählbaren Übertragungsgeschwindigkeiten aller Geräte auf bestimmte Werte normiert sind. |
Bit-TimingDie Möglichkeit, eine freiwählbare Übertragungsgeschwindigkeit einzustellen, wurde vorgesehen, aber nicht eingebaut. |
Default value of RS232 output timer, based on baud rate(Must be filled with actual value before RS232 input/output if baud rate is "user specified" in RS232 control register, memory address $0293.) |
Non standard (bittime/2-100) | RS-232 Non-Standard BPS (Time/2-100) USA | RS232 Non-standard Bits/Second. | Bit timing | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0297 | RSSTAT | 663 |
RS-232: Mock 6551 Status RegisterThe contents of this register indicate the error status of RS-232 data transmission. That status can be determined by PEEKing this location directly, by referencing the BASIC reserved variable ST, or by using the Kernal READST (65031, $FE07) routine. Note that if you use ST or Kernal, this location will be set to 0 after it is read. Therefore, if you need to test more than one bit, make sure that each test preserves the original value, because you won't be able to read it again. The meaning of each bit value is specified below:
The user is responsible for checking these errors and taking appropriate action. If, for example, you find that Bit 0 or 1 is set when you are sending, indicating a framing or parity error, you should resend the last byte. If Bit 2 is set, the GET#2 command is not being executed quickly enough to empty the buffer (BASIC should be able to keep up at 300 baud, but not higher). If Bit 7 is set, you will want to stop sending, and execute a GET#2 to see what is being sent. |
RS232-StatusregisterGenauso wie in der Speicherzelle 144 der Status aller Ein- und Ausgabe- Operationen angezeigt wird, werden alle Fehler der RS232-Schnittstelle in der Speicherzelle 663 angezeigt. Die Bedeutung der einzelnen Bits, wenn sie auf 1 gesetzt sind, zeigt Tabelle 14. Der Status wird nicht automatisch angezeigt, sondern muß vom Programm abgefragt werden. Abfragen können Sie sowohl durch PEEKen der Speicherzelle 663 als auch durch Aufrufen der Statusvariablen ST. Die Variable ST, die normalerweise den Inhalt der Zelle 144 wiedergibt, schaltet nach dem Eröffnen eines RS232-Kanals durch OPEN 1,2 auf die Speicherzelle 663 um. Jedoch ist Vorsicht geboten, da durch Aufruf von ST der Inhalt von 663 gelöscht wird. Es ist ratsam, den Wert von ST erst einer anderen Variablen zuzuordnen, wenn sie mehrfach verwendet werden soll. Falls das Status-Register einen Fehler anzeigt, muß das Programm entsprechende Konsequenzen ziehen. Wenn zum Beispiel Bit 0 oder Bit 1 gesetzt sind, ist es angebracht, das letzte Daten-Byte noch einmal zu übertragen. Wenn Bit 2 gesetzt ist, heißt dies, daß der GET #-Befehl den Eingabepufferspeicher nicht schnell genug entleert. Falls die Übertragungsgeschwindigkeit von 300 Bit/s, die maximal mit einem Basic-Programm erreichbar ist, nicht ausreicht, muß entweder der Sender langsamer eingestellt werden, oder Sie schreiben das Programm in Maschinensprache. |
RS-232 StatusHier werden die Fehlermeldungen der RS-232 Schnittstelle angezeigt:
|
Value of ST variable, device status for RS232 input/outputBits:
|
RS-232 status register | RS-232: 6551 Status Register Image | RS232 Pseudo 6551 Status Register Image. | RS-232 status | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0298 | BITNUM | 664 |
RS-232: Number of Bits Left to be Sent/ReceivedThis location is used to determine how many zero bits must be added to the data character to pad its length out to the word length specified in 659 ($0293). |
RS232 - Anzahl der zu übertragenden BitsDiese Speicherzelle wird verwendet, um festzustellen, mit wievielen Nullen das zu übertragende Zeichen aufgefüllt werden muß, um die in Speicherzelle 659 (Bit 5 und 6) ausgewählte Wortlänge herzustellen (s. Speicherzellen 168 und 180). |
Anzahl der Datenbits für RS-232Diese Speicherzelle wird verwendet, um die Wortlänge festzustellen. |
RS232 byte size, number of data bits per data byte, default value for bit counters. | Number of bits to send (fast response) | RS-232 Number of Bits Left to Send | RS232 Number of Bits left to send. | # bits to send | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0299-$029A | BAUDOF | 665-666 |
Time Required to Send a BitThis location holds the prescaler value used by CIA #2 timers A and B. These timers cause an NMI interrupt to drive the RS-232 receive and transmit routines CLOCK/PRESCALER times per second each, where CLOCK is the system 02 frequency of 1,022,730 Hz (985,250 if you are using the European PAL television standard rather than the American NTSC standard), and PRESCALER is the value stored at 56580-1 ($DD04-5) and 56582-3 ($DD06-7), in low-byte, high-byte order. You can use the following formula to figure the correct prescaler value for a particular RS-232 baud rate: PRESCALER=((CLOCK/BAUDRATE)/2)-100 The American (NTSC standard) prescaler values for the standard RS-232 baud rates which the control register at 659 ($0293) makes available are stored in a table at 65218 ($FEC2), starting with the two-byte value used for 50 baud. The European (PAL standard) version of that table is located at 58604 ($E4EC). |
RS232 - Zeit, die zum Übertragen eines Bits gebraucht wirdSobald ein RS232-Kanal eröffnet worden ist, berechnet das Betriebssystem einen Wert, der die Zeitdauer eines Bits festlegt. Da die Übertragungsrate in Speicherzelle 659 einstellbar ist, hängt diese Bit-Dauer von der gewählten Übertragungsgeschwindigkeit ab. Die Bit-Dauer errechnet sich aus der Systemfrequenz (985,25 kHz) geteilt durch die Übertragungsgeschwindigkeit. Dieser Wert steht in Low-/High-Byte-Darstellung in diesen beiden Speicherzellen, von wo aus er vom Betriebssystem abgerufen wird. |
RS-232 Baud-RateDie Übertragungsrate errechnet sich aus der Systemfrequenz (985.25) KHz dividiert duch die Baudrate. Dieser Wert steht in LOW- und HIGH-Byte-Darstellung in den beiden Speicherzellen. Er wird vom Betriebssystem abgerufen. |
Baud rate full bit time (created by open) | RS-232 Baud Rate: Full Bit Time (us) | RS232 Baud Rate; Full Bit time microseconds. | RS-232 speed/code | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$029B-$029E | 667-670 |
Byte Indices to the Beginning and End of Receive and Transmit BuffersThe two 256-byte First In, First Out (FIFO) buffers for RS-232 data reception and transmission are dynamic wraparound buffers. This means that the starting point and the ending point of the buffer can change over time, and either point can be anywhere withing the buffer. If, for example, the starting point is at byte 100, the buffer will fill towards byte 255, at which point it will wrap around to byte 0 again. To maintain this system, the following four locations are used as indices to the starting and the ending point of each buffer. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$029B | RIDBE | 667 |
RS-232: Index to End of Receive BufferThis index points to the ending byte within the 256-byte RS-232 receive buffer, and is used to add data to that buffer. |
RS232-Index auf das Ende des EingabepufferspeichersDieser Index wird verwendet, um Daten in den Eingabepufferspeicher zu schreiben. Wenn man ihn nämlich zum Inhalt der Speicherzelle 247/248 addiert, erhält man die Adresse des zuletzt in den Eingabepufferspeicher eingegebenen Bytes. |
Offset of byte received in RS232 input buffer. | Input buffer index to end | RS-232 Index to End of Input Buffer | RS232 Index to End of Input Buffer. | RS232 receive pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$029C | RIDBS | 668 |
RS-232: Index to Start of Receive BufferThis index points to the starting byte within the 256-byte RS-232 receive buffer, and is used to remove data from that buffer. |
RS232-Index auf den Anfang des EingabepufferspeichersDieser Index wird verwendet, um Daten aus dem Eingabepufferspeicher auszulesen. Wenn man ihn nämlich zum Inhalt der Speicherzelle 247 und 248 addiert, erhält man die Adresse des ersten in den Eingabepufferspeicher eingegebenen Bytes. |
Offset of current byte in RS232 input buffer. | Input buffer pointer to start | RS-232 Start of Input Buffer (Page) | RS232 Pointer: High Byte of Address of Input Buffer. | RS232 input pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$029D | RODBS | 669 |
RS-232: Index to Start of Transmit BufferThis index points to the starting byte within the 256-byte RS-232 transmit buffer, and is used to remove data from that buffer. |
RS232-Index auf den Anfang des AusgabepufferspeichersDieser Index wird verwendet, um Daten aus dem Ausgabepufferspeicher auszulesen. Wenn man ihn nämlich zum Inhalt der Speicherzelle 249 und 250 addiert, erhält man die Adresse des ersten in den Ausgabepufferspeicher eingegebenen Bytes. |
Offset of byte to send in RS232 output buffer. | Output buffer index to start | RS-232 Start of Output Buffer (Page) | RS232 Pointer: High Byte of Address of Output Buffer. | RS232 transmit pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$029E | RODBE | 670 |
RS-232: Index to End of Transmit BufferThis index points to the ending byte within the 256-byte RS-232 transmit buffer, and is used to add data to that buffer. |
RS232-Index auf das Ende des AusgabepufferspeichersDieser Index wird verwendet, um Daten in den Ausgabepufferspeicher zu schreiben. Wenn man ihn nämlich zum Inhalt der Speicherzelle 249 und 250 addiert, erhält man die Adresse des zuletzt in den Ausgabepufferspeicher eingegebenen Bytes. |
Offset of current byte in RS232 output buffer. | Output buffer index to end | RS-232 Index to End of Output Buffer | RS232 Index to End of Output Buffer. | RS232 output pointer | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$029F-$02A0 | IRQTMP | 671-672 |
Save Area for IRQ Vector During Cassette I/OThe routines that read and write tape data are driven by an IRQ interrupt. In order to hook one of these routines into the interrupt, the RAM IRQ vector at 788-789 ($0314-$0315) must be changed to point to the address at which it starts. Before that change is made, the old IRQ vector address is saved at these locations, so that after the tape I/O is finished, the interrupt that is used for scanning the keyboard, checking the stop key, and updating the clock can be restored. You will note that all of the above functions will be suspended during tape I/O. |
Zwischenspeicher für den IRQ-Vektor während Kassetten-Ein-/AusgabeDie Routinen des Betriebssystems, die Daten auf, beziehungsweise von Kassette ein- und ausgeben, werden durch die Interrupt-Routine gesteuert. Diese Routine unterbricht normalerweise 60mal in der Sekunde alle Aktivitäten des Computers, um diverse »Hausaufgaben« (Uhr weiterschalten, STOP-Taste abfragen und so weiter) auszuführen. Bei Kassetten-Ein-/Ausgaben ist diese Interrupt-Routine jedoch abgeschaltet. Dies wird dadurch erreicht, daß der Vektor in Speicherzelle 788 und 789, der auf die Anfangsadresse der Interrupt-Routine zeigt, auf eine Adresse der Kassetten-Routine gesetzt wird. Um nach der Kassettenoperation weitermachen zu können, wird der »alte« Interrupt-Vektor in dieser Speicherzelle 671 und 672 gespeichert. |
Speicher für IRQ während BandbetriebBei Kassettenoperationen wird hier in LOW- und HIGH-Byte-Darstellung der Vektor für die Interruptroutine gespeichert. |
Holds irq during tape ops | Holds IRQ Vector During Tape I/O | Temporary store for IRQ Vector during Tape operations. | IRQ save during tape I/O | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02A1 | ENABL | 673 |
RS-232 Interrupts EnabledThis location holds the active NMI interrupt flag byte from CIA #2 Interrupt Control Register (56589, $DD0D). The bit values for this flag are as follows:
|
bei C 64: Flagge für RS232-Interrupt bei VC 20: frei verfügbarDiese Speicherzelle enthält den Wert des Interrupt-Steuerregisters 56589, das die RS232-Schnittstelle steuert. Die Bedeutung der einzelnen Bits, wenn sie auf 1 gesetzt sind, zeigt Tabelle 15. Diese Flagge kann zu Steuerzwecken abgefragt werden. Um beispielsweise ein Programm warten zu lassen, bis der Ausgabepufferspeicher geleert ist, gibt man die Anweisung
die das Programm so lange aufhält, bis die Übertragung abgeschlossen und Bit O der Flagge gelöscht ist. Die folgenden 4 Speicherzellen, nämlich 674 bis 678, werden nur vom C 64 benutzt. Beim VC 20 sind sie nicht belegt und können frei verwendet werden. |
CIA 2 NMI-FlagDiese Speicherzelle erhält den Wert des Interruptsteuerregisters, das die RS-232 Schnittstelle steuert. |
Temporary area for saving original value of CIA#2 interrupt control register, at memory address $DD0D, during RS232 input/output. | RS-232 enables (replaces ier) | RS-232 Enables | RS232 Enables. | CIA 2 (NMI) Interrupt Control | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02A2 | CASTON | 674 | Indicator of CIA #1 Control Register B Activity During Cassette I/O |
Indikator für das Steuerregister A des CIA #1Mit CIA werden die beiden »Complex Interface Adapter« des C 64 bezeichnet. Das sind integrierte Schaltkreise, die Ein- und Ausgabeoperationen steuern. Jeder der beiden CIAs hat mehrere Register. Das Steuerregister A (Adresse 56334 beziehungsweise $DC0E) beeinflußt die Zählregister des CIA, die ihrerseits die Ein- und Ausgabe von Daten auf beziehungsweise von Kassetten steuern. Das Betriebssystem speichert zu diesem Zweck geeignete Bitmuster in der Speicherzelle 674 ab, die von da in das Steuerregister transferiert werden. |
CIA 1 Timer ABei Bandroutinen wird hier das HIGH-Byte von Timer A zwischengespeichert. |
Temporary area for saving original value of CIA#1 timer #1 control register, at memory address $DC0E, during datasette input/output. | TOD sense during cassettes | TOD Sense During Cassette I/O | TOD sense during Tape I/O. | CIA 1 Timer A control log | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02A3-$02A4 | 675-676 | Unknown. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02A3 | KIKA26 | 675 | Save Area for CIA #1 Interrupt Control Register During Cassette Read |
Speicher für das Interrupt- Steuerregister B des CIA #1Ein weiteres Register (Adresse 56333 beziehungsweise $DC0D) ist für die Unterbrechungen (Interrupt) des Computers bei Ein- und Ausgaben zuständig. In der Speicherzelle 675 werden Werte dieses Interruptregisters beim Lesen von der Kassette zwischengespeichert. |
CIA 1 InterruptflagBei Bandroutinen wird in dieser Speicherzelle festgelegt, welche IRQs freigegeben sind und welche nicht. |
Cassette: holds old D1ICR after clear on read | Temp Storage For Cassette Read | Temporary storage during Tape READ. | CIA 1 Interrupt Log | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02A4 | STUPID | 676 | Save Area for CIA #1 Control Register A During Cassette Read |
Zusatzspeicher für Steuerregister B des CIA #1Derselbe Wert, der bei der Vorbereitung des Lesevorganges von der Kassette in die Speicherzelle 674 kommt, gelangt auch nach 676, von wo er zu einem späteren Zeitpunkt beim Lesen zu Vergleichszwecken herangezogen wird. |
CIA 1 Flag für Timer AHier wird bei Bandroutinen angegeben, ob Timer A läuft oder nicht. Wenn hier eine $00 steht, ist der Timer freigegeben, andernfalls ist er gesperrt. |
Cassette: hold indicator (NZ - no T1IRQ yet) for T1IRQ | Temp D1 IRQ Indicator For Cassette Read | Temporary D1IRQ Indicator during Tape READ. | CIA 1 Timer A enabled flag | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02A5 | LINTMP | 677 | Temporary Index to the Next 40-Column Line for Screen Scrolling |
Zwischenspeicher für das Link-Byte während des Bildschirm-ScrollensDas Betriebssystem enthält eine Routine, welche den Bildschirminhalt hochschiebt (scrollt), sobald eine leere Zeile eingeschoben wird. Das bedeutet, daß jedesmal die Angaben in den Link-Tabellen der Speicherzellen 217 bis 241 geändert werden müssen. In der Speicherzelle 677 wird nun das Link-Byte zwischengespeichert, während der obere Teil des Bildschirms hochgeschoben wird. Beim VC 20 gibt es diese Funktion übrigens auch. Sie wird durch die Speicherzelle 242 ausgefüllt. |
Bildschirmzeile | Number of line currently being scrolled during scrolling the screen. | Temporary for line index | Temp For Line Index | Temporary for Line Index. | Screen row marker | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02A6 | PALNTS | 678 |
PAL/NTSC FlagAt power-on, a test is performed to see if the monitor uses the NTSC (North American) or PAL (European) television standard. This test is accomplished by setting a raster interrupt for scan line 311, and testing if the interrupt occurs. Since NTSC monitors have only 262 raster scan lines per screen, the interrupt will occur only if a PAL monitor is used. The results of that test are stored here, with a 0 indicating an NTSC system in use, and one signifying a PAL system. This information is used by the routines which set the prescaler values for the system IRQ timer, so that the IRQ occurs every 1/60 second. Since the PAL system 02 clock runs a bit slower than the NTSC version, this prescaler value must be adjusted accordingly. |
Flagge für PAL oder NTSCIm Gegensatz zum VC 20, der entweder fest auf die deutsche Fernsehnorm PAL oder aber auf die amerikanische Norm NTSC eingestellt ist, kann der C 64 beide Normen verkraften. Diese beiden Normen beziehen sich unter anderem auf die Anzahl der Zeilen und auf die Abtast-Geschwindigkeit des Lichtstrahls im Fernsehgerät oder im Monitor. Das Betriebssystem des C 64 überprüft gleich beim Einschalten, ob eine Rasterzeile 311 im angeschlossenen Sichtgerät vorhanden ist. Ist sie nicht vorhanden, muß alles auf die NTSC-Norm eingestellt werden, da diese nur 262 Rasterzeilen hat und mit einer internen Taktfrequenz von 14,3 MHz läuft. Ist eine Rasterzeile 311 vorhanden, wird auf PAL-Norm eingestellt mit einer Taktfrequenz von 17,7 MHz. Das Resultat dieses Tests wird in der Speicherzelle 678 gespeichert: als 0 für NTSC und 1 für PAL. |
Flag für PAL- (1) o. NTSC-Version (0)Hier steht ein Wert, der angibt, ob es sich um eine PAL- oder eine NTSC- Version handelt. |
PAL/NTSC switch, for selecting RS232 baud rate from the proper tableValues:
|
PAL vs NTSC flag 0=NTSC 1=PAL | PAL/NTSC Flag, 0= NTSC, 1 = PAL | Flag: TV Standard: $00 = NTSC, $01 = PAL. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$02A7-$02FF | 679-767 |
UnusedThe programmer may use this area for machine language subroutines, or for graphics data storage. If the VIC-II ship is using the bottom 16K for graphics and memory (the default setting when the system is turned on), this is one of the few free areas available for storing sprite or character data. Locaitons 704-767 could be used for sprite data block number 11, without interfering with BASIC program text or variables. |
nicht belegtDiese 89 Byte sind frei und können für alle möglichen Programme und Anwendungen verwendet werden. Beim VC 20 stehen sogar 95 Byte zur Verfügung, da der freie Bereich ja schon ab Speicherzelle 673 beginnt. Dieser Speicherbereich hat den Vorteil, daß er - wie der Kassettenpuffer ja auch - von Basic nicht gestört wird. Er kann also für kleinere Maschinenprogramme oder auch für Sprite-Blöcke verwendet werden. Gegenüber dem Kassettenpuffer hat dieser Bereich den Vorteil, daß er durch Kassettenoperationen nicht gestört wird. |
Unused (89 bytes). | Unused | Unused. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0300-$030B | 768-779 |
BASIC Indirect Vector TableSeveral important BASIC routines are vectored through RAM. This means that the first instruction executed by the routine is an indirect jump to a location pointed to by one of the vectors in this table. On power up, the system sets these vectors to point to the next instruction past the original JuMP instruction. The routine then continues with that instruction as if the jump never took place. For example, the BASIC error message routine starts at 42039 ($A437) with the instruction JMP ($0300). The indirect vector at 768 ($0300) points to 42042 ($A43A), which is the instruction immediately following JMP ($0300). Although this may seem like a fancy way of accomplishing nothing, using these indirect vectors serves two important purposes. First, it allows you to use these important BASIC routines without knowing their addresses in the BASIC ROM. For example, the routine to LIST the ASCII text of the single-byte BASIC program token that is currently in the Accumulator (.A) is located at one address in the VIC, and another in the 64. On future Commodore computers it may be found at still another location. Yet as long as the routine is vectored in RAM at 774 ($0306), the statement QP=PEEK(774)+256*PEEK(775) would find the address of that routine on any of the machines. Thus, entering such routines through RAM vectors rather than a direct jump into the ROMs helps to keep your programs compatible with different machines. The other important effect of having these vectors in RAM is that you can alter them. In that way, you can redirect these important BASIC routines to execute your own preprocessing routines first. If you wanted to add commands to BASIC, for example, how would you go about it? First, you would need to change the BASIC routines that convert ASCII program text to tokenized program format, so that when a line of program text was entered, the new keyword would be stored as a token. Next, you would need to change the routine that executes tokens, so that when the interpreter comes to your new keyword token, it will take the proper action. You would also have to change the routine that converts tokens back to ASCII text, so that your program would LIST the token out correctly. And you might want to alter the routine that prints error messages, to add new messages for your keyword. As you will see, vectors to all of these routines can be found in the following indirect vector table. Changing these vectors is a much more elegant and efficient solution than the old wedge technique discussed at location 115 ($73) |
…Die nächsten 12 Speicherzellen enthalten 6 Vektoren, deren Bedeutung bei der Übersetzung von Basic-Programmen im Texteinschub Nr. 31 »Indirekte Sprung- Vektoren« näher erklärt wird. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0300-$0301 | IERROR | 768-769 |
Vector to the Print BASIC Error Message RoutineThis vector points to the address of the ERROR routine at 58251 ($E38B). |
Vektor auf die Ausgabe von Fehler-Meldungen (ERROR)Dieser Vektor zeigt auf die Anfangsadresse der Basic-Routine, welche für die leidigen Fehlermeldungen zuständig ist. Beim C 64 zeigt der Vektor auf 58251 ($E38B), beim VC 20 auf 50234 ($C438). Diese Routine verwendet eine Tabelle im Basic-Übersetzer, in der alle Fehlermeldungen gespeichert sind. Sie liegt im Speicherbereich 41374 bis 41767 (beim VC 20 49566 bis 49959). Die Routine verwendet den Inhalt des X-Registers (siehe Speicherzelle 781), um die entsprechende Fehlermeldung ganz einfach durch Abzählen der Reihenfolge aus der Tabelle auszulesen und auf dem Bildschirm anzuzeigen. Ein Verbiegen dieses Vektors ist für zwei Anwendungsfälle sinnvoll. Man kann die Fehlermeldung abschalten, um zu prüfen, ob ein bestimmtes Peripherie-Gerät, zum Beispiel das Floppylaufwerk, angeschlossen beziehungsweise eingeschaltet ist. Die Fehlermeldung ist abschaltbar mit POKE 768,61. Wieder eingeschaltet wird sie mit POKE 768,139. Ein Anwendungsbeispiel habe ich bereits im Texteinschub Nr. 14 »ST-atus« gebracht. Die zweite Anwendung einer Verbiegung zielt auf eine Übersetzung der Fehlermeldungen. Wem der vorgegebene englische - und manchmal nicht gerade einleuchtende - Text der Fehlermeldungen nicht gefällt, kann den Vektor auf einen Speicherbereich legen, in dem er seine speziellen deutschen Fehlermeldungen speichert. Eine genaue Kenntnis der Fehlermeldungsroutine ist dazu allerdings erforderlich. (Die nächsten 12 Speicherzellen enthalten 6 Vektoren, deren Bedeutung bei der Übersetzung von Basic-Programmen im Texteinschub Nr. 31 »Indirekte Sprung- Vektoren« näher erklärt wird.) |
$E38B Vektor für BASIC-Warmstart |
Execution address of warm reset, displaying optional BASIC error message and entering BASIC idle loop.Default: $E38B. |
indirect ERROR (output error in .X) | Vector: Print BASIC Error Message | Vector: Indirect entry to BASIC Error Message, (X) points to Message ($E38B). | Error message link | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0302-$0303 | IMAIN | 770-771 |
Vector to the Main BASIC Program LoopThis vector points to the address of the main BASIC program loop at 42115 ($A483). This is the routine that is operating when you are in the direct mode (READY). It executes statements, or stores them as program lines. |
Vektor auf die Hauptroutine zur Ausführung von Basic-BefehlenDieser Vektor zeigt auf die Adresse 42115 ($A483), beim VC 20 auf 50307 ($C483). Die dort beginnende Routine steuert den Direkt-Modus, indem sie entweder direkt eingegebene Befehle ausführt oder mit Zeilennummer eingegebene Anweisungen speichert. |
$A483 Vektor für Eingabe einer Zeile |
Execution address of BASIC idle loop.Default: $A483. |
indirect MAIN (system direct loop) | Vector: BASIC Warm Start | Vector: Indirect entry to BASIC Input Line and Decode ($A483). | Basic warm start link | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0304-$0305 | ICRNCH | 772-773 |
Vector to the Routine That Crunches the ASCII Text of Keywords into TokensThis vector points to the address of the CRUNCH routine at 42364 ($A57C). |
Vektor auf die Basic-Routine, die ASCII-Text in Token umwandeltDieser Vektor zeigt auf 42364 ($A57C), beim VC 20 auf 50556 ($C57C). Dort beginnt eine Routine, die nach dem Drücken der RETURN-Taste alle Anweisungen der damit eingegebenen Zeile absucht und Text beziehungsweise Wörter, die nicht zwischen Gänsefüßen stehen, als Basic-Befehle interpretiert und sie dann in sogenannte »Token« umwandelt. Token sind Codezahlen, die im Computer anstelle von Textbefehlen verwendet werden. Sie sind im Texteinschub Nr. 32 »Die Kurzschrift von Basic« näher beschrieben. Dieser Vektor kann verbogen werden, um zusätzliche Basic-Befehle zu erfinden und in das Betriebssystem einzubauen. |
$A57C Vektor für Umwandlung in Interpretercode |
Execution address of BASIC line tokenizater routine.Default: $A57C. |
indirect CRUNCH (tokenization routine) | Vector: Tokenize BASIC Text | Vector: Indirect entry to BASIC Tokenise Routine ($A57C). | Crunch Basic tokens link | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0306-$0307 | IQPLOP | 774-775 |
Vector to the Routine That Lists BASIC Program Token as ASCII TextThis vector points to the address of the QPLOP routine at 42778 ($A71A). |
Vektor auf die Basic-Routine, die Token in ASCII-Werte zurückwandelt (LIST)Dieser Vektor zeigt auf die Adresse 42778 ($A71A), beim VC 20 auf 50970 ($C71A). Dort beginnt eine Routine, die Token wieder in LISTbaren Text umwandelt. Sie steht nicht allein, sondern wird als Unterprogramm von der LIST- Routine verwendet. Falls ein Programmierer spezielle zusätzliche Basic-Befehle erfunden hat, kann er durch Verbiegen dieses Vektors seine eigenen Token lesbar ausLISTen. Man kann auch durch eine entsprechende Verbiegung erreichen, daß die LIST- Routine nicht angesprungen werden kann, was gleichbedeutend ist mit einer LIST- Sperre. Das ist aber wohl nur sinnvoll bei einem Autostart-Programm. Besser finde ich da ein kleines Programm, das J. Pellechi in der Zeitschrift RUN, Ausgabe 6/85 (Seite 10), angegeben hat:
Beim VC 20 ist nur die Zeile 90 verschieden:
In den freien Speicherbereich ab Speicherzelle 679 wird ein kleines Maschinenprogramm gePOKEt, das in den DATA-Zeilen 70 bis 90 steht. In Zeile 50 steht der für unser Beispiel entscheidende Befehl: Der Vektor in 774 und 775 wird nach der Adresse 679 verbogen. Dadurch springt die LIST-Routine immer zuerst auf die Adresse 679, in der sie das kleine Maschinenprogramm findet. Disassembliert schaut das so aus:
Zuerst wird der Akkumulator mit dem Inhalt der Speicherzelle 653 ($028D) geladen. Dort steht bekanntlich eine Zahl von 1 bis 7, je nachdem, ob die SHIFT-, CTRL- oder Commodore-Taste gedrückt ist. Ist dies der Fall, springt das Programm auf die Adresse 680 zurück und bildet so eine Dauerschleife, bis die Taste wieder losgelassen wird. Erst dann geht es weiter mit der ursprünglichen Zieladresse des Vektors in 774 und 775, nämlich $A71A (42778) beziehungsweise $C71A (50970) beim VC 20. Auf diese Weise können Sie das LISTen eines Programms mit einer der drei genannten Tasten anhalten. |
$A71A Vektor für Umwandlung in Klartext (LIST) |
Execution address of BASIC token decoder routine.Default: $A71A. |
indirect LIST (char list) | Vector: BASIC Text LIST | Vector: Indirect entry to BASIC LIST Routine ($A71A). | Print tokens link | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0308-$0309 | IGONE | 776-777 |
Vector to the Routine That Executes the Next BASIC Program TokenThis vector points to the address of the GONE routine at 42980 ($A7E4) that executes the next program token. |
Vektor auf die Basic-Routine, die den nächsten Befehl liest und ausführtDieser Vektor zeigt auf die Adresse 42980 ($A7E4), beim VC 20 auf 51172 ($C7E4). Diese Routine prüft das nächste Token, ob es gültig ist. Wenn der ASCII-Wert des Token kleiner als 128 ist, wird er als Zeichen einerVariablen angesehen, und das System springt auf die LET-Routine. Das erklärt, warum zur Definition einer Variablen der LET-Befehl auch weggelassen werden kann. Durch Verbiegen dieses Vektors kann zum Beispiel eine Trace-Routine gebaut werden, welche zuerst die Nummer der Zeile ausdruckt, die gerade ausgeführt wird, bevor sie auf die ursprüngliche Zieladresse des Vektors zurückkehrt. |
$A7E4 Vektor für BASIC-Befehlsadresse holen |
Execution address of BASIC instruction executor routine.Default: $A7E4. |
indirect GONE (char dispatch) | Vector: BASIC Char. Dispatch | Vector: Indirect entry to BASIC Character dispatch Routine ($A7E4). | Start new Basic code link | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$030A-$030B | IEVAL | 778-779 |
Vector to the Routine That Evaluates a Single-Term Arithmetic ExpressionThis vector points to the address of the EVAL routinea t 44678 ($AE86) which, among other things, is used to evaluate BASIC functions such as INT and ABS. |
Vektor auf die Basic-Routine, die einen numerischen Ausdruck in eine Gleitkommazahl umwandeltDieser Vektor zeigt auf 44675 ($AE83), beim VC 20 auf 52867 ($CE83). Hier beginnt eine Routine, die einen einzelnen numerischen Wert, wenn er Teil eines Ausdrucks ist, von seinem ASCII-Wert in eine Gleitkomma-Zahl umwandelt. Ist der Ausdruck eine Konstante, wird diese Umwandlung durchgeführt. Ist der Ausdruck eine Variable, wird ihr Zahlenwert aus dem Variablenspeicher geholt. Ist der Ausdruck die Zahl »pi«, wird der Zahlenwert für »pi« in den Gleitkomma-Akkumulator gebracht. |
$AE86 Vektor für Ausdruck auswerten |
Execution address of routine reading next item of BASIC expression.Default: $AE86. |
indirect EVAL (symbol evaluation) | Vector: BASIC Token Evaluation | Vector: Indirect entry to BASIC Token evaluation ($AE86). | Get arithmetic element link | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$030C-$030F | 780-783 |
Register Storage AreaThe BASIC SYS command uses this area to store 6510 internal registers--the Accumulator (.A), the .X and .Y index registers, and the status register, .P. Before every SYS command, each of the registers is loaded with the value found in the corresponding storage address. After the ML program finished executing, and returns to BASIC with an RTS instruction, the new value of each register is stored in the appropriate storage address. This is only true of SYS, not of the similar USR command. This feature allows you to place the necessary preentry values into the registers from BASIC before you SYS to a Kernal or BASIC ML routine. It also enables you to examine the resulting effect of the routine on the registers, and to preserve the condition of the registers on exit for subsequent SYS calls. An extremely practical application comes immediately to mind. Although the 64's BASIC 2 has many commands for formatting printed characters on the monitor screen (for example, TAB, SPC, PRINT A$,B), there is none to adjust the vertical cursor position. There is a Kernal routine, PLOT (58634, $E50A), which will allow you to position the cursor anywhere on the screen. In order to use it, you must first clear the carry flag (set it to 0), and then place the desired horizontal column number in the .Y register and the vertical row number in the .X register before entering the routine with a SYS 65520. Using the register storage area, we can print the work HELLO at row 10, column 5 with the following BASIC line:
You can also use these locations to help you take advantage of Kernal routines that return information in the register. For example, the SCREEN routine (58629,$E505) returns the number of screen rows in the .Y register, and the number of columns in the .X register. Using this routine, a BASIC program could be written to run on machines with different screen formats (for example, the 64 and the VIC-20). Just PEEK(781) after a SYS 65517 to see how many screen columns the computer display has. |
Speicher für RegisterDer SYS-Befehl holt aus den nächsten vier Speicherzellen alle notwendigen Parameter, die für ein mit SYS zu startendes Maschinenprogramm notwendig sind. Er speichert sie in die vier Register des Mikroprozessors 6510 (beim VC 20 heißt er 6502). Es sind dies:
Die Bedeutung der Register ist im Assembler-Kurs erklärt worden. Normalerweise funktioniert der SYS-Befehl nur, wenn vorher schon alle Parameter des aufgerufenen Maschinenprogramms richtig vorhanden sind, was meistens nicht der Fall ist. So können Sie zum Beispiel mit Aufrufen der Load-Routine durch SYS 62622 nichts ausrichten, weil die für LOAD erforderlichen Parameter, nämlich Gerätenummer, File-Namen, Anfangs- und Endadresse, nicht festgelegt sind. Wie dies mit Hilfe der vier folgenden Register-Speicherzellen erreichbar ist, hat Rolf Zweifel schon in der Ausgabe 7/84, Seite 131 erklärt. Weil das aber schon lange her ist und weil es hier so schön in den Kurs paßt, wiederhole ich dieses Thema im Texteinschub Nr. 33 »Der vorbereitete SYS-Befehl«. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$030C | SAREG | 780 | Storage Area for .A Register (Accumulator) | Speicher für den Akkumulator | Akku für SYS-Befehl |
Default value of register A for SYS. Value of register A after SYS. |
.A reg | Storage for 6502 .A Register | Storage for 6510 Accumulator during SYS. | SYS A-reg save | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$030D | SXREG | 781 | Storage Area for .X Index Register | Speicher für das X-Register | X-REG für SYS-Befehl |
Default value of register X for SYS. Value of register X after SYS. |
.X reg | Storage for 5502 .X Register | Storage for 6510 X-Register during SYS. | SYS X-reg save | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$030E | SYREG | 782 | Storage Area for .Y Index Register | Speicher für das Y-Register | Y-REG für SYS-Befehl |
Default value of register Y for SYS. Value of register Y after SYS. |
.Y reg | Storage for 6502 .Y Register | Storage for 6510 Y-Register during SYS. | SYS Y-reg save | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$030F | SPREG | 783 |
Storage Area for .P (Status) RegisterThe Status (.P) register has seven different flags. Their bit assignments are as follows:
If you wish to clear any flag before a SYS, it is safe to clear them all with a POKE 783,0. The reverse is not true, however, as you must watch out for the Interrupt disable flag. A 1 in this flag bit is equal to an SEI instruction, which turns off all IRQ interrupts (like the one that reads the keyboard, for example). Turning off the keyboard could make the computer very difficult to operate! To set all flags except for Interrupt disable to 1, POKE 783,247. |
Speicher für das Statusregister | tatus-Register für SYS-Befehl |
Default value of status register for SYS. Value of status register after SYS. |
.P reg | Storage for 6502 .SP Register | Storage for 6510 Status Register during SYS. | SYS status reg save | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0310-$0312 | USRPOK | 784-786 |
Sprungbefehl und wählbare Sprungadresse des USR-BefehlsMit dem Basic-Befehl USR wird bekanntlich ein Maschinenprogramm gestartet. Diese drei Speicherzellen werden bei der Abwicklung von USR verwendet. In ihnen muß der Anwender des USR-Befehls die Zieladresse in Low-/High-Byte-Darstellung angeben, ab der das Maschinenprogramm im Speicher steht. Dieser Vorgang ist bereits behandelt worden bei den Speicherzellen 0 bis 2 des VC 20, die ja genau den Speicherzellen 784 bis 786 des C 64 entsprechen. Speziell für den C 64 ist der USR-Befehl noch einmal behandelt, und zwar im Texteinschub Nr. 34 »Das Mauerblümchen USR«. (Diese drei Speicherzellen 784 bis 786 sind beim VC 20 nicht belegt. Beim C 64 entsprechen sie den Adressen 0 bis 2 des VC 20.) |
JMP ABS machine instruction, jump to USR() function. | user function dispatch | USR function jump ($B248) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0310 | 784 |
Jump Instruction for User Function ($4C)The value here (67, $4C) is first part of the 6510 machine language JuMP instruction for the USR command. |
USR Function Jump Instr (4C) | USR Function JMP Instruction ($4C). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0311-$0312 | USRADD | 785-786 |
Address of USR Routine (Low Byte First)These locations contain the target address of the USR command. They are initialized by the Operating System to point to the BASIC error message handler routine, so that if you try to execute a USR call without changing these values, you wil receive an ILLEGAL QUANTITY error message. In order to successfully execute a USR call, you must first POKE in the target address in low-byte, high-byte order. You can calculate these two values for any address with the formula:
For example, if the USR routine started at 49152 ($C000), you would POKE 786, INT(49152/256):POKE 785,49152-(PEEK(786)*256 before executing the USR command. What makes the USR command different from SYS is that you can pass a parameter into the machine language routine by placing it in parenthesis after the USR keyword, and you can pass a parameter back to a variable by assigning its value to the USR function. In other words, the statement X=USR(50) will first put the number 50 in floating point format into the Floating Point Accumulator (FAC1) at 97-102 ($61-$66). Then, the machine language program designated by the address at this vector will be executed. Finally, the variable X will be assigned the floating point value which ends up in FAC1 after the user-written routine is finished. Since floating point representation is difficult to work with, it is handy to change these floating point parameters into integers before working with them. Fortunately, there are vectored routines which will do the conversions for you. The routine vectored at locations 3-4 converts the number in FAC1 to a two-byte signed integer, with the low byte in the .Y register (and location 101 ($65)) and the high byte in the Accumulator (.A). Remember, that number is converted to a signed integer in the range between 32767 and -32768, with Bit 7 of the high byte used to indicate the sign. To pass a value back through the USR function, you need to place the number into FAC1. To conert a signed integer to floating point format, place the high byte into the Accumulator (.A), the low byte into the .Y register, and jump through the vector at locations 5-6 with a JMP ($05) instruction. The floating point result will be left in FAC1. |
$B248 USR-Vektor | Execution address of USR() function. | USR Address Low Byte / High Byte | USR Address ($LB,$MB). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0313 | 787 | Unused |
beim C 64 und VC 20 nicht belegtWährend dieses freie Byte des C 64 nicht viel nutzt, haben VC 20-Besitzer immerhin vier aufeinanderfolgende freie Byte für eigene Vektoren und andere zwischenzuspeichernde Werte zur Verfügung, die nie in Gefahr geraten, von einem Basic-Programm überschrieben zu werden. |
Unused. | Unused | Unused. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0314-$0315 | CINV | 788-789 |
Vector to IRQ Interrupt RoutineThis vector points to the address of the routine that is executed when an IRQ interrupt occurs (normally 59953 ($EA31)). At power on, the CIA #1 Timer B is set to cause an IRQ interrupt to occur every 1/60 second. This vector is set to point to the routine which updates the software clock and STOP key check, blinks the cursor, maintains the tape interlock, and reads the keyboard. By changing this vector, the user can add or substitute a machine language routine that will likewise execute every 1/60 second. The user who is writing IRQ interrupt routines should consider the following:
In the same vein, if you replace the normal IRQ routine with your own, you should be aware that the keyboard's scanning and clock update will not occur unless you call the old interrupt routine once every 1/60 second. It is suggested that if you plan to use that routine, you save the old vector address in some other location. In that way, you can JuMP to the keyboard interrupt routine through this alternate vector, rather than assuming that the ROM address will never change and that it is safe to jump into the ROM directly. |
Vektor auf die IRQ-Interrupt-Routine des BetriebssystemsDieser Vektor zeigt auf die Adresse 59953 ($EA31) - beim VC 20 auf 60095 ($EABF). Ab hier beginnt die Routine des Betriebssystems, die den IRQ-Interrupt ausführt. Die Bedeutung der verschiedenen Interrupts (Unterbrechungen), ihre Auslöser und Abläufe sind als Übersicht im Texteinschub Nr. 35 »Dem Computer ins Wort fallen« dargestellt. Die IRQ-Routine wird vom Timer A des Ein-/Ausgabe-Bausteins CIA #1 - beim VC 20 vom Timer 1 des Ein-/Ausgabe-Bausteins VIA #2 - ausgelöst, und zwar periodisch 60mal in jeder Sekunde. In der Programmpause werden die im Texteinschub beschriebenen »Haushaltsarbeiten« durchgeführt. Dieser Vektor eignet sich hervorragend für eigene Programmierzwecke, da er durch das Verbiegen auf eine andere Adresse seine gleichmäßige und hochfrequente Wiederkehr nicht verliert. Mit seiner Hilfe können also eigene Maschinenprogramme 60mal in der Sekunde in ein Programm eingeschoben werden - eine Methode, die deswegen den englischen Namen »Wedge« = Keil, erhalten hat. Zwei Vorbedingungen sind allerdings dabei zu erfüllen.
Ich habe lange nach einem Beispiel gesucht. Ich kenne viele: Abfrage der Joysticks, Lautstärke von Tönen mit Funktionstasten steuern, von Basic unabhängige Laufschrift, um ein paar zu nennen. Aber alle haben einen ziemlich langen Maschinensprache-Teil. Ich bringe daher hier das kürzeste Beispiel, das ich kenne. Es stammt von Rügheimer und Spanik. Das Programm verändert dauernd die Farbe des Bildschirmrahmens:
Dieses Programm gilt nur für den C 64; für den VC 20 müßte es entsprechend umgeschrieben werden. Die Zeilen 10 bis 30 lesen das Maschinenprogramm, das in den DATA-Zeilen 40 bis 60 steht, in die Speicherzellen 679 bis 699. Diese stehen, wie wir das letzte Mal gesehen haben, zur freien Verfügung - und sind daher ideal geeignet, ein kleines Maschinenprogramm ungestört aufzunehmen. In Zeile 70 wird der IRQ-Interrupt unterbrochen. Jetzt kommt der wichtige Teil: Zeile 80 verbiegt den IRQ-Vektor zur Speicherzelle 176 + 256 * 2 = 679. Zeile 90 schaltet schließlich den IRQ-Interrupt wieder ein. Jetzt passiert also folgendes: Jedesmal, wenn der Timer A den Haushalt-IRQ auslöst, springt der Computer zuerst einmal auf das Maschinenprogramm ab Speicherzelle 679 und schaltet die Rahmenfarbe um. Dann erst springt der letzte Befehl des Maschinenprogramms auf die ursprüngliche IRQ-Adresse 59953 ($EA31), von der aus das Betriebssystem weitermacht, als sei nichts geschehen. Für Kenner gebe ich noch das Assembler-Listing des Maschinenprogramms an:
Es gibt noch eine kleine, erwähnenswerte Anwendung. Wenn der Vektor nicht auf den Anfang der IRQ-Routine bei 59953, sondern auf 59956 - also drei Stellen weiter - zeigt, übergeht die IRQ-Routine den Teil, welcher die STOP-Taste abfragt und die TI/TI$-Uhr weiterschaltet, wodurch effektiv die STOP-Taste ausgeschaltet wird. Das geht ganz schnell mit POKE 788,52. Mit POKE 788,49 wird das wieder rückgängig gemacht. Beim VC 20 sind es die Werte POKE 788,194 oder POKE 788,191. |
$EA31 IRQ-Vektor |
Execution address of interrupt service routine.Default: $EA31. |
IRQ RAM vector | Vector: Hardware Interrupt | Vector: Hardware IRQ Interrupt Address ($EA31). | Hardware interrupt vector ($EA31) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0316-$0317 | CBINV | 790-791 |
Vector: BRK Instruction InterruptThis vector points to the address of the routine which will be executed anytime that a 6510 BRK instruction (00) is encountered. The default value points to a routine that calls several of the Kernal initialization routines such as RESTOR, IOINIT and part of CINT, and then jumps through the BASIC warm start vector at 40962. This is the same routine that is used when the STOP and RESTORE keys are pressed simultaneously, and is currently located at 65126 ($FE66). A machine language monitor program will usually change this vector to point to the monitor warm start address, so that break points may be set that will return control to the monitor for debugging purposes. |
Vektor auf die BREAK-Interrupt-Routine des BetriebssystemsDiese Routine ist im Texteinschub Nr. 35 nicht erwähnt, weil sie ein Teil der NMI-Routine ist. Dieser Vektor zeigt auf die Adresse 65126 ($FE66) - beim VC 20 auf 65234 ($FED2). Die da beginnende Routine des Betriebssystems wird aufgerufen, wenn der Maschinenbefehl BRK ausgeführt wird. Er führt letztlich zu einem Warmstart, das heißt der Bildschirm wird gelöscht und der Cursor meldet sich mit READY. Diese Routine wird auch durch das gleichzeitige Drücken der STOP- und der RESTORE-Taste angestoßen. |
$FE66 BRK-Vektor |
Execution address of BRK service routine.Default: $FE66. |
BRK instr RAM vector | Vector: BRK Instr. Interrupt | Vector: BRK Instruction Interrupt Address ($FE66). | Break interrupt vector ($FE66) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0318-$0319 | NMINV | 792-793 |
Vector: Non-Maskable InterruptThis vector points to the address of the routine that will be executed when a Non-Maskable Interrupt (NMI) occurs (currently at 65095 ($FE47)). There are two possible sources for an NMI interrupt. The first is the RESTORE key, which is connected directly to the 6510 NMI line. The second is CIA #2, the interrupt line of which is connected to the 6510 NMI line. When an NMI interrupt occurs, a ROM routine sets the Interrupt disable flag, and then jumps through this RAM vector. The default vector points to an interrupt routine which checks to see what the cause of the NMI was. If the cause was CIA #2, the routine checks to see if one of the RS-232 routines should be called. If the source was the RESTORE key, it checks for a cartridge, and if present, the cartridge is entered at the warm start entry point. If there is no cartridge, the STOP key is tested. If the STOP key was pressed at the same time as the RESTORE key, several of the Kernal initialization routines such as RESTOR, IOINIT and part of CINT are executed, and BASIC is entered through its warm start vector at 40962. If the STOP key was not pressed simultaneously with the RESTORE, the interrupt will end without letting the user know that anything happened at all when the RESTORE key was pressed. Since this vector controls the outcome of pressing the RESTORE key, it can be used to disable the STOP/RESTORE sequence. A simple way to do this is to change this vector to point to the RTI instruction. A simple POKE 792,193 will accomplish this. To set the vector back, POKE 792,71. Note that this will cut out all NMIs, including those required for RS-232 I/O. |
Vektor auf die NMI-Routine des Betriebssystems.Der NMI-Interrupt ist im Texteinschub Nr. 35 »Dem Computer ins Wort fallen« näher beschrieben. Der Vektor zeigt auf den Beginn dieser Routine ab Speicherzelle 65095 ($FE47) - beim VC 20 ab 65197 ($FEAD). Sobald ein NMI-Interrupt auftritt, wird zuerst durch Setzen der Interrupt- Abschalt-Flagge (Interrupt Disable Flag) jede Unterbrechung durch den IRQ- Interrupt unterbunden. Dann wird geprüft, wer den NMI-Interrupt ausgelöst hat, und zwar in der Reihenfolge: RS232-Schnittstelle, RESTORE-Taste; eingestecktes Modul und schließlich die STOP-Taste. Die letztere dient zum Sichem der RESTORE-Taste. Nur wenn beide gemeinsam gedrückt werden, kommt die NMI- Unterbrechung durch die RESTORE-Taste zur Auswirkung. Da die RESTORE-Taste fast als erste abgefragt wird, kann sie und ihre Kombination mit der STOP-Taste durch Verbiegen des Vektors in Speicherzelle 792 bis 793 abgeschaltet werden. Beim C 64 geht das mit POKE 792,193 - Wieder eingeschaltet wird mit POKE 792,71. Beim VC 20 geht das mit POKE 792,91 beziehungsweise POKE 792,173 - Natürlich können Spezialisten durch Verbiegen des Vektors auf andere Adressen ihre eigenen NMI-Routinen bauen. |
$FE47 NMI-Vektor |
Execution address of non-maskable interrupt service routine.Default: $FE47. |
NMI RAM vector | Vector: Non-Maskable Interrupt | Vector: Hardware NMI Interrupt Address ($FE47). | NMI interrupt vector ($FE47) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$031A-$032D | 794-813 |
Kernal Indirect VectorsThere are 39 Kernal routines for which there are vectors in the jump table located at the top of the ROM (65409, $FF81). For ten of these routines, the jump table entry contains a machine language instruction to jump to the address pointed to by the RAM vector in this table. The addresses in this table are initialized to point to the corresponding routines in the Kernal ROM. Since these addresses are in RAM, however, any entry in this table may be changed. This enables the user to add to these routines, or to replace them completely. You will notice, for example, that many of these routines involve Input/ Output functions. By changing the vectors to these routines, it is possible to support new I/O devices, such as an IEEE disk drive used through an adapter. The user should be cautioned that since some of these routines are interrupt-driven, it is dangerous to change these vectors without first turning off all interrupts. For a safe method of changing all of these vectors at one time, along with the interrupt vectors above, see the entry for the Kernal VECTOR routine at 64794 ($FD1A). More specific information about the individual routines can be found in the descriptions given for their ROM locations. |
Indirects for codeConforms to KERNAL spec 8/19/80 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$031A-$031B | IOPEN | 794-795 | Vector to Kernal OPEN Routine (Currently at 62282 ($F34A)) |
Vektor auf die OPEN-Routine des BetriebssystemsDie Routine beginnt ab Adresse 62282 ($F34A) - beim VC 20 ab 62474 ($FEAD). Diese Routine prüft, ob eine Datei (File) eröffnet werden kann. Das geht immer dann, wenn die File-Nummer nicht 0 ist und wenn weniger als 10 andere Dateien bereits eröffnet sind. Für die serielle Schnittstelle (Geräte-Nummer 4, 5, 8 bis 11) wird an das angewählte Gerät zuerst der Befehl »Listen« gegeben und dann die Sekundär-Adresse des OPEN-Befehls. Beim Bandgerät (Geräte-Nummer 1) prüft die Routine den Tape Header einer sequentiellen Datei beziehungsweise schreibt einen Tape Header auf das Band. Bei Anwahl der RS232-Schnittstelle (Geräte-Nummer 2) aktiviert die Routine einige Leitungen und reserviert je einen Ein- und Ausgabe-Pufferspeicheram oberen Ende des Basic-Programmspeichers. |
$F34A OPEN-Vektor |
Execution address of OPEN, routine opening files.Default: $F34A. |
KERNAL OPEN Routine Vector | Vector: Indirect entry to Kernal OPEN Routine ($F34A). | OPEN vector ($F34A) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$031C-$031D | ICLOSE | 796-797 | Vector to Kernal CLOSE Routine (Currently at 62097 ($F291)) |
Vektor auf die CLOSE-Routine des BetriebssystemsDieser Vektor zeigt auf die Adresse 62097 ($F291) - beim VC 20 auf 62282 ($F34A). Ab hier beginnt eine Routine, die beim CLOSE-Befehl zuerst prüft, ob die Datei-Nummer in der Tabelle der eröffneten Datei enthalten ist. Dann holt sie die dazugehörige Geräte-Nummer und Sekundär-Adresse und schließt den Kanal und die Datei. |
$F291 CLOSE-Vektor |
Execution address of CLOSE, routine closing files.Default: $F291. |
KERNAL CLOSE Routine Vector | Vector: Indirect entry to Kernal CLOSE Routine ($F291). | CLOSE vector ($F291) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$031E-$031F | ICHKIN | 798-799 | Vector to Kernal CHKIN Routine (Currently at 61966 ($F20E)) | $F20E CHKIN-Vektor |
Execution address of CHKIN, routine defining file as default input.Default: $F20E. |
KERNAL CHKIN Routine | Vector: Indirect entry to Kernal CHKIN Routine ($F20E). | Set - input vector ($F20E) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0320-$0321 | ICKOUT | 800-801 | Vector to Kernal CKOUT Routine (Currently at 62032 ($F250)) | $F250 CKOUT-Vektor |
Execution address of CHKOUT, routine defining file as default output.Default: $F250. |
KERNAL CHKOUT Routine | Vector: Indirect entry to Kernal CHKOUT Routine ($F250). | Set - output vector ($F250) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0322-$0323 | ICLRCH | 802-803 | Vector to Kernal CLRCHN Routine (Currently at 62259 ($F333)) |
Vektor auf die CLRCHN-Routine des BetriebssystemsDer Name dieser Routine ist die Abkürzung für »clear channel«. Diese Routine, die ab Adresse 62259 ($F333) - beim VC 20 ab 62461 ($F3F3) - beginnt, setzt alle Kanäle in den Einschaltzustand zurück. Das heißt, das Eingabegerät ist die Tastatur, das Ausgabegerät ist der Bildschirm. |
$F333 CLRCH-Vektor |
Execution address of CLRCHN, routine initializating input/output.Default: $F333. |
KERNAL CLRCHN Routine Vector | Vector: Indirect entry to Kernal CLRCHN Routine ($F333). | Restore I/0 vector ($F333) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0324-$0325 | IBASIN | 804-805 | Vector to Kernal CHRIN Routine (Currently at 61783 ($F157)) |
Vektor auf die CHRIN-Routine des BetriebssystemsDieser Vektor zeigt auf die Adresse 61783 ($F157) - beim VC 20 auf 61966 ($F20E). Die hier beginnende Routine, deren Abkürzung »Character Input« bedeutet, holt das jeweils nächste Byte vom Eingabepuffer des angewählten Gerätes, sofern ein solcher eingerichtet ist (zum Beispiel Kassettenpuffer, RS232-Puffer). Bei Eingabe von der Tastatur holt diese Routine so lange Bytes aus dem Tastaturpuffer und zeigt sie auf dem Bildschirm an, bis das Zeichen für ein ungeSHIFTetes RETURN auftritt. Erst dann gibt die Routine das erste Zeichen der logischen Zeile auf dem Bildschirm an den Basic-Übersetzer weiter. |
$F157 INPUT-Vektor |
Execution address of CHRIN, data input routine, except for keyboard and RS232 input.Default: $F157. |
KERNAL CHRIN Routine | Vector: Indirect entry to Kernal CHRIN Routine ($F157). | INPUT vector ($F157) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0326-$0327 | IBSOUT | 806-807 | Vector to Kernal CHROUT Routine (Currently at 61898 ($F1CA)) |
Vektor auf die CHROUT-Routine des BetriebssystemsDie CHROUT-Routine entspricht der CHRIN-Routine in der anderen Richtung. Sie bedeutet »Character Output« und transferiert ein Byte, das im Akkumulator steht, in den Puffer des angewählten Ausgabegerätes. Sie beginnt ab Adresse 62898 ($F1CA), - beim VC 20 ab 62074 ($F27A). |
$F1CA OUTPUT-Vektor |
Execution address of CHROUT, general purpose data output routine.Default: $F1CA. |
KERNAL CHROUT Routine | Vector: Indirect entry to Kernal CHROUT Routine ($F1CA). | Output vector ($F1CA) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0328-$0329 | ISTOP | 808-809 |
Vector to Kernal STOP Routine (Currently at 63213 ($F6ED))This vector points to the address of the routine that tests the STOP key. The STOP key can be disabled by changing this with a POKE 808,239. This will not disable the STOP/RESTORE combination, however. To disable both STOP and STOP/ RESTORE, POKE 808,234 (POKEing 234 here will cause the LIST command not to function properly). To bring things back to normal in either case, POKE 808, 237. |
Vektor auf die STOP-Routine des BetriebssystemsDer Vektor zeigt auf die Adresse 63213 ($F6ED) - beim VC 20 auf 63344 ($F770). Die dort beginnende Routine prüft, ob die STOP-Taste gedrückt ist. Durch Verbiegen dieses Vektors kann die STOP-Taste abgeschaltet werden. Beim C 64 geht dies mit POKE 808,239; wieder eingeschaltet wird die STOP-Taste mit POKE 808,237. Beim VC 20 sind die Werte POKE 808,100 beziehungsweise POKE 808,112. |
$F6ED STOP-Vektor | KERNAL STOP Routine Vector | Vector: Indirect entry to Kernal STOP Routine ($F6ED). | Test-STOP vector ($F6ED) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$032A-$032B | IGETIN | 810-811 | Vector to Kernal GETIN Routine (Currently at 61758 ($F13E)) |
Vektor auf die GETIN-Routine des BetriebssystemsDiese Routine ist fast identisch mit der CHRiN-Routine (siehe Speicherzellen 804 bis 805). Sie holt genauso Zeichen von angewählten Geräten in die Eingabepuffer. Der einzige und damit wichtigste Unterschied liegt in der Behandlung der Tastatur-Eingabe. Im Gegensatz zu CHRIN holt sie ein Byte aus dem Tastaturpuffer sofort in den Akkumulator. Der Vektor zeigt auf den Anfang der Routine ab Speicherzelle 61785 ($F13E) - beim VC 20 ab 61941 ($F1F5). |
$F13E GET-Vektor |
Execution address of GETIN, general purpose data input routine.Default: $F13E. |
KERNAL GETIN Routine | Vector: Indirect entry to Kernal GETIN Routine ($F13E). | GET vector ($F13E) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$032C-$032D | ICLALL | 812-813 | Vector to Kernal CLALL Routine (Currently at 62255 ($F32F)) | $F32F CLALL-Vektor |
Execution address of CLALL, routine initializing input/output and clearing all file assignment tables.Default: $F32F. |
KERNAL CLALL Routine Vector | Vector: Indirect entry to Kernal CLALL Routine ($F32F). | Abort I/o vector ($F32F) | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$032E-$032F | USRCMD | 814-815 |
Vector to User-Defined Command (Currently Points to BRK at 65126 ($FE66))This appears to be a holdover from PET days, when the built-in machine language monitor would JuMP through the USRCMD vector when it encountered a command that it did not understand, allowing the user to add new commands to the monitor. Although this vector is initialized to point to the routine called by STOP/ RESTORE and the BRK interrupt, and is updated by the Kernal VECTOR routine (64794, $FD1A), it does not seem to have the function of aiding in the addition of new commands. |
Freier VektorNach dem Einschalten zeigt dieser Vektor auf die BREAK-Routine, genauso wie der Vektor in Speicherzelle 790 und 791. Er ist ein Überbleibsel aus dem PET- Betriebssystem, das aber beim VC 20 und C 64 keine Rolle spielt. Hier können also eigene Vektoren definiert und eingesetzt werden. |
$FE66 Warmstart-Vektor |
Unused.Default: $FE66. |
User-Defined Vector | User Defined Vector ($FE66). | Warm start vector ($FE66) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0330-$0331 | ILOAD | 816-817 | Vector to Kernal LOAD Routine (Currently at 62622 ($F49E)) |
Vektor auf die LOAD-Routine des BetriebssystemsDieser Vektor zeigt auf die Adresse 62622 ($F49E) - beim VC 20 auf 62793 ($F549). Die dort beginnende Routine transferiert Daten von einem Eingabegerät direkt in den RAM-Speicher. Sie kann auch zum VERIFYen durch Vergleich der geladen mit den gespeicherten Daten verwendet werden. |
$F4A5 LOAD-Vektor |
Execution address of LOAD, routine loading files.Default: $F4A5. |
KERNAL LOAD Routine | Vector: Indirect entry to Kernal LOAD Routine ($F4A5). | LOAD link ($F4A5) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0332-$0333 | ISAVE | 818-819 | Vector: Kernal SAVE Routine (Currently at 62941 ($F5DD)) | $F5ED SAVE-Vektor |
Execution address of SAVE, routine saving files.Default: $F5ED. |
savesp | KERNAL SAVE Routine Vector | Vector: Indirect entry to Kernal SAVE Routine ($F5ED). | SAVE link ($F5ED) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$0334-$033B | 820-827 |
UnusedEight free bytes for user vectors or other data. |
Freier SpeicherbereichDiese 8 Byte stehen zur freien Verfügung. |
Unused (8 bytes). | Unused | Unused. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$033C-$03FB | TBUFFR | 828-1019 |
Cassette I/O BufferThis 192-byte buffer area is used to temporarily hold data that is read from or written to the tape device (device number 1). When not being used for tape I/O, the cassette buffer has long been a favorite place for Commodore programmers to place short machine language routines (although the 64 has 4K of unused RAM above the BASIC ROM at 49152 ($C000) that would probably better serve the purpose). Of more practical interest to the 64 programmer is the possible use of this area for VIC-II chip graphics memory (for example, sprite shape data or text character dot data). If the VIC-II chip is banked to the lowest 16K of memory (as is the default selection), there is very little memory space which can be used for such things as sprite shape data without conflict. If the tape is not in use, locations 832-895 ($0340-$037F) can be used as sprite data block number 13, and locations 896-959 ($0380-$03BF) can be used as sprite data block number 14. The types of tape blocks that can be stored here are program header blocks, data header blocks, and data storage blocks. The first byte of any kind of block (which is stored at location 828 ($033C)) identifies the block type. Header blocks follow this identifier byte with the two-byte starting RAM address of the tape data, the two-byte ending RAM address, and the filename, padded with blanks so that the total length of the name portion equals 187 bytes. Data storage blocks have 191 bytes of data following the identifier byte. The meanings of the various identifier blocks are as follows: A value of 1 signifies that the block is the header for a relocatable program file, while a value of 3 indicates that the block is the header for a nonrelocatable program file. A relocatable file is created when a program is SAVEd with a secondary address of 0 (or any even number), while a nonrelocatable program file is created if the secondary SAVE address is 1 (or any odd number). The difference between the two types of files is that a nonrelocatable program will always load at the address specified in the header. A relocatable program will load at the current start of BASIC address unless the LOAD statement uses a secondary address of 1, in which case it will also be loaded at the addrss specified in the header. You should note that a program file uses the cassette buffer only to store the header block. Actual program data is transferred directly to or from RAM, without first being buffered. An identifier value of 4 means that the block is a data file header. Such a header block is stored in the cassette buffer whenever a BASIC program OPENs a tape data file for reading or writing. Subsequent data blocks start with an identifier byte of 2. These blocks contain the actual data byte written by the PRINT #1 command, and read by the GET #1 and INPUT #1 commands. Unlike the body of a program file, these blocks are temporarily stored in the cassette byffer when being written or read. An identifier byte of 5 indicates that this block is the logical end of the tape. This signals the Kernal not to search past this point, even if there are additional tape blocks physically present on the tape. |
KassettenpufferDiese 192 Byte beherbergen den Kassettenpuffer. Der Name kennzeichnet diesen Speicherbereich als Zwischenspeicher für Ein- und Ausgabe-Operationen von und auf Band. Dabei unterscheiden sich die normalen LOAD-, SAVE- und VERIFY-Befehle von den Datei-Befehlen INPUT#, GET# und PRINT#. Bei LOAD, SAVE und VERIFY steht im Kassettenpuffer lediglich der Vorspann, der auf englisch »Tape Header« heißt. Die Funktion und Zusammensetzung des Tape Headers habe ich schon bei den Speicherzellen 183 bis 187 und im Texteinschub Nr. 20 »Tape Header« detailliert beschrieben. Die eigentlichen Daten berühren den Kassettenpuffer nicht, sondern werden direkt von und in den RAM-Speicher transferiert. Bei GET#, INPUT# und PRINT# werden nicht nur der Tape Header, sondern auch alle Daten im Kassettenpuffer zwischengespeichert. Dieser blockweise Transport ist an den charakteristischen Unterbrechungen des Datasettenmotors leicht zu erkennen. Der Kassettenpuffer kann durch Verbiegen der Zeiger in Speicherzelle 178 und 179 auf beliebige Plätze des Speichers, aber nicht unterhalb 512, geschoben werden. Normalerweise gibt das keinen Sinn, es sei denn, der Speicherbereich 828 bis 1019 wurde mit einem eigenen Maschinenprogramm belegt, und durch das Verschieben des Kassettenpuffers in höhere Regionen möchte man das Maschinenprogramm vor der Zerstörung durch ungeplante Datasetten-Operationen schützen. Die Kenntnis der Inhalte der Speicherzellen des Kassettenpuffers kann man ausnutzen, um die ärgerlichen LOAD ERROR-Probleme zu lösen. Die Methode dazu ist im Texteinschub Nr. 36 »Reparatur von LOAD ERROR« beschrieben. Ist die Datasette nicht angeschlossen, oder wird sie nicht eingesetzt, kann der Speicherbereich des Kassettenpuffers als freier Speicher benutzt werden. |
Bandpuffer | Datasette buffer (192 bytes). | cassette data b | Tape I/O Buffer | Tape I/O Buffer. | Cassette buffer | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
$03FC-$03FF | 1020-1023 |
UnusedFour more free bytes. |
Freie SpeicherplätzeAuch diese 4 Byte stehen zur freien Verfügung. |
Unused (4 bytes). | Unused | Unused. |