PageRenderTime 72ms CodeModel.GetById 43ms RepoModel.GetById 1ms app.codeStats 0ms

/kernel_test.fth

https://github.com/august0815/forthos
Forth | 816 lines | 736 code | 80 blank | 0 comment | 35 complexity | df17e0a52bb898f3089f63cf29cd7d55 MD5 | raw file
  1. ; program: kernel_test
  2. ; Test for the kernel.
  3. ; License: GPL
  4. ; José Dinuncio <jdinunci@uc.edu.ve>, 12/2009.
  5. %include "forth.h"
  6. %include "kernel_words.h"
  7. %include "kernel_video.h"
  8. %include "kernel_kbd.h"
  9. %include "irq.h"
  10. extern name_getchar
  11. %undef OLDLINK
  12. %xdefine LINK name_getchar
  13. [BITS 32]
  14. : here
  15. DP @
  16. ;
  17. : print_scancode
  18. kbd_scancode dup intprint spc sc_to_c spc emit cr
  19. ;
  20. defvar "tic_count", tic_count, 0, 0
  21. : print_tic
  22. 1 tic_count +!
  23. tic_count @ 100 mod 0= if
  24. tic_msg printcstring cr
  25. then
  26. ;
  27. : print_scancodes
  28. begin print_scancode 0 until
  29. ;
  30. : print_interrupt
  31. fault printcstring cr
  32. ;
  33. ; prints an idt entry
  34. : print_idtentry
  35. dup 4 + @ swap @ ; wh wl
  36. dup hi hexprint spc ; sel
  37. lo hexprint spc ; base lo
  38. dup hi hexprint spc ; base hi
  39. lo 8 shr hexprint cr ; flags
  40. ;
  41. ; test irq
  42. defcode "test_irq", test_irq, 0
  43. int 33
  44. next
  45. ; divide by zero
  46. : div_by_zero
  47. 2 0 / drop
  48. ;
  49. ; Print hello word
  50. : print_hello
  51. hello printcstring cr
  52. ;
  53. %define _invoke_addr print_hello
  54. : test_invoke
  55. _invoke_addr execute
  56. ;
  57. ; function: store_in_buffer
  58. ;
  59. ; used by read_line
  60. ; Stack:
  61. ; ( char text_buffer text_buffer -- text_buffer )
  62. : store_in_buffer
  63. swap dup 1+ -rot c!
  64. ;
  65. ; function: read_line ; einlesen einer Zeile bis CR TESTED_OK
  66. ;
  67. ; Stack:
  68. ; address_of_text_buffer --
  69. ; zeile_buffer: ist 1024 byte lang
  70. : read_line
  71. 1
  72. begin
  73. while
  74. getchar dup 0x09 ;TAB
  75. =
  76. if
  77. drop tab ;branch repn
  78. then
  79. dup 0x0D =
  80. if
  81. drop 0x20 store_in_buffer
  82. 0 store_in_buffer
  83. drop
  84. exit
  85. then
  86. dup 0x08 ;BS backspace
  87. =
  88. if
  89. drop
  90. cursor_back ; del the char
  91. 0x20 emit cursor_back ; the position on back !
  92. 1- ; position of text_buffer(input) on back
  93. ;branch repn
  94. else
  95. dup emit store_in_buffer
  96. then
  97. 1
  98. repeat
  99. ;
  100. text_buffer: times 1024 db 0
  101. ; function: key1
  102. ;
  103. ; reads the next char in text_buffer PPTR points at
  104. ; Stack:
  105. ; -- char
  106. defcode "key1", key1 ,0
  107. xor eax,eax
  108. call _KEY1
  109. push eax
  110. next
  111. _KEY1:
  112. push ebx
  113. mov ebx,[var_PPTR]
  114. mov al,[ebx]
  115. inc ebx
  116. mov dword [var_PPTR],ebx
  117. pop ebx
  118. ret
  119. ; only test
  120. : tstout
  121. text_buffer dup
  122. cr printcstring cr
  123. '>' emit
  124. ;
  125. ; function: NUMBER TESTED_OK
  126. ;
  127. ; IN : ecx length of string
  128. ;
  129. ; edi start address of string
  130. ;
  131. ; OUT:eax parsed number
  132. ;
  133. ; ecx number of unparsed characters (0 = no error)
  134. defcode "number", number, 0
  135. pop ecx ; length of string
  136. pop edi ; start address of string
  137. call _NUMBER
  138. push eax ; parsed number
  139. push ecx ; number of unparsed characters (0 = no error)
  140. next
  141. _NUMBER:
  142. xor eax,eax
  143. xor ebx,ebx
  144. test ecx,ecx ; trying to parse a zero-length string is an error, but will return 0.
  145. jz .5
  146. mov edx,[var_BASE] ; get BASE (in %dl)
  147. ; Check if first character is '-'.
  148. mov bl,[edi] ; %bl = first character in string
  149. inc edi
  150. push eax ; push 0 on stack
  151. cmp bl,'-' ; negative number?
  152. jnz .2
  153. pop eax
  154. push ebx ; push <> 0 on stack, indicating negative
  155. dec ecx
  156. jnz .1
  157. pop ebx ; error: string is only '-'.
  158. mov ecx, $1
  159. ret
  160. ; Loop reading digits.
  161. .1: imul eax,edx ; %eax *= BASE
  162. mov bl,[edi] ; %bl = next character in string
  163. inc edi
  164. ; Convert 0-9, A-Z to a number 0-35.
  165. .2: sub bl,'0' ; < '0'?
  166. jb .4
  167. cmp bl,$10 ; <= '9'?
  168. jb .3
  169. sub bl,$17 ; < 'A'? (17 is 'A'-'0')
  170. jb .4
  171. add bl,$10
  172. .3: cmp bl,dl ; >= BASE?
  173. jge .4
  174. ; OK, so add it to %eax and loop.
  175. add eax,ebx
  176. dec ecx
  177. jnz .1
  178. ; Negate the result if first character was '-' (saved on the stack).
  179. .4: pop ebx
  180. test ebx,ebx
  181. jz .5
  182. neg eax
  183. .5: ret
  184. ; function: FIND TESTED_OK
  185. ;
  186. ; IN: ecx = length
  187. ; edi = address
  188. ;
  189. ;OUT: ; eax = address of dictionary entry (or NULL)
  190. defcode "find", find, 0
  191. pop ecx ; ecx = length
  192. pop edi ; edi = address
  193. call _FIND
  194. push eax ; eax = address of dictionary entry (or NULL)
  195. next
  196. _FIND:
  197. push esi ; Save esi so we can use it in string comparison.
  198. ; Now we start searching backwards through the dictionary for this word.
  199. mov edx,[var_LATEST] ; LATEST points to name header of the latest word in the dictionary
  200. .1: test edx,edx ; NULL pointer? (end of the linked list)
  201. je .4
  202. ; Compare the length expected and the length of the word.
  203. ; Note that if the F_HIDDEN flag is set on the word, then by a bit of trickery
  204. ; this won't pick the word (the length will appear to be wrong).
  205. xor eax,eax
  206. mov al,[edx+4] ; %al = flags+length field
  207. and al,(0x20| 0x1f) ;F_HIDDEN|F_LENMASK) ; %al = name length
  208. cmp byte al,cl ; Length is the same?
  209. jne .2
  210. ; Compare the strings in detail.
  211. push ecx ; Save the length
  212. push edi ; Save the address (repe cmpsb will move this pointer)
  213. lea esi,[edx+5] ; Dictionary string we are checking against.
  214. repe cmpsb ; Compare the strings.
  215. pop edi
  216. pop ecx
  217. jne .2 ; Not the same.
  218. ; The strings are the same - return the header pointer in %eax
  219. pop esi
  220. mov eax,edx
  221. ret
  222. .2: mov edx,[edx] ; Move back through the link field to the previous word
  223. jmp .1 ; .. and loop.
  224. .4: ; Not found.
  225. pop esi
  226. xor eax,eax ; Return zero to indicate not found.
  227. ret
  228. ; function: ">CFA" TESTED_OK
  229. defcode ">cfa", tcfa, 0
  230. pop edi
  231. call _TCFA
  232. push edi
  233. next
  234. _TCFA:
  235. xor eax,eax
  236. add edi,4 ; Skip link pointer.
  237. mov al,[edi] ; Load flags+len into %al.
  238. inc edi ; Skip flags+len byte.
  239. and al,0x1f ;F_LENMASK ; Just the length, not the flags.
  240. add edi,eax ; Skip the name.
  241. add edi,3 ; The codeword is 4-byte aligned.
  242. and edi,~3
  243. ret
  244. ; function: >DFA
  245. defword ">dfa", tdfa, 0
  246. dd tcfa ; (get code field address)
  247. dd incr4 ; (add 4 to it to get to next word)
  248. dd exit
  249. ; function: head
  250. defcode "head", head, 0
  251. pop ecx
  252. pop edx
  253. mov edi, [var_DP]
  254. mov eax, [var_LATEST]
  255. stosd
  256. ;xor eax, eax
  257. ;stosb
  258. mov al, cl
  259. stosb
  260. push esi
  261. mov esi, edx
  262. rep movsb
  263. pop esi
  264. lea edi,[edi+3]
  265. and edi, ~3
  266. mov eax, [var_DP]
  267. mov [var_LATEST], eax
  268. mov [var_DP], edi
  269. next
  270. : header
  271. wort head
  272. ;
  273. ;-------------------test-------------------------------------
  274. DOVAR:
  275. add eax,4
  276. push eax
  277. next
  278. : create
  279. header lit [#] DOVAR comma
  280. ;
  281. ;-------------------test-------------------------------------
  282. ; defcode; "," TESTED_OK
  283. defcode ",", comma, 0
  284. pop eax ; Code pointer to store.
  285. call _COMMA
  286. next
  287. _COMMA:
  288. mov edi,[var_DP] ; DP
  289. stosd ; Store it.
  290. mov dword [var_DP],edi ; DP
  291. ret
  292. ; function: [
  293. defcode "[", LBRAC, 0x80 ;;F_IMMED,LBRAC,0
  294. mov dword [var_STATE],0 ; Set STATE to 0.
  295. next
  296. ; function: ]
  297. defcode "]", RBRAC, 0
  298. mov dword [var_STATE],1 ; Set STATE to 1.
  299. next
  300. ; function: :
  301. ; [#] needed by forth2s.py to compile -> dd DOCOL (not litn DOCOL)
  302. defword ":", colon, 0
  303. dd wort ; Get the name of the new word
  304. dd head ; HEADER the dictionary entry / header
  305. dd lit
  306. dd DOCOL
  307. dd comma ; Append DOCOL (the codeword).
  308. dd LATEST
  309. dd fetch
  310. dd hidden ; Make the word hidden (see below for definition).
  311. dd RBRAC ; Go into compile mode.
  312. dd exit
  313. defword ";",SEMICOLON,0x80
  314. dd STATE , fetch
  315. if
  316. dd lit, exit, comma ; Append EXIT (so the word will return).
  317. dd LATEST, fetch, hidden ; Toggle hidden flag -- unhide the word (see below for definition).
  318. dd LBRAC ; Go back to IMMEDIATE mode.
  319. then
  320. dd exit
  321. ; function: IMMEDIATE TESTED_OK
  322. defcode "immediate", immediate, 0x80 ; F_IMMED
  323. mov edi,[var_LATEST] ; LATEST word.
  324. add edi,4 ; Point to name/flags byte.
  325. xor byte [edi],0x80 ; F_IMMED ; Toggle the IMMED bit.
  326. next
  327. ; function: HIDDEN
  328. defcode "hidden", hidden, 0
  329. pop edi ; Dictionary entry.
  330. add edi,4 ; Point to name/flags byte.
  331. xor byte [edi],0x20 ;F_HIDDEN ; Toggle the HIDDEN bit.
  332. next
  333. ; function: HIDE
  334. : hide
  335. wort ; Get the word (after HIDE).
  336. find ; Look up in the dictionary.
  337. hidden ; Set F_HIDDEN flag.
  338. ;
  339. ; function: "'" TESTED_OK
  340. defcode "'", tick, 0
  341. lodsd ; Get the address of the next word and skip it.
  342. push eax ; Push it on the stack.
  343. next
  344. ; TODO Branching??
  345. ; function: LITSTRING
  346. defcode "litstring", litstring, 0
  347. lodsd ; get the length of the string
  348. push esi ; push the address of the start of the string
  349. push eax ; push it on the stack
  350. add esi,eax ; skip past the string
  351. add esi,3 ; but round up to next 4 byte boundary
  352. and esi,~3
  353. next
  354. ; function: WORT rename later to WORD via alias
  355. ;
  356. ; gibt den pointer des strings aus zeilenbuffer bis zum Leerzeichen
  357. ; zurück , PPTR zeigt danach auf das nächste Wort
  358. ; edi ; push base address
  359. ; ecx ; push length
  360. defcode "wort", wort , 0
  361. call _word
  362. push edi ; push base address
  363. push ecx ; push length
  364. next
  365. _word:
  366. ;/* Search for first non-blank character. Also skip \ comments. */
  367. mov ebx,[var_PPTR]
  368. .1:
  369. mov al,[ebx] ;_KEY ; get next key, returned in %eax
  370. test al,al
  371. jnz .5
  372. mov dword [var_END_OF_LINE],0xffff
  373. ret
  374. .5: inc ebx
  375. cmp al,'\' ; start of a comment?
  376. je .3 ; if so, skip the comment
  377. cmp al,' '
  378. jbe .1 ; if so, keep looking
  379. ;/* Search for the end of the word, storing chars as we go. */
  380. mov edi,ptr_buff ; pointer to return buffer
  381. .2:
  382. stosb ; add character to return buffer
  383. mov al,[ebx] ;_KEY ; get next key, returned in %eax
  384. inc ebx; _KEY ; get next key, returned in %al
  385. cmp al,' ' ; is blank?
  386. ja .2 ; if not, keep looping
  387. ;/* Return the word (well, the static buffer) and length. */
  388. sub edi,ptr_buff
  389. mov ecx,edi ; return length of the word
  390. mov edi,ptr_buff ; return address of the word
  391. mov dword [var_PPTR],ebx
  392. ret
  393. .4:
  394. ;/* Code to skip \ comments to end of the current line. */
  395. .3:
  396. mov al,[ebx] ;_KEY ; get next key, returned in %eax
  397. inc ebx ;_KEY
  398. cmp al,$13 ; end of line yet?
  399. jne .3
  400. jmp .1
  401. section .data ; NB: easier to fit in the .data section
  402. ; A static buffer where WORD returns. Subsequent calls
  403. ; overwrite this buffer. Maximum word length is 256 chars.
  404. ptr_buff: times 256 db 0
  405. section .text
  406. : quit
  407. R0 rsp!
  408. 1 begin while line_interpret ?stack -1 repeat ; loops forever
  409. ;
  410. ; function: TELL
  411. : tell
  412. drop printcstring ;printt
  413. ;
  414. ; function: echooff
  415. ;
  416. ; Stack:
  417. ; --
  418. : echooff
  419. 0 NOECHO !
  420. ;
  421. ; function: echoon
  422. ;
  423. ; Stack:
  424. ; --
  425. : echoon
  426. 1 NOECHO !
  427. ;
  428. ; function: PRESSKEY
  429. ;
  430. ; Stack:
  431. ; --
  432. : presskey
  433. key_press printcstring tab '!' emit getchar drop clear
  434. ;
  435. ;defcode: INTERPRET
  436. defcode "interpret", interpret, 0
  437. mov dword [var_PARS_ERROR],0
  438. call _word ; Returns %ecx = length, %edi = pointer to word.
  439. ; Is it in the dictionary?
  440. xor eax,eax
  441. mov dword [interpret_is_lit],eax ; Not a literal number (not yet anyway ...)
  442. call _FIND ; Returns %eax = pointer to header or 0 if not found.
  443. test eax,eax ; Found?
  444. jz .1
  445. ; In the dictionary. Is it an IMMEDIATE codeword?
  446. mov edi,eax ; %edi = dictionary entry
  447. mov al,[edi+4] ; Get name+flags.
  448. push ax ; Just save it for now.
  449. call _TCFA ; Convert dictionary entry (in %edi) to codeword pointer.
  450. pop ax
  451. and al,0x80 ;F_IMMED ; Is IMMED flag set?
  452. mov eax,edi
  453. jnz .4 ; If IMMED, jump straight to executing.
  454. jmp .2
  455. .1: ; Not in the dictionary (not a word) so assume it's a literal number.
  456. ;
  457. inc dword [interpret_is_lit]
  458. call _NUMBER ; Returns the parsed number in %eax, %ecx > 0 if error
  459. test ecx,ecx
  460. jnz .6
  461. mov ebx,eax
  462. mov eax,lit ; The word is LIT
  463. .2: ; Are we compiling or executing?
  464. ;--------------NOW COMPILING !!-----------------------------
  465. mov dword edx, [var_STATE]
  466. test edx, edx
  467. jz .4 ; Jump if executing.
  468. ; Compiling - just append the word to the current dictionary definition.
  469. call _COMMA
  470. mov ecx, [interpret_is_lit] ; Was it a literal?
  471. test ecx, ecx
  472. jz .3
  473. mov eax,ebx ; Yes, so LIT is followed by a number.
  474. call _COMMA
  475. .3: next
  476. .4: ; Executing - run it!
  477. mov ecx,[interpret_is_lit] ; Literal?
  478. test ecx,ecx ; Literal?
  479. jnz .5
  480. ; Not a literal, execute it now. This never returns, but the codeword will
  481. ; eventually call next which will reenter the loop in QUIT.
  482. jmp [eax]
  483. .5: ; Executing a literal, which means push it on the stack.
  484. push ebx
  485. next
  486. .6: ; Parse error (not a known word or a number in the current BASE).
  487. ; Print an error message followed by up to 40 characters of context.
  488. ;mov ebx,2 ; 1st param: stderr
  489. mov dword [var_PARS_ERROR] ,0xffff
  490. next
  491. defcode "char", char, 0
  492. call _word
  493. xor eax,eax
  494. mov al,[edi]
  495. push eax
  496. next
  497. ; funktion: printt
  498. ; prints an string of len , pointer to string
  499. ;
  500. ; Stack:
  501. ; len pointer_to string --
  502. : printt
  503. 1- 0 do
  504. rot dup @ emit 1+ -rot
  505. loop
  506. drop
  507. ;
  508. ; funktion: U.
  509. ; for debuging
  510. : U.
  511. BASE @ /mod ?dup
  512. if ;( if quotient <> 0 then )
  513. U.
  514. else
  515. then
  516. dup 10 <
  517. if
  518. '0' ;(decimal digits 0..9 )
  519. else
  520. 10 - 'A'
  521. then
  522. + emit
  523. ;
  524. ; funktion: .S
  525. ; for debug
  526. : dotS
  527. '>' emit dsp@
  528. begin
  529. dup S0 @ <
  530. while
  531. dup @ U. spc 4+
  532. repeat
  533. drop '<' emit
  534. ;
  535. ; function: inter
  536. ;
  537. ;| the interpreter loop
  538. ;| tests for 'INTERPRET' errors and shows the result of interpret/compile
  539. ; Stack:
  540. ; --
  541. : inter
  542. 0 END_OF_LINE !
  543. NOECHO @ 0<>
  544. if
  545. cr
  546. then
  547. 1
  548. begin
  549. while
  550. interpret
  551. END_OF_LINE @ 0<> ; endof line Interprt was OK
  552. if
  553. NOECHO @ 0<>
  554. if
  555. cr ok printcstring cr
  556. then
  557. 0 dup END_OF_LINE ! PARS_ERROR !
  558. ;clear Error_flag
  559. ;clear End_of_Line fla
  560. exit
  561. then
  562. PARS_ERROR @ 0<> ; error in einput stream
  563. if
  564. cr 10 ink text_buffer printcstring
  565. cr 12 ink errmsg printcstring
  566. PPTR_LAST @ 10 printt cr
  567. 15 ink presskey
  568. 0 dup END_OF_LINE ! PARS_ERROR ! exit
  569. then
  570. PPTR @ PPTR_LAST !
  571. 1
  572. repeat
  573. ;
  574. ; function: to_PPTR
  575. ; store the value on stack to PPTR and increment PPTR and FILP
  576. ; Stack:
  577. ; char FILP -- FILP+1
  578. : to_PPTR
  579. PPTR @ c! 1 PPTR +! 1+
  580. ;
  581. ; function: endln
  582. ; store ";CR0" at end of line in text_buffer
  583. ; same as CR on keyboard input
  584. ; Stack:
  585. ; --
  586. : endln
  587. 0x3b to_PPTR FILP ! 0xd to_PPTR FILP ! 0x0 PPTR @ c!
  588. ;
  589. ; function: linecopy
  590. ; ( -- )
  591. ;| reads from source until ';' char is found in stream
  592. ;| replace in the stream
  593. ;| 'lf' with SPACE
  594. ;| 'tab' with SPACE
  595. ;| if ';' is found then 'CR' an 0 is added (to text_buffer)
  596. ;| this simulates an keyboard input with 'CR' , so the interpreter will
  597. ;| execute the line
  598. : linecopy
  599. dup c@ ; .s presskey ; IF LF is the first char
  600. 0x0a =
  601. if
  602. 0xd to_PPTR FILP ! 0x0 PPTR @ c! exit
  603. then
  604. 1
  605. begin while
  606. dup c@ dup 0x3b <> if
  607. dup 0x0a = ; wenn LF dann SPACE
  608. if
  609. drop 0x20
  610. then
  611. dup 0x09 = ; wenn TAB dann SPACE
  612. if
  613. drop 0x20
  614. then
  615. to_PPTR 1
  616. else
  617. endln exit
  618. then
  619. ; zeilemit ;.s presskey
  620. repeat
  621. endln ; CR and 0 -> ENDING 0 for PRINTSTRING
  622. ;
  623. ; function: interforth
  624. ; ( -- )
  625. ;| executes the loaded ( via GRUB) file
  626. : interforth
  627. echooff
  628. SRC @ FILP ! ; source file_position_pointer
  629. text_buffer PPTR ! ; input_line_source_pointer
  630. 1
  631. begin
  632. while
  633. FILP @
  634. linecopy
  635. text_buffer PPTR !
  636. NOECHO @ 0<>
  637. if
  638. cr cr text_buffer printcstring
  639. then
  640. inter ;zeilemit;presskey
  641. text_buffer dup PPTR_LAST ! ; remember the last word witch compiled without error
  642. PPTR !
  643. 1 FILP +!
  644. FILP @ c@ ; ; is next char = 0 ; then it is EOF
  645. ?dup
  646. if
  647. -1 FILP +! ; no , go for next line_input
  648. ;dd DROP
  649. else
  650. ;dd DROP
  651. exit ; yes , EOF
  652. then
  653. ;dd DROP
  654. 1
  655. repeat
  656. ;
  657. : zeilemit
  658. cr 10 0 do '-'emit loop cr '>'emit text_buffer printcstring '<' emit
  659. ;
  660. : teilemit
  661. cr 10 0 do '_'emit loop cr '>'emit ptr_buff printcstring '<' emit
  662. ;
  663. ; function: line_interpret
  664. ; ( -- )
  665. ;| reads stream of char to text_buffer
  666. ;| until 'CR' is hit
  667. : line_interpret
  668. text_buffer dup TEXT_BUFF ! read_line
  669. inter
  670. text_buffer dup PPTR_LAST ! PPTR !
  671. ;drop ; clsstack drop
  672. ;
  673. : depth
  674. S0 @ dsp@ - 4-
  675. ;
  676. : ?stack
  677. depth 0>
  678. if
  679. drop
  680. else
  681. stackerr printcstring
  682. S0 @ dsp!
  683. then
  684. ;
  685. : compile
  686. cr cr >dfa
  687. GRUB @ 0x14 + @
  688. GRUB @ 0x18 + @
  689. dup @ swap 4+ @ swap
  690. 2dup - rot drop ;.s cr presskey printt presskey
  691. GRUB @ 0x14 + @
  692. GRUB @ 0x18 + @
  693. dup @ swap 4+ @ swap
  694. 2dup - rot SRC_END ! 0 SRC_END c! ; Store 0 (EOF ) TO SRC_END
  695. swap dup SRC ! 2drop 2drop interforth
  696. text_buffer TEXT_BUFF ! 1 TEXT_BUFF @ c! ; init
  697. S0 @ dsp!
  698. text_buffer dup PPTR_LAST ! PPTR !
  699. ;
  700. extern module
  701. ; function: main
  702. ; The first forth word executed by the kernel.
  703. : main_test
  704. clear module @ GRUB !
  705. 0x101006 print_idtentry
  706. 0x10100E print_idtentry
  707. 0x101016 print_idtentry
  708. ;[`] print_scancode 33 register_isr_handler
  709. ;[`] print_tic 32 register_isr_handler
  710. compile
  711. quit
  712. stop
  713. ;
  714. global last_word
  715. ; function: tst
  716. ; dummy for marking LATEST
  717. ; Stack:
  718. ; --
  719. last_word:
  720. : tst
  721. cr 10 0 do '-'emit loop cr
  722. ;
  723. section .rodata
  724. hello: db "hello, world", 0
  725. fault: db "A fault happened", 0
  726. tic_msg: db "The clock tics", 0
  727. ok: db ' OK ... ' ,0
  728. key_press: db ' PRESS ANY KEY .... ' , 0
  729. outputmes: db 'Words of forth' , 0
  730. inputloop: db 'Enter words' , 0
  731. errmsg: db 'PARSE ERROR: AT ->' ,0
  732. gef: db 'GEFUNDEN' , 0
  733. ngef: db 'NICHT IN TABELLE' , 0
  734. stackmes: db 'STACK> ', 0
  735. stackerr: db ' STACK undeflow .. reset STACK !' ,0
  736. interpret_is_lit: db 0