Forth 编译程序
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;}
解释状态==执行状态 编译地址==执行地址
定义 [ 和 ] :
| : LIT ( - n ) 编译数字的运行时间代码 R@ @ 取出编译在词身内的数字 R> 2+ >R ; 调整IP 运行时 LIT 做两项工作: 1、它必须把跟着它的数字放到参数堆栈顶; 2、它必须移动解释指针 IP 越过这个数字而指向下一个编译地址。 |
: FIVE+ 5 + ;
|
| 开始执行 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 必须立即执行 |
冒号定义的开始和结束:
| : : ( - ) 定义一个高级定义,新定义完成之前被"隐藏"起来,冒号的执行代码给程序增添一层嵌套 !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 分号自身必须在编译状态下执行,所以必须是一个立即词。 |
数字文字常量:
| : ASCII ( - char ) 把输入流中下一个字符的ASCII代码编译为一个数字文字常量 BL WORD 取出下一个字符 1+ C@ 得到它的ASCII代码 STATE @ 获取当前系统状态(编译?解释) IF [COMPILE] LITERAL 编译状态就把其编为文字常数 THEN 否则留在参数堆栈上 ; IMMEDIATE |
|
| : ['] ( - ) ' [COMPILE] LITERAL ; IMMEDIATE |
['] 被定义成为一个立即型的定义,因此对于 ['] 定义内的 ' 来说,所谓的输入流中的下一个词就是冒号定义内跟在 ['] 后面的那个词。 |
| : 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 编译程序的更多相关文章
- delphi7 编译程序时报win32.indcu.a病毒的解决方法
Delphi7用了很久一直都没问题,同一个工程文件昨天编译时mod32还不会报毒,今天重新编译时,生成的exe突然nod32报毒. 提示: “Project1.exe Win32/Induc.A 病毒 ...
- 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 ...
- 在Linux下如何使用GCC编译程序、简单生成 静态库及动态库
最近在编写的一个Apache kafka 的C/C++客户端,,在看他写的 example中,他的编译是用librdkafka++.a和librdkafka.a 静态库编译的,,,而我们这 ...
- 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.”,也就是说如果想要使 ...
- 减小Gcc编译程序的体积
众所周知,Gcc编译的原始程序一般很大,其实有几种方法能大大减小目标代码的体积,一般有以下几种方法. 基本知识来源:http://www.mingw.org/wiki/Large_executable ...
- MFC编译程序,缺少MFC动态链接库的解决
MFC编译程序,缺少MFC动态链接库的解决 问题:VS2010 c++编写的程序在别人的机子运行不了,缺少mfc100u.dll xxx100d.dll等的解决方法 解决方法: 1.将这些dll打包, ...
- RHEL 7特性说明(七):编译程序及工具
转载自:RedHat https://access.redhat.com/documentation/zh-CN/Red_Hat_Enterprise_Linux/7/html/7.0_Release ...
- windows下用vs2008和boost结合编译程序
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://co63oc.blog.51cto.com/904636/504469 win ...
- Delphi使用大图标编译程序
在Windows Vista. Windows7以上Windows系统中可以支持大图标显示了,但是Delphi编译出来的程序却只能显示32x32的图标,这使Delphi编译的程序看起来很不专业.下面就 ...
- VS2012 编译程序时报无法载入PDB文件错误解决方式
VS2012 编译程序时报无法载入PDB文件错误解决方式 "ConsoleApplication1.exe"(Win32): 已载入"C:\Users\hp\Docume ...
随机推荐
- Java笔试
异常 Throwable是Java错误处理的父类,有两个子类:Error和Exception. Error:无法预期的严重错误,导致JVM虚拟机无法继续执行,几乎无法恢复捕捉的 Exception:可 ...
- BZOJ 5261 Rhyme
思路 考虑一个匹配的过程,当一个节点x向后拼接一个c的时候,为了满足题目条件的限制,应该向suflink中最深的len[x]+1>=k的节点转移(保证该后缀拼上一个c之后,长度为k的子串依然属于 ...
- Linux常用命令——网络命令
Linux常用命令——网络命令 Linux ifconfig 描述:查看设置网络IP 安装命令:yum -y install net-tools 语法:ifconfig 示例:ifconfig et ...
- 一键快速部署CodeBlocks的EGE图形库工具
大一下学期,学完了c语言的基本内容, 也就开始开发项目了,此时一个图形界面就比较重要了,c语言中不提供图形界面,一般这些是用的其它开发的图形库,如 Easyx .ege等. 本文就提供 Codeblo ...
- CentOS7攻克日记(四) —— 安装Mysql和Redis
这一篇主要安装mysql,redis等数据库 在这篇开始之前,有一个坑,上一篇更改python软连接的时候,尽量都用名字是python3来软连接/usr/../bin/python3.6,把名字是 ...
- 爬坑之路---Google map
google.maps.event.adddDomListen(window, 'load', callback);当文档流中所有的dom加载完成后,执行回调函数,可以不用在script中使用defe ...
- 理解R语言gdistance包下的transition函数
library(raster)library(gdistance)r <- raster(nrows=3, ncols=4, xmn=0, xmx=7, ymn=0, ymx=6, crs=&q ...
- Spark2.X管理与开发
==========第一篇:Scala编程语言========= 一.Scala语言基础 1.Scala语言简介 Scala是一种多范式的编程语言,其设计的初衷是要集成面向对象编程和函数式编程的各 ...
- Venom- Eminem
I got a song filled with shit for the strong willed. 我写了一首充满戾气的歌献给意志坚强的人. When the world give you a ...
- 雷林鹏分享:jQuery EasyUI 数据网格 - 创建列组合
jQuery EasyUI 数据网格 - 创建列组合 easyui 的数据网格(DataGrid)可以创建列组合,如下所示: 在本实例中,我们使用平面数据来填充数据网格(DataGrid)的数据,并把 ...