papierkorb:4th_lesson_7
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| papierkorb:4th_lesson_7 [2025-08-16 19:10] – ↷ Seite von projects:4th_lesson_7 nach papierkorb:4th_lesson_7 verschoben mka | papierkorb:4th_lesson_7 [Unbekanntes Datum] (aktuell) – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | === Lesson 7 === | ||
| - | < | ||
| - | \ | ||
| - | \ 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.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.7 WRITING NUMBERS AND STRINGS | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | 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. | ||
| - | using the CODE word to define a Forth word. The general form of | ||
| - | the CODE word is as follows: | ||
| - | |||
| - | CODE < | ||
| - | < | ||
| - | <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 < | ||
| - | word END-CODE takes the place of the semi-colon and ends the code | ||
| - | word definition. | ||
| - | |||
| - | The < | ||
| - | notation. | ||
| - | look very much like standard 8086/8088 assembly language. | ||
| - | Forth word PREFIX needs to be executed before the CODE word is | ||
| - | compiled. | ||
| - | |||
| - | The <return command> can be any of the following: | ||
| - | |||
| - | NEXT JMP > | ||
| - | |||
| - | 1PUSH PUSH AX | ||
| - | JMP > | ||
| - | |||
| - | 2PUSH PUSH DX | ||
| - | PUSH AX ( pushes dx and ax on the stack | ||
| - | JMP > | ||
| - | |||
| - | Debugging CODE words is made easier using the 8088 Tutor monitor | ||
| - | that is included with this Forth Course. | ||
| - | 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" | ||
| - | |||
| - | 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 < | ||
| - | the address < | ||
| - | |||
| - | 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 " | ||
| - | the code segment. | ||
| - | by the Forth word ?CS: and will be printed on the screen when you | ||
| - | type the word " | ||
| - | |||
| - | A five byte space is reserved at the offset address " | ||
| - | The offset addresses for " | ||
| - | the stack, and the CFA of CMOVE will also be printed on the screen | ||
| - | when you type " | ||
| - | comment; | ||
| - | |||
| - | HEX | ||
| - | CREATE source.addr 11 C, 22 C, 33 C, 44 C, 55 C, | ||
| - | CREATE dest.addr | ||
| - | 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. | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | | ||
| - | |||
| - | code segment = E74 | ||
| - | source addr = 6929 | ||
| - | dest addr = 6931 | ||
| - | top of stack = FFE2 | ||
| - | address of CMOVE = 41C | ||
| - | |||
| - | Your values may be different. | ||
| - | 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 > | ||
| - | Type /GSE74 to display the data segment = code segment. | ||
| - | Type /GO6929 to display the " | ||
| - | 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, | ||
| - | five times will move the five bytes from " | ||
| - | " | ||
| - | |||
| - | 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 " | ||
| - | 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. | ||
| - | to use this word if you are moving a string up in memory where the | ||
| - | destination string may overlap the source string. | ||
| - | 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, | ||
| - | and BEGIN...UNTIL together with the following code conditionals: | ||
| - | |||
| - | Forth | ||
| - | |||
| - | 0= JNE/JNZ | ||
| - | 0<> | ||
| - | 0< JNS | ||
| - | 0> | ||
| - | < | ||
| - | >= JL/JNGE | ||
| - | <= JNLE/JG | ||
| - | > | ||
| - | U< JNB/JAE/JNC | ||
| - | U> | ||
| - | U< | ||
| - | 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 | ||
| - | POP | ||
| - | 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 | ||
| - | POP | ||
| - | POP | ||
| - | MOV | ||
| - | 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 | ||
| - | \ 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. | ||
| - | of file I/O words that you can use and extend to handle a variety | ||
| - | of file I/O and other DOS operations. | ||
| - | 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. | ||
| - | |||
| - | { 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; | ||
| - | |||
| - | : $> | ||
| - | 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. | ||
| - | and an error flag on the stack. | ||
| - | is TRUE, the error code is in ax (3rd element on the | ||
| - | stack). | ||
| - | 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 | ||
| - | U>= | ||
| - | IF \ if carry = 0 | ||
| - | | ||
| - | ELSE \ else | ||
| - | | ||
| - | 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 | ||
| - | 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 | ||
| - | 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 | ||
| - | 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 | ||
| - | Prints error message if unable to close. | ||
| - | comment; | ||
| - | |||
| - | : close.file | ||
| - | 3E00 \ ah = 3E | ||
| - | SWAP 0 0 \ bx = handle | ||
| - | 2fdos | ||
| - | NIP \ nip dx | ||
| - | IF | ||
| - | | ||
| - | THEN | ||
| - | DROP ; | ||
| - | |||
| - | comment: | ||
| - | create.file | ||
| - | addr points to an asciiz string | ||
| - | attr is the file attribute: 0 - normal file | ||
| - | 01H - read only 02H - hidden | ||
| - | 04H - system | ||
| - | 10H - subdirectory | ||
| - | comment; | ||
| - | |||
| - | : create.file | ||
| - | 3C00 \ ah = 3C | ||
| - | 0 2SWAP SWAP \ 3C00 0 attr addr | ||
| - | 2fdos | ||
| - | NIP ; \ nip dx | ||
| - | |||
| - | |||
| - | comment: | ||
| - | open/ | ||
| - | otherwise creates a new normal file. | ||
| - | " | ||
| - | Returns a handle for the opened file. | ||
| - | Prints error messages if unable to open. | ||
| - | comment; | ||
| - | |||
| - | : open/ | ||
| - | 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 | ||
| - | 4100 | ||
| - | 0 ROT 0 SWAP | ||
| - | 2fdos | ||
| - | NIP ; | ||
| - | |||
| - | : erase.file | ||
| - | $>asciiz | ||
| - | delete.file | ||
| - | IF | ||
| - | CR ." Delete file error no. " . | ||
| - | ELSE | ||
| - | DROP | ||
| - | THEN ; | ||
| - | |||
| - | comment: | ||
| - | read.file | ||
| - | into buffer at ' | ||
| - | actually read. If this value is 0 then the | ||
| - | end of file was read. Prints error message | ||
| - | if unsuccessful. | ||
| - | comment; | ||
| - | |||
| - | : read.file | ||
| - | >R 3F00 \ handle #bytes 3F00 | ||
| - | -ROT R> \ 3F00 handle #bytes addr | ||
| - | 2fdos | ||
| - | NIP \ nip dx | ||
| - | IF | ||
| - | | ||
| - | THEN ; | ||
| - | |||
| - | comment: | ||
| - | write.file | ||
| - | to file with ' | ||
| - | if unsuccessful. | ||
| - | comment; | ||
| - | |||
| - | : write.file | ||
| - | >R 4000 \ handle #bytes 4000 | ||
| - | -ROT R> \ 4000 handle #bytes addr | ||
| - | 2fdos | ||
| - | NIP \ nip dx | ||
| - | IF | ||
| - | | ||
| - | ELSE | ||
| - | DROP | ||
| - | THEN ; | ||
| - | |||
| - | comment: | ||
| - | mov.ptr | ||
| - | 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 | ||
| - | 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 | ||
| - | to the start of file. | ||
| - | comment; | ||
| - | |||
| - | : rewind.file | ||
| - | 0 0 0 mov.ptr 2DROP ; | ||
| - | |||
| - | comment: | ||
| - | get.length | ||
| - | ' | ||
| - | comment; | ||
| - | |||
| - | : get.length | ||
| - | 0 0 2 mov.ptr ; | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | comment: | ||
| - | read.file.L | ||
| - | with handle " | ||
| - | extended memory at seg:offset. | ||
| - | comment; | ||
| - | |||
| - | CODE read.file.L | ||
| - | POP DX | ||
| - | POP DS | ||
| - | POP CX | ||
| - | POP BX | ||
| - | MOV AH, # 3F | ||
| - | INT 21 | ||
| - | U>= | ||
| - | IF | ||
| - | | ||
| - | ELSE | ||
| - | | ||
| - | THEN | ||
| - | MOV CX, CS \ restore DS | ||
| - | MOV DS, CX | ||
| - | PUSH AX | ||
| - | PUSH BX | ||
| - | NEXT | ||
| - | END-CODE | ||
| - | |||
| - | comment: | ||
| - | write.file.L | ||
| - | seg:offset to the opened file with handle " | ||
| - | comment; | ||
| - | |||
| - | CODE write.file.L | ||
| - | POP DX | ||
| - | POP DS | ||
| - | POP CX | ||
| - | POP BX | ||
| - | MOV AH, # 40 | ||
| - | INT 21 | ||
| - | U>= | ||
| - | IF | ||
| - | | ||
| - | ELSE | ||
| - | | ||
| - | THEN | ||
| - | MOV CX, CS \ restore DS | ||
| - | MOV DS, CX | ||
| - | PUSH AX | ||
| - | PUSH BX | ||
| - | NEXT | ||
| - | END-CODE | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | comment: | ||
| - | findfirst.dir | ||
| - | file specified by the asciiz string at " | ||
| - | comment; | ||
| - | |||
| - | CODE findfirst.dir ( addr -- f ) \ search directory for first match | ||
| - | POP | ||
| - | PUSH DS \ save ds | ||
| - | MOV AX, CS | ||
| - | MOV DS, AX \ ds = cs | ||
| - | MOV CX, # 10 \ attr includes subdirectories | ||
| - | MOV AX, # 4E00 \ ah = 4E | ||
| - | INT | ||
| - | JC 1 $ \ if no error | ||
| - | MOV AX, # FF \ flag = TRUE | ||
| - | JMP 2 $ \ else | ||
| - | 1 $: MOV AX, # 0 | ||
| - | 2 $: POP | ||
| - | PUSH AX \ push flag on stack | ||
| - | NEXT | ||
| - | END-CODE | ||
| - | |||
| - | comment: | ||
| - | findnext.dir | ||
| - | file specified by the asciiz string at " | ||
| - | 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 | ||
| - | JC 1 $ \ if no error | ||
| - | MOV AX, # FF \ flag = TRUE | ||
| - | JMP 2 $ \ else | ||
| - | 1 $: MOV AX, # 0 | ||
| - | 2 $: POP | ||
| - | PUSH AX \ push flag on stack | ||
| - | NEXT | ||
| - | END-CODE | ||
| - | comment: | ||
| - | set-dta.dir | ||
| - | comment; | ||
| - | |||
| - | CODE set-dta.dir | ||
| - | POP | ||
| - | PUSH DS \ save ds | ||
| - | MOV AX, CS | ||
| - | MOV DS, AX \ ds = cs | ||
| - | MOV AX, # 1A00 \ ah = 1A | ||
| - | INT | ||
| - | POP | ||
| - | 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 | ||
| - | 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 | ||
| - | handle in the variable ' | ||
| - | 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 | ||
| - | | ||
| - | THEN ; | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | comment: | ||
| - | get.next.byte | ||
| - | whose handle is in ' | ||
| - | Sets eof variable to true if eof. | ||
| - | comment; | ||
| - | |||
| - | : get.next.byte | ||
| - | handl @ 1 PAD read.file | ||
| - | IF | ||
| - | FALSE eof ! PAD C@ | ||
| - | ELSE | ||
| - | TRUE eof ! | ||
| - | THEN ; | ||
| - | |||
| - | comment: | ||
| - | get.next.val | ||
| - | disk file whose handle is in ' | ||
| - | 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 | ||
| - | handl @ 2 PAD read.file | ||
| - | IF | ||
| - | FALSE eof ! PAD @ | ||
| - | ELSE | ||
| - | TRUE eof ! | ||
| - | THEN ; | ||
| - | |||
| - | comment: | ||
| - | get.next.dval | ||
| - | disk file whose handle is in ' | ||
| - | 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 | ||
| - | handl @ 4 PAD read.file | ||
| - | IF | ||
| - | FALSE eof ! PAD 2@ | ||
| - | ELSE | ||
| - | TRUE eof ! | ||
| - | THEN ; | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | comment: | ||
| - | parenchk | ||
| - | read the file until the byte following | ||
| - | the next ' | ||
| - | Exits if eof is read. | ||
| - | comment; | ||
| - | |||
| - | : parenchk | ||
| - | DUP ASCII ( = | ||
| - | IF | ||
| - | DROP | ||
| - | BEGIN | ||
| - | get.next.byte eof? | ||
| - | ASCII ) = | ||
| - | UNTIL | ||
| - | | ||
| - | THEN ; | ||
| - | |||
| - | comment: | ||
| - | quotechk | ||
| - | read the file until the byte following | ||
| - | the next quote (") is read. | ||
| - | Exits if eof is read. | ||
| - | comment; | ||
| - | |||
| - | : quotechk | ||
| - | DUP ASCII " = | ||
| - | IF | ||
| - | DROP | ||
| - | BEGIN | ||
| - | get.next.byte eof? | ||
| - | ASCII " = | ||
| - | UNTIL | ||
| - | | ||
| - | THEN ; | ||
| - | |||
| - | comment: | ||
| - | ? | ||
| - | is the ASCII code of a valid digit in | ||
| - | the current base. | ||
| - | comment; | ||
| - | |||
| - | : ? | ||
| - | DUP BASE @ DIGIT NIP ; | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | comment: | ||
| - | get.next.digit | ||
| - | from the disk file. | ||
| - | Exits if eof is read. | ||
| - | comment; | ||
| - | |||
| - | : get.next.digit | ||
| - | BEGIN | ||
| - | | ||
| - | | ||
| - | | ||
| - | ? | ||
| - | WHILE | ||
| - | DROP | ||
| - | REPEAT ; | ||
| - | |||
| - | comment: | ||
| - | get.digit/ | ||
| - | or a minus sign from the disk file. | ||
| - | Exits if eof is read. | ||
| - | comment; | ||
| - | |||
| - | : get.digit/ | ||
| - | BEGIN | ||
| - | | ||
| - | | ||
| - | | ||
| - | DUP ASCII - = | ||
| - | SWAP ?digit ROT OR NOT | ||
| - | WHILE | ||
| - | DROP | ||
| - | REPEAT ; | ||
| - | |||
| - | comment: | ||
| - | get.next.number | ||
| - | 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 | ||
| - | { get.digit/ | ||
| - | BEGIN \ consecutive digits | ||
| - | | ||
| - | | ||
| - | | ||
| - | ? | ||
| - | 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: | ||
| - | ? | ||
| - | Note that the flag is left as the | ||
| - | second element on the stack. | ||
| - | comment; | ||
| - | |||
| - | : ? | ||
| - | DUP ASCII . = SWAP ; | ||
| - | |||
| - | comment: | ||
| - | get.next.dnumber | ||
| - | 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 | ||
| - | { get.digit/ | ||
| - | BEGIN | ||
| - | | ||
| - | | ||
| - | | ||
| - | ? | ||
| - | ? | ||
| - | UNTIL | ||
| - | DROP } | ||
| - | DUP PAD C! | ||
| - | DUP PAD + BL OVER 1+ C! | ||
| - | SWAP 0 DO | ||
| - | SWAP OVER C! 1- | ||
| - | LOOP | ||
| - | NUMBER | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | comment: | ||
| - | get.next.string | ||
| - | double quotes " | ||
| - | and stores it as a counted string at " | ||
| - | comment; | ||
| - | |||
| - | : get.next.string | ||
| - | BEGIN | ||
| - | | ||
| - | ASCII " = | ||
| - | UNTIL | ||
| - | 0 PAD 1+ | ||
| - | BEGIN \ cnt addr | ||
| - | | ||
| - | DUP ASCII " <> | ||
| - | WHILE | ||
| - | OVER C! | ||
| - | SWAP 1+ SWAP | ||
| - | 1+ | ||
| - | REPEAT | ||
| - | 2DROP PAD C! PAD ; | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | comment: | ||
| - | |||
| - | 7.7 WRITING NUMBERS AND STRINGS | ||
| - | |||
| - | --------------------------------------------------- | ||
| - | send.byte | ||
| - | whose handle is in ' | ||
| - | comment; | ||
| - | |||
| - | : send.byte | ||
| - | PAD C! | ||
| - | handl @ | ||
| - | 1 PAD write.file ; | ||
| - | |||
| - | comment: | ||
| - | send.number | ||
| - | ASCII string to the opened disk file | ||
| - | whose handle is in ' | ||
| - | comment; | ||
| - | |||
| - | : send.number | ||
| - | (.) 0 | ||
| - | DO | ||
| - | DUP C@ send.byte | ||
| - | 1+ | ||
| - | LOOP | ||
| - | DROP ; | ||
| - | |||
| - | comment: | ||
| - | send.number.r | ||
| - | ASCII string to the opened disk file | ||
| - | whose handle is in ' | ||
| - | The number will be right-justified in a | ||
| - | field of width " | ||
| - | ascii blanks. | ||
| - | comment; | ||
| - | |||
| - | : send.number.r | ||
| - | >R (.) R> | ||
| - | OVER - | ||
| - | 0 DO | ||
| - | BL send.byte | ||
| - | LOOP | ||
| - | 0 DO | ||
| - | DUP C@ send.byte 1+ | ||
| - | LOOP | ||
| - | DROP ; | ||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | |||
| - | comment: | ||
| - | send.dnumber | ||
| - | ASCII string to the opened disk file | ||
| - | whose handle is in ' | ||
| - | The decimal point is positioned according | ||
| - | to the contents of DPL. | ||
| - | comment; | ||
| - | |||
| - | : send.dnumber | ||
| - | 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 | ||
| - | PAD ! handl @ | ||
| - | 2 PAD write.file ; | ||
| - | |||
| - | : send.dval | ||
| - | PAD 2! handl @ | ||
| - | 4 PAD write.file ; | ||
| - | |||
| - | : send.string | ||
| - | DUP C@ | ||
| - | SWAP 1+ SWAP | ||
| - | 0 DO | ||
| - | DUP I + C@ | ||
| - | | ||
| - | 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." | ||
| - | send." | ||
| - | send.string | ||
| - | send." ; | ||
| - | |||
| - | |||
| - | </ | ||
papierkorb/4th_lesson_7.1755364236.txt.gz · Zuletzt geändert: 2025-08-16 19:10 von mka