body, table{font-family: 微软雅黑; font-size: 13.5pt}
table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;}
th{border: 1px solid gray; padding: 4px; background-color: #DDD;}
td{border: 1px solid gray; padding: 4px;}
tr:nth-child(2n){background-color: #f8f8f8;}

      解释状态==执行状态         编译地址==执行地址

      FORTH 系统内部有一个系统变量 STATE,当 STATE==0,系统处于"执行"状态,当 STATE <> 0,系统处于"编译"状态。系统从输入缓冲区中取出下一个字符串放到词缓冲区,然后去词典中查找该词;如果该词在词典中,就把该词的定义的编译地址(cfa,也叫执行地址)送到参数栈顶。然后,如果系统处于执行状态,则外部解释程序(即文本解释程序)就调用内部解释程序(地址解释程序)执行该定义;如果系统处于编译状态,则编译程序就把留在参数栈顶的 cfa 移到词典的顶部,把该定义的 cfa 编入到正在被编译的定义的参数域中,但是,如果cfa所代表的定义是一个立即词,不管系统处于什么状态,都执行它。
      若输入流中分离出来的字符串在词典中没有定义,系统就把它转化成一个数字,如果成功,文本解释程序就把该数字放置到参数栈上;若系统处于编译状态,则编译程序就把该数字编入词典成为一个数字文字常数(literal)。
      

定义 [ 和 ] :
      FORTH 提供 [ 和 ] 这两个定义以显示改变系统的状态,[ 使系统从编译状态变为执行状态;] 使系统从执行状态变为编译状态。这两个定义均只能在冒号定义中使用。若  [  ] 成对出现在冒号定义中,则包含的部分被立即执行而不被编译。

文字常数:
      FORTH 中,有一些进行编译工作的词,称为编译类词。它们的效果是给词典中编译进这样或那样的内容。可以把参数堆栈上的数字“原封不动”的搬进词典形成“文字常数(literal)”;所以在词典中不少情况下是编译地址和文字常量并存的局面。五个编译词:LIT、LITERAL、(DLITERAL)、COMPILE、[COMPILE]。
:   LIT    ( - n )       编译数字的运行时间代码
        R@  @         取出编译在词身内的数字
        R>  2+  >R  ;        调整IP


运行时 LIT 做两项工作:
1、它必须把跟着它的数字放到参数堆栈顶;
2、它必须移动解释指针 IP 越过这个数字而指向下一个编译地址。
:  FIVE+   5  +  ;

FIVE+ ^LIT 5 ^+ ^UNNEST
1000 1002 1004 1006
开始执行 LIT 之前,IP 偏移指向 5 。即(IP)=1002。执行 LIT,由于 LIT 是冒号定义,所以先执行的是 LIT 的代码指针域 cfa 内的 NEST,执行过程:
1、(IP) -> 返回栈顶保存,于是返回栈首项的内容为1002
2、(W)+2 -> W  它是 LIT 的 pfa
3、(W) -> IP  
4、执行 NEST 内最后的 NEXT ,于是就开始执行 LIT 的词身
^R@  把返回栈顶的内容1002复制到参数栈顶  ^@ 取出1002单元的内容5   ^R> 把返回栈顶的1002送到参数栈顶  ^2+  参数栈首项变为1004,指着下一个要执行的词 +  ^>R 把1004送回返回栈顶保存  ^UNNEST 把返回栈顶的1004 -> IP,接着执行1004处的 +。
:  COMPILE   ( - )      只可以用在冒号定义内部。当该冒号定义执行时,COMPILE 就把跟在它后面的定义编译进词典中。
         R>
         DUP  2+  >R
         @  ,  ;


与 LIT 定义相比,COMPILE 仅仅在定义的最后多了一个逗号,由它把留在堆栈顶上的跟在 COMPILE 之后的词的 cfa 编入词典
:  LITERAL   ( n -  )       把在参数栈上的单字长整数编译成为一个文字常数。
       COMPILE  LIT       首先编译运行时间代码 LIT
       ,                             接着编译数字本身
       ;  IMMEDIATE      使其成为立即词
eg:
:  test   [  5  ]  LITERAL  +  ;
//数字 5 必须处于词 [ 和 ] 中间。
:  DLITERAL   ( d -  )     把在参数栈上的双字长整数编译成为一个双字长的文字常量
        SWAP      颠倒双字长整数的次序
        [COMPILE]  LITERAL   把文字常数的编译推迟到 DLITERAL 执行时进行。因为 LITERAL 是立即词,故只有用[COMPILE]才能把它编入 DLITERAL 中。
        [COMPILE]  LITERAL   强行编译双字长文字常数的高16位。
        ;  IMMEDIATE
:  [COMPILE]   ( - )      强行编译跟着的立即型定义
          '           寻求跟着的词的执行地址
          ,           编译它
          ;  IMMEDIATE       必须立即执行

编译循环:
      FORTH 中编译过程与解释过程(即执行过程)的区别在于:在编译过程中,不是执行从输入流中分离出来的词,而是把词的编译地址添加到词典的顶部,在那儿系统正在构造一个新的冒号定义的参数域;如果从输入流中分离出来的是数字,那么编译过程不是把数字留在参数堆栈上,而是把它编译成为定义中的数字文字常数。以后当执行该定义时,同一数字便可被重新取出并放置到参数栈顶。冒号定义的编译程序就是定义 ] ,它和解释程序 INTERPERT 有类似操作。

冒号定义的开始和结束:
:    :    ( - )                    定义一个高级定义,新定义完成之前被"隐藏"起来,冒号的执行代码给程序增添一层嵌套
         !CSP            把当前参数堆栈指针存入变量CSP以在定义结束时查错之用,正常编译不应影响参数堆栈的深度
         CURRENT  @  CONTEXT  !                   使 context 词汇与 current 词汇一致
         CREATE                使用跟在冒号后面的名字在词典中建立一个首部
         HIDE                    使该首部躲过词典搜索
         ]                          进入冒号定义的编译程序,开始建造在参数域中的执行地址表
         ;USES                把跟着的代码程序(即下面的NEST)的地址插入到新定义的代码指针域,使新定义成为一个冒号定义。(类似DOES>,编译运行过程已经规定好的代码到代码域)
         NEST  ,                编译地址解释程序NEST的地址,使其可被放进新定义的cfa
