1、Moving Forth Part 3MOVING FORTHPart 3: Demystifying DOESby Brad RodriguezThis article first appeared in The Computer Journal #62 (July/August 1993).OOPS! Theres a colossal mistake in one of my 6809 design decisions in the previous installment. It became evident when I started to code the Forth word
2、EXECUTE. EXECUTE causes the execution of a single Forth word, whose address is given on the Parameter Stack. (To be precise: the compilation address, a.k.a. Code Field Address, is given on the stack.) This can be any kind of Forth word: CODE definition, colon definition, CONSTANT, VARIABLE, or defin
3、ed word. This differs from the usual Forth interpretation process in that the address of the word-to-execute is given on the stack, and not taken from the thread (as pointed to by IP). In our direct-threaded 6809 code this can be easily coded: EXECUTE: TFR TOS,W put address of word in W PULU TOS pop
4、 new TOS JMP ,W jump to address given in WNote: this is JMP ,W and not JMP ,W, since we already have the code address of the word. Were not fetching from the high-level thread. (If TOS wasnt in register, EXECUTE could be done with simply JMP ,PSP+.) Now suppose that this EXECUTEd word is a colon def
5、inition. W will be pointing to its Code Field, which contains JMP ENTER. This does the following (described in the previous article): JMP ENTER .ENTER: PSHS IP LDX -2,IP re-fetch the Code Field address LEAY 3,X NEXTThis is the mistake! We are not executing this word from within a thread, so IP was n
6、ot pointing to a copy of its Code Field address! (Remember, the address of the word-to-EXECUTE came from the stack.) This form of ENTER will not work with EXECUTE, because there is no way to find the address of the word being executed! This suggests a new general rule for DTC Forths: if NEXT does NO
7、T leave the address of the word-being-executed in a register, you MUST use a Call in the code field. So, the 6809 Forth is back to using a JSR in the Code Field. But to avoid the speed penalty for ENTER - one of the most-used code fragments in Forth - Ill complete the exercise for the student from t
8、he last article. Note what happens if you swap the registers assigned to RSP and PSP: with RSP=S, with RSP=U, and PSP=U and PSP=S (previous) (new) JSR ENTER JSR ENTER . .ENTER: PULS W PSHU IP push old IP onto R stack PSHS IP PULS IP pop new IP from JSR stack TFR W,IP NEXT NEXTThe new version execute
9、s in 31 cycles, the same as the JMP version I had wanted to use. The improvement is because the JSR version of ENTER must use both Forths Return Stack, and the 6809 subroutine-return stack (JSR stack). Using two different stack pointers means we dont have to swap the top-of-stack with IP, eliminatin
10、g the need for a temporary register. This illustrates the usual development process for a new Forth kernel: make some design decisions, write some sample code, discover a bug or a better way to do things, throw out some code, change some design decisions, rewrite some sample code, loop until satisfi
11、ed. (This is the programming equivalent of a rip up PC board autorouter.) This teaches an important lesson: make EXECUTE one of your benchmark words! OOPS, AGAIN Carey Bloodworth of Van Buren, AR has pointed out a minor but embarassing mistake in my 6809 code in the previous installment. For the TOS
12、-in-memory version of 0=, I showed the code fragment LDD ,PSP CMPD #0to test for top-of-stack equalling zero. In this case, the CMPD instruction is completly superfluous, since the LDD instruction will set the Zero flag if D is zero! (The TOS-in-D version still requires the CMPD instruction, but rem
13、ains faster than TOS-in- memory.) Now, on to our main topic: WHATS A CODE FIELD? The DOES concept seems to be one of the most misunderstood and mystifying aspects of Forth. Yet DOES is also one of Forths most powerful features - in many ways, it anticipated object- oriented programming. The action a
14、nd power of DOES hinges upon a brilliant innovation of Forth: the Code Field. Recall from Part 1 that the body of a Forth definition consists of two parts: the Code Field, and the Parameter Field. You can think of these two fields in several ways: * The Code Field is the action taken by this Forth w
15、ord, and the Parameter Field is the data on which it acts. * The Code Field is a subroutine call, and the Parameter Field is parameters that are included in-line after the call. (The assembly language programmers view.) * The Code Field is the single method for this class of words, and the Parameter
16、 Field contains the instance variables for this particular word. (The object-oriented programmers view.) Common features appear in all these views: * The Code Field routine is always called with at least one argument, namely, the address of the Parameter Field for the Forth word being executed. The
17、Parameter Field may contain any number of parameters. * There are relatively few distinct actions, i.e., relatively few distinct routines referenced by the Code Field. Each of these routines is widely shared (except for CODE words, as we will see later). Recall, for example, the ENTER routine from P
18、art 2: this common routine is used by all Forth colon definitions. * The interpretation of the Parameter Field is implicitly determined by the contents of the Code Field. I.e., each Code Field routine expects the Parameter Field to contain a certain kind of data. A typical Forth kernel will have sev
19、eral Code Field routines predefined. Code Field Parameter Field routine contents ENTER a high-level thread (series of addresses) DOCON a constant value DOVAR a storage location for data DOVOC vocabulary info (varies by implementation)What makes this feature powerful is that a Forth program is not li
20、mited to this set of Code Field routines (or whatever set is provided in your kernel). The programmer can define new Code Field routines, and new Parameter Fields to match. In object- oriented lingo, new classes and methods can be created (although each class has only one method). And - like Forth w
21、ords themselves - the Code Field actions can be defined in either assembly language or high-level Forth! To understand the mechanism of the Code Field, and how parameters are passed, we will first look at the case of assembly-language (machine code) actions. Well start with Indirect Threading (ITC),
22、 since it is the easiest to understand, and then see how the logic is modified in Direct-Threaded (DTC) and Subroutine- Threaded (STC) Forths. Then, well look at how the Code Field action can be written in high-level Forth. Forthwrights are somewhat inconsistent in their terminology, so Ill define m
23、y terms, using the ITC Forth word illustrated in Figure 1. The Header contains the dictionary information, and isnt involved in the execution of the Forth word. The Body is the working part of the word, and consists of the fixed-length Code Field, and the variable-length Parameter Field. For any giv
24、en word, the locations of these two fields in memory are the Code Field Address (CFA) and the Parameter Field Address (PFA), respectively. The Code Field Address of a word is the address in memory where its Code Field is located. This is not to be confused with the contents of the Code Field, which,
25、 in ITC Forths, is another different address. To be specific, the contents of the Code Field is the address of a fragment of machine code somewhere else in memory. I will refer to this as the Code Address. Later, when in discussing DTC and STC Forths, I will also refer to the Code Field contents, wh
26、ich will include more than just the Code Address. MACHINE-CODE ACTIONS Forth CONSTANTs are probably the simplest example of a machine- code action. Lets consider some good Francophone constants 1 CONSTANT UN2 CONSTANT DEUX3 CONSTANT TROISExecuting the word UN will push the value 1 onto the Forth Par
27、ameter Stack. Executing DEUX will push a 2 onto the stack, and so on. (Dont confuse Parameter Stack with Parameter Field; they are entirely separate.) In the Forth kernel there is a single word called CONSTANT. This is not a constant-type word itself; it is a high-level Forth definition. CONSTANT is
28、 a defining word: it creates new words in the Forth dictionary. Here we create the new constant-type words UN, DEUX, and TROIS. (You may think of these as instances of the class CONSTANT.) These three words will have their Code Fields pointing to a machine code fragment that does the action of CONST
29、ANT. What must this code fragment do? Figure 2 shows the memory representation of the three constants. All three words point to a common action routine. The difference in the words is entirely contained in their Parameter Fields, which, in this case, simply hold the constant values (instance variabl
30、es in object lingo). So, the action of these three words should be fetch the contents of the Parameter Field, and push this onto the stack. The code understands implicitly that the parameter field contains a single-cell value. To write a machine-code fragment to do this, we need to know how to find
31、the Parameter Field Address, after the Forth interepreter jumps to the machine code. That is, how is the PFA passed to the machine-code routine? This, in turn, depends on how the Forth interpreter NEXT has been coded, which varies from implementation to implementation. To write machine-code actions,
32、 we must understand NEXT. The ITC NEXT was described in pseudo-code in Part 1. Heres one implementation for the 6809, using Y=IP and X=W: NEXT: LDX ,Y+ ; (IP) - W, and IP+2 - IP JMP ,X ; (W) - temp, JMP (temp)Suppose that were in a high-level thread . SWAP DEUX + . with the Interpreter Pointer (IP) pointing to the DEUX instruction, when NEXT is executed. (This would be at the very end of SWAP.) Figure 3 illustrates what happens. IP (register Y)
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1