MISCELLANEOUS MVP-FORTH UTILITIES
There are a number of utilities available in MVP-FORTH. MVP-FORTH is in fact an application program. The nucleus or kernel of MVP-FORTH could be made much smaller but it would no longer serve the purpose of providing the user with a fully functional learning tool.
Some of the special features of MVP- FORTH are addressed in this section. They are arranged in no particular order.
Although commenting source code is often over done, it is good to include a sufficient number of comments while writing your programs. Comments are excluded from the compiler and are indicated by enclosing them within parentheses or preceding a line with a back slash. Either method works.
As already illustrated, the 0 line of each screen is by custom a comment line and is enclosed within parentheses. Often programmers include their initials and date on that line. If your system has a built in clock you might want to include the time on that line as well.
Older implementations also enclosed some primitive names within parentheses. When the names of these words were included within the parentheses of a comment, the comment was terminated. It is often terminated before the end of the intended comment. After considerable frustration trying to use good documentation and having the comment line terminated unexpectly, an alternate notation was adopted for indicating a primitive. The word is placed within angle brackets instead of parentheses. The angle brackets are the "less than" and "greater than" symbols. The technique provided a simple solution to the problem. The connotation of the word being a primitive is very obvious.
Examples of such run time primitive functions are the vectored routines of MVP- FORTH. They are placed within angle brackets.
Earlier you were told that you would be able to save the current operating object code. That can be done with the function SAVE-FORTH. Refer to the implementations in ALL ABOUT FORTH. The function is relatively long but provides an example of access to a number of system functions from MVP-FORTH.
The system calls access the underlying system disk drivers. These functions are essentially the same in CP/M-80, CP/M-86, and MS-DOS. The implementation of SAVE-FORTH can be used as a model for access to most of the system functions.
This implementation uses the older file control blocks of DOS rather than the more recent handles. The implementation is simpler but does have its limitations. A new version could be added if you desired. It would provide an application for learning how to manage handles.
As implemented, the object code will be saved on drive 0 through the parameter of 0 in the system function 14 call with SYSCALL. The value of 0 is defined as a constant in the FORTH dictionary rather than being left for conversion. It is thus compiled as two bytes in the definition of SAVE-FORTH. Inspect the data field of SAVE-FORTH with DUMP.
Especially with hard disks being more common, it has become desirable to be able to select the drive on which to write the object code file. A simple patch to SAVE-FORTH, will make this possible.0 CONSTANT DISK
DISK will be compiled as two bytes whose function is to return the current value of the constant. It has been initialized to 0. By finding the location of the code field address of the 0 following the value 0D hexadecimal ( for system function 14 ) in a DUMP, you can replace the code field address of 0 with the code field address of DISK.HEX ' 0 CFA . DECIMAL
This has been an aside. SAVE-FORTH runs the way it is. Study of the implementation will provide an example for a number of other programs to access disk operating system functions.
The name you select at the prompt can either be the same name as the file you are currently running or you can give it a new name. If you use the same name the previous directory entry will be deleted and then reused as the new name. At this point you could equally well give the name of the application as a name with the file type .COM, such as PROGRAM.COM.
Depending upon the size of the disk you are using, you will have more or less space to keep as many different applications as you wish. When doing development work it is often convenient to save successive object code images with different names. Then you have a series of backups for each level.
The use of the system to save object code images would be eliminated if we had systems fast enough to recompile an application to satisfy our impatience. Many common micro-processor systems will take several minutes to compile a moderate size program. In some systems it takes that long to compile the UTILITIES, SUPPLEMENTALS, EDITOR and ASSEMBLER, on top of the MVP-FORTH kernel. When the system can compile all of this in less than a second or two, there will be no need for saving the object code module.
FLUSH is an early word in the history of FORTH. Its function is to write back to disk all screen buffers which have been marked with UPDATE. Whenever the text on a screen is modified, that screen buffer is marked with UPDATE. It appears that the name was thought inelegant and was replaced with SAVE-BUFFERS in FORTH-79. Very quickly most programmers gave SAVE-BUFFERS the alias FLUSH.
Perhaps you should examine the screen buffers. Each buffer contains 1024 bytes of data with two trailing bytes containing the value of 0, two leading bytes which contain the current screen number, and a flag for the UPDATE function. The contents of the screen buffer need not contain only text data. It may contain any series of 1024 bytes. Only if text material is present within the screen buffer can it be listed in a reasonable form with LIST.
The two bytes containing 0 in the trailer cause the screen to terminate the loading function. This prevents a run away system should you forget to terminate a colon definition with a semicolon. It prevents you from concatinating screens. As a basic rule, if you need more than one screen for a colon definition, you probably should rethink your implementation. In ALL ABOUT FORTH is a definition for --> which will allow you to develop bad habits.
The leading two bytes contain the absolute screen number. As long as you are on drive 0, it will be the same as the actual screen number. But if you should be using screens on a second disk drive, an offset is added to the screen number in labeling the buffer. The current offset is stored in a variable OFFSET. What could be simpler?
The highest order bit of the leading sixteen bits is set to mark the buffers for update. The function of UPDATE is to set that bit. When the buffer space is needed for another screen, it is first checked to see if it has been marked for update. If it has, it is written back to disk before it is used. If it is not, the buffer is simply written over.
You can inspect the header value easily.75 BLOCK 2- @ .
This will show you the current block number in that buffer. Now try:UPDATE 75 BLOCK 2- @ .
The memory used by FORTH is initialized to the number of buffers in the constant #BUFF. By changing the number in this constant, a different number of new buffers will be initialized with CHANGE. These buffers are a form of disk caching.
Perhaps you have made a series of modifications and then thought better of them. Maybe there will be other occasions where you would like not to save the current changes to a screen back to disk. This can be avoided by the function of EMPTY-BUFFERS. All buffers are emptied. This command is also executed when the buffers are initialized. It is just as well that the word is a little difficult to type. It is destructive of information.
The use of the buffers in MVP-FORTH is cyclical in sequence. Both the run time functions of BLOCK and BUFFER will cycle through the available screen buffers. The variables USE and PREV are used in conjunction with these functions. USE is a variable providing the address to or from which data will be written from or to disk. The address currently in USE will be used by the disk access functions of the operating system. Should you change it from a pointer to a buffer, you will have to change it back when you again try to read screens to the buffers.
The beginning of the buffers is pointed to by a constant named FIRST. Below FIRST are several other areas. The return stack comes down from FIRST. It approaches the terminal input buffer which is pointed to by a user variable, TIB. The data stack, or parameter stack if you wish, starts from TIB and moves toward lower memory.
This area of memory can all be examined with the DUMP function. You will note however, that this is an active area of memory. The DUMP function uses the data stack and the return stack. Thus you cannot get a stable image of these areas.
The sixteen bit processor systems have a larger memory than the limited 64K available on most 8-bit processor systems. With the 80x86 family of processors, more than 16- bits of address are needed. With MVP-FORTH on these systems, you can read and write to any part of memory with long functions. These require that the address be given in 2 16-bit words with what is known as the segment address first. The common fetch and store functions are: !L , @L, C!L and C@L. You can also dump from any area with DUMPL. This function also requires 2 16-bit words for an address with the segment word first. You can use this function to examine the memory mapped display as well as the ROM memory in the system. MVP-FORTH program space is limited to a single segment but all memory segments are accessable. The DOS parameters in low memory can be examined and modified.
The dictionary search proceeds through the entries by a series of links. It is possible to restrict the search to specific segments of the vocabulary by placing entries in special areas known as vocabularies. The EDITOR and ASSEMBLER (hard copies of which are in the MVP-FORTH Documentation) are each in separate vocabularies. Unless one of these vocabularies is invoked by entering its name, no dictionary entries in the vocabularies will be found. This is one reason that you may not be able to use the line editor provided.
There are two flavors of vocabularies available in MVP-FORTH. In one all vocabularies chain directly to FORTH. That is, when a vocabulary is invoked, it will be searched first and then the FORTH vocabulary will be searched. If you were to define a second vocabulary within another vocabulary, the search would only search the current one and jump directly to the FORTH vocabulary. The other flavor allows the sequential searching of parent vocabularies all of the way back to FORTH. The latter is known as <VOCABULARYFIG>. The former is <VOCABULARY79>. The function of VOCABULARY is vectored through 'VOCABULARY.VOCABULARY NEW IMMEDIATE NEW DEFINITIONS : NEW-TEST ." THIS IS THE NEW VOCABULARY." ; FORTH DEFINITIONS
VOCABULARY is a defining word. It creates a dictionary entry for the new word following VOCABULARY as with any other defining word. All vocabularies are made IMMEDIATE. IMMEDIATE sets the second most significant bit in the word just defined. When this bit is set, the word will execute rather than compile when used within a colon definition. More on immediate words later.
Then to add definitions to the newly formed vocabulary, you must invoke the function of DEFINITIONS. With this function, all new definitions will be placed in the selected vocabulary until a new vocabulary is selected with DEFINITIONS. This is why you returned to FORTH DEFINITIONS.
The FORTH words CURRENT and CONTEXT are primitives used to select the proper vocabularies for searching and compiling.
You will now find that in the FORTH vocabulary, you will be unable to find NEW-TEST. However, by first invoking the vocabulary NEW, you can then execute NEW-TEST. The example provides a pattern for the use of vocabularies. It also gives you an idea of how EDITOR and ASSEMBLER work. You might examine the source screens for both of those vocabularies for further examples.
A name which has the flag set with IMMEDIATE will execute rather than compile during compilation. One can force the compilation of an immediate word with the function of [COMPILE].: L ( --- ) SCR @ LIST [COMPILE] EDITOR ;
This is a convenient utility. In the EDITOR is a word L which causes the current screen to be relisted. After loading a screen, you are left in the FORTH vocabulary. What you would like to do is list the same screen again and go back to the EDITOR. You could accomplish this with:EDITOR L
But perhaps you forgot to write EDITOR and just used the word L . This mistake will give you an error message because L is not defined in the FORTH vocabulary. The variable SCR stores the address of the most recently accessed screen. Thus you can reLIST the screen easily enough. But EDITOR is an immediate word. Therefore, to force its compilation with your new L in the FORTH vocabulary you have to use [COMPILE].
Whether you are compiling or executing is determined by a flag in the variable STATE. While you are in the compile state, you can temporarily leave and enter the execute state. In the execute state, the input stream is interpreted and executed. In this state, you can make calculations and return to the compile state. The flag in STATE is reset with the function [ , and set with ] .
This section has been rambling through a number of less commonly used MVP-FORTH functions. The discussion should spur you on to further experimentation.
Next Previous Contents