Benutzer-Werkzeuge

Webseiten-Werkzeuge


papierkorb:4th_lesson_7

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

papierkorb:4th_lesson_7 [2025-08-16 19:10] – ↷ Seite von projects:4th_lesson_7 nach papierkorb:4th_lesson_7 verschoben mkapapierkorb:4th_lesson_7 [Unbekanntes Datum] (aktuell) – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1
Zeile 1: Zeile 1:
-=== Lesson 7 === 
  
-<code> 
-\       Lesson 7 - Code Words and DOS I/O 
-\       The Forth Course 
-\       by Richard E. Haskell 
-\          Dept. of Computer Science and Engineering 
-\          Oakland University, Rochester, MI 48309 
-comment: 
- 
- 
-                                Lesson 7 
- 
-                        CODE WORDS AND DOS I/O 
- 
- 
-                7.1  CODE WORDS                         7-2 
- 
-                7.2  CODE CONDITIONALS                  7-5 
- 
-                7.3  LONG MEMORY WORDS                  7-6 
- 
-                7.4  DOS WORDS                          7-7 
- 
-                7.5  BASIC FILE I/O                     7-9 
- 
-                7.6  READING NUMBERS AND STRINGS       7-14 
- 
-                7.7  WRITING NUMBERS AND STRINGS       7-20 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-7.1  CODE WORDS 
- 
-        Assembly language instructions can be used to define Forth words 
-        when the maximum speed of execution is needed or when direct access 
-        to the computers hardware is required.  This is accomplished by 
-        using the CODE word to define a Forth word.  The general form of 
-        the CODE word is as follows: 
- 
-        CODE <name> 
-                <assembly commands> 
-                <return command> 
-                END-CODE 
- 
-        The word CODE takes the place of the colon in a colon definition 
-        and builds a header for the name of the Forth word <name> The 
-        word END-CODE takes the place of the semi-colon and ends the code 
-        word definition. 
- 
-        The <assembly commands> can be written in either POSTFIX or PREFIX 
-        notation.  We recommend PREFIX which makes the assembly language 
-        look very much like standard 8086/8088 assembly language.  The 
-        Forth word PREFIX needs to be executed before the CODE word is 
-        compiled. 
- 
-        The <return command> can be any of the following: 
- 
-        NEXT    JMP  >NEXT      ( jumps to the inner interpreter >NEXT ) 
- 
-        1PUSH   PUSH AX 
-                JMP  >NEXT      ( pushes ax on the stack and jumps to >NEXT ) 
- 
-        2PUSH   PUSH DX 
-                PUSH AX         ( pushes dx and ax on the stack 
-                JMP  >NEXT        and then jumps to >NEXT ) 
- 
-        Debugging CODE words is made easier using the 8088 Tutor monitor 
-        that is included with this Forth Course.  A complete description 
-        of how to use the Tutor monitor in the process of learning 8088/8086 
-        assembly language is given in the book 
- 
-        "IBM PC - 8088 Assembly Language Programming" by Richard E. Haskell. 
- 
-        Instructions for ordering the book are given when you run the 
-        program. 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-        As an example of using the Tutor monitor to disassemle and 
-        single step through a CODE word consider the following definition 
-        of the Forth word CMOVE that moves a string of <count> bytes from 
-        the address <source> to the address <dest>. 
- 
-        CODE CMOVE      ( source dest count -- ) 
-                CLD                     \ move up in memory 
-                MOV  BX, SI             \ save SI (IP) 
-                MOV  AX, DS             \ copy DS for setting ES 
-                POP  CX                 \ cx = count 
-                POP  DI                 \ di = destination address 
-                POP  SI                 \ si = source address 
-                PUSH ES                 \ save es 
-                MOV  ES, AX             \ point es to code segment 
-                REPNZ                   \ repeat until count is zero 
-                MOVSB                   \ copy DS:SI to ES:DI 
-                MOV  SI, BX             \ restore si 
-                POP  ES                 \ restore es 
-                NEST                    \ done, jmp to >NEXT 
-                END-CODE 
- 
-        When you FLOAD this lesson the following Forth code will store the 
-        hex values 11 22 33 44 55 at the offset address "source.addr" in 
-        the code segment.  The actual value of the code segment is given 
-        by the Forth word ?CS: and will be printed on the screen when you 
-        type the word "show.addrs". 
- 
-        A five byte space is reserved at the offset address "dest.addr". 
-        The offset addresses for "source.addr", "dest.addr", the top of 
-        the stack, and the CFA of CMOVE will also be printed on the screen 
-        when you type "show.addrs". 
-comment; 
- 
-        HEX 
-        CREATE source.addr 11 C, 22 C, 33 C, 44 C, 55 C, 
-        CREATE dest.addr   5 ALLOT 
-        5 CONSTANT #bytes 
-        : test          ( -- ) 
-                        source.addr dest.addr #bytes CMOVE ; 
- 
-        : show.addrs    ( -- ) 
-                HEX 
-                CR ." code segment = " ?cs: u. 
-                CR ." source addr = " source.addr u. 
-                CR ." dest addr = " dest.addr u. 
-                CR ." top of stack = " SP0 @ U. 
-                CR ." address of CMOVE = " [ ' CMOVE ] LITERAL U. 
-                CR DECIMAL ; 
- 
-comment: 
-        The words [, ] and LITERAL will be discussed in Lesson 9. 
- 
- 
- 
- 
- 
-       Assume the values printed when you type "show.addrs" are the following: 
- 
-        code segment = E74 
-        source addr = 6929 
-        dest addr = 6931 
-        top of stack = FFE2 
-        address of CMOVE = 41C 
- 
-        Your values may be different.  If they are, use your corresponding 
-        values in the following exercise. 
- 
-        Type debug test. 
-        Type test. 
-        Step through the first three word which will put the following 
-        values on the stack: 
-                        6929 6931 5 
-        Press F to go to Forth. 
-        Type SYS TUTOR - This will execute the TUTOR program 
-        From the TUTOR memory display 
-        Type >SE74  to display the code segment. 
-        Type /GSE74 to display the data segment = code segment. 
-        Type /GO6929 to display the "source addr" in the data segment. 
-                Note that 11 22 33 44 55 is displayed. 
-        Type /RSSE74 to make the stack segment the same as the code segment. 
-        Type /RPSFEDC to set the stack pointer equal to the 
-                top of stack (FFE2) minus 6. 
-        Type >O41C to go to the start of the CMOVE code. 
-        Single step through this program by pressing key F1. 
- 
-        Note that when you get to the REP instruction, pressing key F1 
-        five times will move the five bytes from "source.addr" to 
-        "dest.addr". 
- 
-        To exit TUTOR, type /QD.  This should take you to DOS. 
-        If you had not changed the stack (which you had to do to get 
-        to the values that the Forth program "test" had put on the stack) 
-        then typing /QD from TUTOR will take you back to Forth where you 
-        had typed "sys tutor". 
- 
- 
-        The Forth word CMOVE> ( source dest count -- ) is similar to 
-        CMOVE except that the bytes are moved in the opposite direction. 
-        That is, the highest address byte is moved first.  It is necessary 
-        to use this word if you are moving a string up in memory where the 
-        destination string may overlap the source string.  The use of CMOVE 
-        will cause the overlapped portion of the source string to be 
-        destroyed before it has a chance to be moved. 
- 
- 
- 
- 
- 
- 
- 
-7.2  CODE CONDITIONALS 
- 
-        When using the Forth assembler jump instructions are achieved 
-        by using the Forth words IF...ELSE...THEN, BEGIN...WHILE...REPEAT, 
-        and BEGIN...UNTIL together with the following code conditionals: 
- 
-                Forth           Assembled Code 
- 
-                0=              JNE/JNZ 
-                0<>             JE/JZ 
-                0<              JNS 
-                0>            JS 
-                <               JNL/JGE 
-                >=              JL/JNGE 
-                <=              JNLE/JG 
-                >               JLE/JNG 
-                U<              JNB/JAE/JNC 
-                U>            JB/JNAE/JC 
-                U<            JNBE/JA 
-                U>              JBE/JNA 
-                OV              JNO 
- 
-        As an example, consider the definition of the Forth word ?DUP 
-        which duplicates the value on top of the stack only if the value 
-        is non-zero. 
- 
-        CODE    ?DUP    ( n -- n n | 0 ) 
-                        POP     AX 
-                        CMP     AX, # 0 
-                        0<> 
-                        IF 
-                           PUSH AX 
-                        THEN 
-                        1PUSH 
-                        END-CODE 
- 
-        Note that when this definition gets assembled into machine code 
-        the statement 0<> is assembled as JE to the instruction following 
-        THEN. 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-7.3  LONG MEMORY WORDS 
- 
-        The following long memory words are useful for accessing data 
-        in segments other than the code segment. 
- 
-        CODE    @L      ( seg off -- n )  \ Fetch 16-bit value from seg:off 
-                        POP     BX              \ BX = offset address 
-                        POP     DS              \ DS = segment address 
-                        MOV     AX, 0[BX]       \ AX = data at DS:BX 
-                        MOV     BX, CS          \ Restore DS to CS value 
-                        MOV     DS, BX 
-                        1PUSH                   \ push value on stack 
-                        END-CODE 
- 
-        CODE    !L      ( n seg off -- )  \ Store 16-bit value at seg:off 
-                        POP     BX              \ BX = offset address 
-                        POP     DS              \ DS = segment address 
-                        POP     AX              \ AX = n 
-                        MOV     0[BX],AX        \ Store n at DS:BX 
-                        MOV     BX, CS          \ Restore DS to CS value 
-                        MOV     DS, BX 
-                        NEXT 
-                        END-CODE 
- 
-        The following are other useful long memory words: 
- 
-        C@L     ( seg off -- byte )  \ Fetch 8-bit byte from seg:off 
- 
-        C!L     ( byte seg off -- )  \ Store 8-bit byte at seg:off 
- 
-        CMOVEL  ( sseg soff dseg doff count ) 
-                \ move a block of count bytes from sseg:soff to dseg:doff 
- 
-        CMOVEL> ( sseg soff dseg doff count ) 
-                \ move a block of count bytes from sseg:soff to dseg:doff 
-                \ moves last byte first to avoid overwriting moved data 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-7.4  DOS WORDS 
- 
-        F-PC has a large number of Forth words for handling DOS file I/O. 
-        These words are defined in the source files HANDLES.SEQ and 
-        SEQREAD.SEQ.  In this and the next section we will develop a set 
-        of file I/O words that you can use and extend to handle a variety 
-        of file I/O and other DOS operations.  These words can be used 
-        in place of, or in conjunction with, the F-PC DOS and file I/O words. 
- 
-comment; 
- 
-VARIABLE ITEMS          \ used to record stack depth 
-VARIABLE handl          \ file handle 
-VARIABLE eof            \ TRUE if end-of-file was read 
-CREATE fname  80 ALLOT  \ 80 byte buffer containing ASCII filename 
- 
-: {     ( -- ) 
-                DEPTH ITEMS ! ; 
- 
-: }     ( -- c ) 
-                DEPTH ITEMS @ - ; 
- 
-comment: 
- 
-{ . . . }       Used to keep track of the number of elements 
-                put on the stack.  For example, 
- 
-                        { 5 2 8 } 
- 
-                will leave the following values 
-                on the top of the stack: 
- 
-                        5 2 8 3 
- 
-                The 3 on top of the stack is the number of 
-                items entered between { and }. 
-comment; 
- 
-: $>asciiz      ( addr1 -- addr2 ) \ change counted string to ASCIIZ string 
-                DUP C@ SWAP 1+ 
-                TUCK + 
-                0 SWAP C! ; 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-\ DOS 2.0+ disk I/O functions 
- 
-comment:  ---------------------------------------------------------- 
-2fdos   calls the DOS INT 21H function with ax=ah:al, 
-        bx, cx and dx on the stack.  It returns ax, dx 
-        and an error flag on the stack.  If the error flag 
-        is TRUE, the error code is in ax (3rd element on the 
-        stack).  If the error flag is FALSE, then ax and dx 
-        will have values that depend on the function call. 
- 
-fdos    is similar to 2fdos, but does not return an error 
-        flag.  It should be used for DOS INT 21H calls that 
-        do not use the carry flag to indicate an error. 
-******************************************************************* 
-comment; 
- 
-PREFIX 
-HEX 
- 
-CODE  2fdos     ( ax bx cx dx -- ax dx f ) 
-                POP     DX 
-                POP     CX 
-                POP     BX 
-                POP     AX 
-                INT     21              \ DOS function call 
-                U>= 
-                IF                      \ if carry = 0 
-                   MOV  BX, # FALSE        set error flag to false 
-                ELSE                    \ else 
-                   MOV  BX, # TRUE      \    set error flag to true 
-                THEN 
-                PUSH    AX 
-                PUSH    DX 
-                PUSH    BX 
-                NEXT 
-                END-CODE 
- 
-CODE  fdos      ( ax bx cx dx -- ax dx ) 
-                POP     DX 
-                POP     CX 
-                POP     BX 
-                POP     AX 
-                INT     21              \ DOS function call 
-                PUSH    AX 
-                PUSH    DX 
-                NEXT 
-                END-CODE 
- 
-DECIMAL 
- 
- 
- 
- 
- 
-comment: 
- 
-7.5  BASIC FILE I/O 
- 
-                The following words can be used for basic file I/O 
-                operations such as opening, creating, closing and 
-                deleting files, as well as reading and writing bytes 
-                from and to the disk file. 
- 
-                ----------------------------------------------------- 
-open.file       ( addr -- handle ff | error.code tf ) 
-                Opens a file. Returns handle under a false flag 
-                or returns error code under a true flag. 
-                addr points to an asciiz string. 
-                Access code is set to 2 to open for reading and writing. 
-comment; 
-HEX 
- 
-: open.file    ( addr -- handle ff | error.code tf ) 
-                3D02                    \ ah = 3D; al = access.code=2 
-                0 ROT 0 SWAP            \ 3D02 0 0 addr 
-                2fdos                   \ DOS function call 
-                NIP ;                   \ nip dx 
- 
-comment:        ----------------------------------------------------- 
-close.file      Closes file whose handle is on the stack. 
-                Prints error message if unable to close. 
-comment; 
- 
-: close.file    ( handle -- ) 
-                3E00                    \ ah = 3E 
-                SWAP 0 0                \ bx = handle 
-                2fdos 
-                NIP                     \ nip dx 
-                IF 
-                   ." Close error number " . ABORT 
-                THEN 
-                DROP ; 
- 
-comment:        ----------------------------------------------------- 
-create.file     Creates file -- returns values as in open.file 
-                addr points to an asciiz string 
-                attr is the file attribute: 0 - normal file 
-                 01H - read only        02H - hidden 
-                 04H - system           08H - volume label 
-                 10H - subdirectory     20H - archive 
-comment; 
- 
-: create.file   ( addr attr -- handle ff | error.code tf ) 
-                3C00                    \ ah = 3C 
-                0 2SWAP SWAP            \ 3C00 0 attr addr 
-                2fdos 
-                NIP ;                   \ nip dx 
- 
- 
-comment:        ------------------------------------------------------ 
-open/create     Opens a file if it exists, 
-                otherwise creates a new normal file. 
-                "addr" points to an asciiz string. 
-                Returns a handle for the opened file. 
-                Prints error messages if unable to open. 
-comment; 
- 
-: open/create   ( addr -- handle ) 
-                DUP open.file 
-                IF 
-                   DUP 2 = 
-                   IF 
-                      DROP 0 create.file 
-                      IF ." Create error no. " . ABORT 
-                      THEN 
-                   ELSE 
-                      ." Open error no. " . DROP ABORT 
-                   THEN 
-                ELSE 
-                   NIP 
-                THEN ; 
- 
-: delete.file   ( addr -- ax ff | error.code tf ) 
-                4100 
-                0 ROT 0 SWAP 
-                2fdos 
-                NIP ; 
- 
-: erase.file    ( $addr -- )    \ erase file with counted string at $addr 
-                $>asciiz 
-                delete.file 
-                IF 
-                   CR ." Delete file error no. " . 
-                ELSE 
-                   DROP 
-                THEN ; 
- 
-comment:        ----------------------------------------------------- 
-read.file       Reads '#bytes' bytes from file with 'handle' 
-                into buffer at 'buff.addr' Returns #bytes 
-                actually read.  If this value is 0 then the 
-                end of file was read.  Prints error message 
-                if unsuccessful. 
-comment; 
- 
-: read.file     ( handle #bytes buff.addr -- #bytes ) 
-                >R 3F00                 \ handle #bytes 3F00 
-                -ROT R>                 \ 3F00 handle #bytes addr 
-                2fdos 
-                NIP                     \ nip dx 
-                IF 
-                   ." Read error no. " . ABORT 
-                THEN ; 
- 
-comment:        ----------------------------------------------------- 
-write.file      Writes '#bytes' bytes from buffer at 'buff.addr' 
-                to file with 'handle' Prints error message 
-                if unsuccessful. 
-comment; 
- 
-: write.file    ( handle #bytes buff.addr -- ) 
-                >R 4000                 \ handle #bytes 4000 
-                -ROT R>                 \ 4000 handle #bytes addr 
-                2fdos 
-                NIP                     \ nip dx 
-                IF 
-                   ." Write error no. " . ABORT 
-                ELSE 
-                   DROP 
-                THEN ; 
- 
-comment:        ------------------------------------------------------- 
-mov.ptr         Moves the file pointer of the file with 'handle'. 
-                doffset is a double number (32-bit) offset 
-                code is the method code: 
-                0 - move pointer to start of file + offset 
-                1 - increase pointer by offset 
-                2 - move pointer to end of file + offset 
-comment; 
- 
-: mov.ptr       ( handle doffset code -- dptr ) 
-                42 FLIP +               \ hndl offL offH 42cd 
-                ROT >R                  \ hndl offH 42cd 
-                -ROT R>                 \ 42cd hndl offH offL 
-                2fdos 
-                IF 
-                   DROP ." Move pointer error no. " . ABORT 
-                THEN ; 
- 
-comment:        ------------------------------------------------------- 
-rewind.file     Moves the pointer of file with 'handle' 
-                to the start of file. 
-comment; 
- 
-: rewind.file   ( handle -- ) 
-                0 0 0 mov.ptr 2DROP ; 
- 
-comment:        ------------------------------------------------------- 
-get.length      Returns the 32-bit length of the file with 
-                'handle'. 
-comment; 
- 
-: get.length    ( handle -- dlength ) 
-                0 0 2 mov.ptr ; 
- 
- 
- 
- 
- 
-comment:        ------------------------------------------------------- 
-read.file.L     Reads the next "#bytes" bytes from the opened file 
-                with handle "handle" and stores these bytes in 
-                extended memory at seg:offset. 
-comment; 
- 
-CODE read.file.L        ( handle #bytes seg offset -- ax f ) 
-                POP     DX 
-                POP     DS 
-                POP     CX 
-                POP     BX 
-                MOV     AH, # 3F 
-                INT     21 
-                U>= 
-                IF 
-                   MOV  BX,  # FALSE 
-                ELSE 
-                   MOV  BX, # TRUE 
-                THEN 
-                MOV     CX, CS          \ restore DS 
-                MOV     DS, CX 
-                PUSH    AX 
-                PUSH    BX 
-                NEXT 
-                END-CODE 
- 
-comment:        ------------------------------------------------------- 
-write.file.L    Writes "#bytes" bytes from extended memory at 
-                seg:offset to the opened file with handle "handle". 
-comment; 
- 
-CODE write.file.L        ( handle #bytes seg offset -- ax f ) 
-                POP     DX 
-                POP     DS 
-                POP     CX 
-                POP     BX 
-                MOV     AH, # 40 
-                INT     21 
-                U>= 
-                IF 
-                   MOV  BX, # FALSE 
-                ELSE 
-                   MOV  BX, # TRUE 
-                THEN 
-                MOV     CX, CS          \ restore DS 
-                MOV     DS, CX 
-                PUSH    AX 
-                PUSH    BX 
-                NEXT 
-                END-CODE 
- 
- 
- 
- 
- 
-comment:        ------------------------------------------------------- 
-findfirst.dir   Search the directory for the first match of the 
-                file specified by the asciiz string at "addr". 
-comment; 
- 
-CODE    findfirst.dir ( addr --  f )    \ search directory for first match 
-                POP     DX              \ dx = addr of asciiz string 
-                PUSH    DS              \ save ds 
-                MOV     AX, CS 
-                MOV     DS, AX          \ ds = cs 
-                MOV     CX, # 10        \ attr includes subdirectories 
-                MOV     AX, # 4E00      \ ah = 4E 
-                INT     21              \ DOS function call 
-                JC      1 $             \ if no error 
-                MOV     AX, # FF        \   flag = TRUE 
-                JMP     2 $             \ else 
-        1 $:    MOV     AX, # 0           flag = FALSE 
-        2 $:    POP     DS              \ restore ds 
-                PUSH    AX              \ push flag on stack 
-                NEXT 
-                END-CODE 
- 
-comment:        ------------------------------------------------------- 
-findnext.dir    Search the directory for the next match of the 
-                file specified by the asciiz string at "addr". 
-comment; 
- 
-CODE    findnext.dir ( --  f )          \ search directory for next match 
-                PUSH    DS              \ save ds 
-                MOV     AX, CS 
-                MOV     DS, AX          \ ds = cs 
-                MOV     AX, # 4F00      \ ah = 4F 
-                INT     21              \ DOS function call 
-                JC      1 $             \ if no error 
-                MOV     AX, # FF        \   flag = TRUE 
-                JMP     2 $             \ else 
-        1 $:    MOV     AX, # 0           flag = FALSE 
-        2 $:    POP     DS              \ restore ds 
-                PUSH    AX              \ push flag on stack 
-                NEXT 
-                END-CODE 
-comment:        ------------------------------------------------------- 
-set-dta.dir     Set the disk transfer area address. 
-comment; 
- 
-CODE    set-dta.dir   ( addr -- )       \ set disk transfer area address 
-                POP     DX              \ dx = dta address 
-                PUSH    DS              \ save ds 
-                MOV     AX, CS 
-                MOV     DS, AX          \ ds = cs 
-                MOV     AX, # 1A00      \ ah = 1A 
-                INT     21              \ DOS function call 
-                POP     DS              \ restore ds 
-                NEXT 
-                END-CODE 
-DECIMAL 
- 
-comment: 
- 
-7.6  READING NUMBERS AND STRINGS 
- 
-                The following words can be used to read bytes, numbers 
-                and strings from a disk file. 
- 
-                ------------------------------------------------------ 
-get.fn          enter a filename from the keyboard and 
-                store it as an asciiz string in fname. 
-comment; 
- 
-: get.fn        ( -- ) 
-                QUERY BL WORD           \ addr 
-                DUP C@ 1+               \ addr cnt+1 
-                2DUP +                  \ addr len addr.end 
-                0 SWAP C!               \ make asciiz string 
-                SWAP 1+ SWAP            \ addr+1 len 
-                fname SWAP              \ from to len 
-                CMOVE ; 
- 
-comment:        ------------------------------------------------------ 
-open.filename   Enter a filename, open it, and store its 
-                handle in the variable 'handl'. 
-comment; 
- 
-: open.filename         ( -- ) 
-                get.fn 
-                fname open/create 
-                handl ! ; 
- 
-comment:        ------------------------------------------------------ 
-eof?            If an end-of-file was read (eof = true) 
-                then exit word containing eof?. 
-comment; 
- 
-: eof?          ( -- ) 
-                eof @ 
-                IF 
-                   2R> 2DROP EXIT 
-                THEN ; 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-comment:        ------------------------------------------------------- 
-get.next.byte   Get the next byte from the disk file 
-                whose handle is in 'handl'. 
-                Sets eof variable to true if eof. 
-comment; 
- 
-: get.next.byte         ( -- byte ) 
-                handl @ 1 PAD read.file 
-                IF 
-                   FALSE eof ! PAD C@ 
-                ELSE 
-                   TRUE eof ! 
-                THEN ; 
- 
-comment:        ------------------------------------------------------- 
-get.next.val    Read the next 16-bit value (2 bytes) from the 
-                disk file whose handle is in 'handl'. 
-                Sets eof variable to true if eof. 
-                Useful if actual numbers, rather than ASCII data, 
-                is stored on the disk file. 
-comment; 
- 
-: get.next.val          ( -- n ) 
-                handl @ 2 PAD read.file 
-                IF 
-                   FALSE eof ! PAD @ 
-                ELSE 
-                   TRUE eof ! 
-                THEN ; 
- 
-comment:        ------------------------------------------------------- 
-get.next.dval   Read the next 32-bit value (4 bytes) from the 
-                disk file whose handle is in 'handl'. 
-                Sets eof variable to true if eof. 
-                Useful if actual numbers, rather than ASCII data, 
-                is stored on the disk file. 
-comment; 
- 
-: get.next.dval          ( -- d ) 
-                handl @ 4 PAD read.file 
-                IF 
-                   FALSE eof ! PAD 2@ 
-                ELSE 
-                   TRUE eof ! 
-                THEN ; 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-comment:        ------------------------------------------------------- 
-parenchk        If the byte on the stack is a '(' 
-                read the file until the byte following 
-                the next ')' is read. 
-                Exits if eof is read. 
-comment; 
- 
-: parenchk      ( byte -- byte ) 
-                DUP ASCII ( = 
-                IF 
-                   DROP 
-                   BEGIN 
-                      get.next.byte eof? 
-                      ASCII ) = 
-                   UNTIL 
-                   get.next.byte eof? 
-                THEN ; 
- 
-comment:        ------------------------------------------------------- 
-quotechk        If the byte on the stack is a quote (") 
-                read the file until the byte following 
-                the next quote (") is read. 
-                Exits if eof is read. 
-comment; 
- 
-: quotechk      ( byte -- byte ) 
-                DUP ASCII " = 
-                IF 
-                   DROP 
-                   BEGIN 
-                      get.next.byte eof? 
-                      ASCII " = 
-                   UNTIL 
-                   get.next.byte eof? 
-                THEN ; 
- 
-comment:        ------------------------------------------------ 
-?digit          Checks to see if the byte on the stack 
-                is the ASCII code of a valid digit in 
-                the current base. 
-comment; 
- 
-: ?digit        ( byte -- byte f ) 
-                DUP BASE @ DIGIT NIP ; 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-comment:        ------------------------------------------------ 
-get.next.digit  Gets the next valid ASCII digit 
-                from the disk file. 
-                Exits if eof is read. 
-comment; 
- 
-: get.next.digit        ( -- digit ) 
-                BEGIN 
-                   get.next.byte eof? 
-                   parenchk eof? 
-                   quotechk eof? 
-                   ?digit NOT 
-                WHILE 
-                   DROP 
-                REPEAT ; 
- 
-comment:        ------------------------------------------------ 
-get.digit/minus   Gets the next valid ASCII digit 
-                  or a minus sign from the disk file. 
-                  Exits if eof is read. 
-comment; 
- 
-: get.digit/minus        ( -- digit or - ) 
-                BEGIN 
-                   get.next.byte eof? 
-                   parenchk eof? 
-                   quotechk eof? 
-                   DUP ASCII - = 
-                   SWAP ?digit ROT OR NOT 
-                WHILE 
-                   DROP 
-                REPEAT ; 
- 
-comment:        --------------------------------------------------- 
-get.next.number   gets the next signed integer stored 
-                  as an ASCII string on the disk and 
-                  converts it to a signed 16-bit integer. 
-                  exits if eof is read. 
-comment; 
- 
-: get.next.number       ( -- n ) 
-                { get.digit/minus eof?          \ uses {  } to store 
-                BEGIN                           \ consecutive digits 
-                   get.next.byte eof?           \ on the stack. 
-                   parenchk eof?                \ ignore (...) 
-                   quotechk eof?                \  and "..." 
-                   ?digit NOT 
-                UNTIL 
-                DROP } 
-                DUP PAD C! 
-                DUP PAD + BL OVER 1+ C! 
-                SWAP 0 DO                       \ move digits on stack 
-                   SWAP OVER C! 1-              \ to counted string as PAD 
-                LOOP 
-                NUMBER DROP ;                   \ convert to number 
- 
-comment:        ---------------------------------------------------- 
-?period         Checks to see if a byte is a period. 
-                Note that the flag is left as the 
-                second element on the stack. 
-comment; 
- 
-: ?period       ( byte -- f byte ) 
-                DUP ASCII . = SWAP ; 
- 
-comment:        ---------------------------------------------------- 
-get.next.dnumber        Gets the next signed real number stored 
-                        as an ASCII string on the disk and 
-                        converts it to a signed double 
-                        number on the stack. 
-                        The number of digits after the decimal 
-                        point is stored in the variable DPL. 
-                        Exits if eof is read. 
-comment; 
- 
-: get.next.dnumber       ( -- dn ) 
-                { get.digit/minus eof? 
-                BEGIN 
-                   get.next.byte eof? 
-                   parenchk eof?                \ similar to 
-                   quotechk eof?                \ get.next.number 
-                   ?period                      \ but include period 
-                   ?digit ROT OR NOT            \ in number string 
-                UNTIL 
-                DROP } 
-                DUP PAD C! 
-                DUP PAD + BL OVER 1+ C! 
-                SWAP 0 DO 
-                   SWAP OVER C! 1- 
-                LOOP 
-                NUMBER  ;                       \ convert to double number 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-comment:        ---------------------------------------------------- 
-get.next.string         Reads the next string enclosed between 
-                        double quotes "....." in the disk file 
-                        and stores it as a counted string at "addr". 
-comment; 
- 
-: get.next.string       ( -- addr )  \ counted string 
-                BEGIN 
-                   get.next.byte eof? 
-                   ASCII " = 
-                UNTIL 
-                0 PAD 1+ 
-                BEGIN                   \ cnt addr 
-                   get.next.byte eof? 
-                   DUP ASCII " <> 
-                WHILE 
-                   OVER C! 
-                   SWAP 1+ SWAP 
-                   1+ 
-                REPEAT 
-                2DROP PAD C! PAD ; 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-comment: 
- 
-7.7  WRITING NUMBERS AND STRINGS 
- 
-                --------------------------------------------------- 
-send.byte       Sends a byte to the opened disk file 
-                whose handle is in 'handl'. 
-comment; 
- 
-: send.byte     ( byte -- ) 
-                PAD C! 
-                handl @ 
-                1 PAD write.file ; 
- 
-comment:        --------------------------------------------------- 
-send.number     Sends a signed 16-bit number as an 
-                ASCII string to the opened disk file 
-                whose handle is in 'handl'. 
-comment; 
- 
-: send.number   ( n -- ) 
-                (.) 0 
-                DO 
-                   DUP C@ send.byte 
-                   1+ 
-                LOOP 
-                DROP ; 
- 
-comment:        --------------------------------------------------- 
-send.number.r   Sends a signed 16-bit number as an 
-                ASCII string to the opened disk file 
-                whose handle is in 'handl'. 
-                The number will be right-justified in a 
-                field of width "len", padded with leading 
-                ascii blanks. 
-comment; 
- 
-: send.number.r         ( n l -- ) 
-                >R (.) R> 
-                OVER - 
-                0 DO 
-                   BL send.byte 
-                LOOP 
-                0 DO 
-                   DUP C@ send.byte 1+ 
-                LOOP 
-                DROP ; 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-comment:        --------------------------------------------------- 
-send.dnumber    Sends a signed 32-bit number as an 
-                ASCII string to the opened disk file 
-                whose handle is in 'handl'. 
-                The decimal point is positioned according 
-                to the contents of DPL. 
-comment; 
- 
-: send.dnumber  ( d -- )  \ DPL = #digits after dec. point 
-                TUCK DABS <# DPL @ ?DUP 
-                IF 
-                   0 DO # LOOP 
-                   ASCII . HOLD 
-                THEN 
-                #S ROT SIGN #> 
-                0 DO 
-                   DUP C@ send.byte 1+ 
-                LOOP DROP ; 
- 
-: send.val      ( n -- )                        \ send 16-bit value 
-                PAD ! handl @ 
-                2 PAD write.file ; 
- 
-: send.dval      ( d -- )                       \ send 32-bit value 
-                PAD 2! handl @ 
-                4 PAD write.file ; 
- 
-: send.string   ( addr -- )             \ addr of counted string 
-                DUP C@ 
-                SWAP 1+ SWAP 
-                0 DO 
-                   DUP I + C@ 
-                   send.byte 
-                LOOP 
-                DROP ; 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
-: send.crlf     ( -- ) 
-                13 send.byte 
-                10 send.byte ; 
- 
-: send.lf     ( -- ) 
-                10 send.byte ; 
- 
-: send.cr       ( -- ) 
-                13 send.byte ; 
- 
-: send.tab      ( -- ) 
-                9 send.byte ; 
- 
-: send.(        ( -- ) 
-                ASCII ( send.byte ; 
- 
-: send.)        ( -- ) 
-                ASCII ) send.byte ; 
- 
-: send.,        ( -- ) 
-                ASCII , send.byte ; 
- 
-: send."        ( -- ) 
-                ASCII " send.byte ; 
- 
-: send."string"         ( addr -- ) 
-                send." 
-                send.string 
-                send." ; 
- 
- 
-</code> 
papierkorb/4th_lesson_7.1755364236.txt.gz · Zuletzt geändert: 2025-08-16 19:10 von mka