:     ( - )           结束一个冒号定义,它编译执行代码UNNEST退出一层件嵌套,改变STATE的值以解释编译
         ?CSP             当前的参数堆栈指针与CSP的值相符吗?若不相符则停止
         COMPILE  UNNEST             给新定义的末尾加上UNNEST,使程序的执行返回到调用者
         REVEAL         与HIDE想反操作
         [COMPILE]  [         在此外编译,[  以结束新定义的编译 
         ;  IMMEDIATE       分号自身必须在编译状态下执行,所以必须是一个立即词。

数字文字常量:
      指的是词典中存放运行时间代码(LIT)的cfa的单元及跟着它的数字单元;执行是LIT把数字送到参数堆栈。LITERAL、DLITERAL、ASCII、[']……
:  ASCII      ( - char )         把输入流中下一个字符的ASCII代码编译为一个数字文字常量
        BL  WORD        取出下一个字符
        1+  C@          得到它的ASCII代码
        STATE  @         获取当前系统状态(编译?解释)
        IF  [COMPILE]  LITERAL          编译状态就把其编为文字常数
        THEN          否则留在参数堆栈上
        ;  IMMEDIATE
:  [']   ( - )
       '  
       [COMPILE]  LITERAL
       ;  IMMEDIATE
[']  被定义成为一个立即型的定义,因此对于 ['] 定义内的 ' 来说,所谓的输入流中的下一个词就是冒号定义内跟在 ['] 后面的那个词。

数字输出转换:

HLD  (- add)  在数字输出转换过程中,保存文本最后字符地址的变量。
:  HOLD   ( char -  )      把ASCII字符char插入输出字符串中
        -1  HLD  +!      HLD为指向输出文本缓冲区的字符指针,在输出文本缓冲区中形成输出数字字符串。数字字符串是从最低有效位开始逆向建立,为把一个字符插入该字符串。HLD 的内容要减一
         HLD  @       取到指定地址
         C!  ;        把字符串插入HLD所指定的地址字节
:  <#   ( - )        初始化数字转换过程,要求栈中是个无符号双字长数
       PAD                返回输出文本的缓冲区地址
       HLD  !  ;      HLD 指向 PAD ,以便字符串能在 PAD 缓冲区中建立
:  #>   ( d - addr len )         结束输出数字转换,并把字符串的地址和长度送入堆栈,它们正是 TYPE 命令所需要的参数
       2DROP       不再需要堆栈中的双字长数
       HLD  @            取出字符串首址
       PAD           取出字符串的末尾地址
       OVER  -  ;         得到字符串的长度
:  SIGN  ( n -  )          如果栈顶项 n 是负数,则在输出数字字符串中插入一个负号
       0<  IF       判断栈顶是不是负数
       ASCII  -  HOLD         插入负号
       THEN  ;   
:  #   ( d1 - d2  )           转换一位数字,并把它加到输出数字字符串中。转换中,d1除以基,商d2被保留在堆栈中,余数被转换成ASCII码,送入输出缓冲区
       BASE  @  MU/MOD         余数和双字长整数商保留在堆栈上
       ROT         把余数移到栈顶
       9  OVER  <        如果余数大于9
       IF  7  +  THEN       加7以形成A
       ASCII  0  +  HOLD  ;     把余数转换成 ASCII 码,并插入到输出缓冲区
:  #S  ( d - 0 0 )         转换一个双字长整数,直至结果为零
       BEGIN
           #       转换一位数字
           2DUP  OR        判断商是否为 0 ?
       0=  UNTIL  ;         如果商为零,退出循环;否则,继续转换。
eg:无符号双字长整数 12345.  ,要求打印成:123.45  ; 命令:<#  #  #  ASCII  .  HOLD  #s  #>  TYPE

小数点的前三位整数用 #S 实现转换。整个转换过程是在 PAD 缓冲区内进行的。转换完成堆栈顶部存放的是ASCII字符串的首地址和长度。

Forth 编译程序的更多相关文章

  1. delphi7 编译程序时报win32.indcu.a病毒的解决方法

    Delphi7用了很久一直都没问题,同一个工程文件昨天编译时mod32还不会报毒,今天重新编译时,生成的exe突然nod32报毒. 提示: “Project1.exe Win32/Induc.A 病毒 ...

  2. Flex编译程序出现 Could not find compiled resource bundle 'SharedResources' for locale 'en_US'.

    Flex编译程序出现 Could not find compiled resource bundle 'SharedResources' for locale 'en_US'. 而且静态类居然为nul ...

  3. 在Linux下如何使用GCC编译程序、简单生成 静态库及动态库

      最近在编写的一个Apache  kafka 的C/C++客户端,,在看他写的 example中,他的编译是用librdkafka++.a和librdkafka.a    静态库编译的,,,而我们这 ...

  4. ubuntu下 GCC编译程序出现 undefined reference to `std::ios_base::Init::Init()'问题

    网上的解释是:“ you need to add -lstdc++, or use 'g++' rather than 'gcc' as your driver program.”,也就是说如果想要使 ...

  5. 减小Gcc编译程序的体积

    众所周知,Gcc编译的原始程序一般很大,其实有几种方法能大大减小目标代码的体积,一般有以下几种方法. 基本知识来源:http://www.mingw.org/wiki/Large_executable ...

  6. MFC编译程序,缺少MFC动态链接库的解决

    MFC编译程序,缺少MFC动态链接库的解决 问题:VS2010 c++编写的程序在别人的机子运行不了,缺少mfc100u.dll xxx100d.dll等的解决方法 解决方法: 1.将这些dll打包, ...

  7. RHEL 7特性说明(七):编译程序及工具

    转载自:RedHat https://access.redhat.com/documentation/zh-CN/Red_Hat_Enterprise_Linux/7/html/7.0_Release ...

  8. windows下用vs2008和boost结合编译程序

      原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://co63oc.blog.51cto.com/904636/504469 win ...

  9. Delphi使用大图标编译程序

    在Windows Vista. Windows7以上Windows系统中可以支持大图标显示了,但是Delphi编译出来的程序却只能显示32x32的图标,这使Delphi编译的程序看起来很不专业.下面就 ...

  10. VS2012 编译程序时报无法载入PDB文件错误解决方式

    VS2012 编译程序时报无法载入PDB文件错误解决方式 "ConsoleApplication1.exe"(Win32): 已载入"C:\Users\hp\Docume ...

随机推荐

  1. net应用程序池自动关闭的解决方法

    while (true) { using (ServerManager sm = ServerManager.OpenRemote("localhost")) { string p ...

  2. Java类的加载和对象创建流程的详细分析

    相信我们在面试Java的时候总会有一些公司要做笔试题目的,而Java类的加载和对象创建流程的知识点也是常见的题目之一.接下来通过实例详细的分析一下: package com.test; public ...

  3. css3常用动效以及总结

    (迁移自旧博客2017 08 06) CSS3 文本效果: box-shadow:盒子阴影,可以给卡片添加提高美化效果.可广泛应用于内容展示页面. <div class="card&q ...

  4. VWmare设置挂载目录

     [root@localhost ~]# mkdir -p /mnt/cdrom  #首先创建一个挂载目录 [root@localhost ~]# mount -t auto /dev/cdrom / ...

  5. 用户端访问centos7上面的tomcat,访问页面出现的非常的慢?

    原因:因为客户端访问centos7上面的tomcat会先 建立session连接,这个连接会用到random的随机数,在linux系统中有一个熵池的概念(熵池是一个内核参数), 他要 用熵池里面的随机 ...

  6. react项目中实现元素的拖动和缩放实例

    在react项目中实现此功能可借助 react-rnd 库,文档地址:https://github.com/bokuweb/react-rnd#Screenshot .下面是实例运用: import ...

  7. 分页查询最好加排序(order by)

    昨天,与外部化系统对接时,发现有一个数据一直咩有集成到,双方各自排查了自己系统的代码,都觉得逻辑非常简单,无法就是一个分页查询而已. 问题就出在这个分页查询上. 为了说明当时问题发生的情景,我模拟了一 ...

  8. Cordova入门系列(一)创建项目

    Cordova是什么? 初学Cordova的人,虽然了解一点点,知道Cordova是用来将html, css, js变成app的,但并不知道到底是怎么用的,原理是什么.经常会有这样的困惑: 它是一个可 ...

  9. Disable access to Windows Update

    Disable access to Windows Update If this policy setting is enabled, all Windows Update features are ...

  10. webpack的安装及使用

     webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler).当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency g ...