精华内容
下载资源
问答
  • 针对嵌入式应用领域对操作系统在重构、扩展、移植、交互、安全、高效等方面日趋苛刻的现实需求及Forth系统所固有的特性,采用Forth虚拟机技术,对基于Forth虚拟机架构的嵌入式操作系统关键技术进行探索,提出一种...
  • 面对越来越复杂的嵌入式应用需求,以及当今嵌入式操作系统研究领域中亟待解决的重构、移植、维护、可信、多核、众核等诸多难题,采用Forth虚拟机技术,对基于Forth虚拟机架构的嵌入式操作系统关键技术进行探索,提出...
  • FORTH 虚拟机内部结构

    2019-10-09 05:31:55
    body, table{font-family: 微软雅黑; font-size: 13.5pt} table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;} th{border: 1p...
    X86架构的 JLP_DOSX_Forth
    CS:段存放机器指令和与硬件有关的系统数据
    DS:段存放用户数据和虚拟机的堆栈等数系统据
    ES:段存放虚拟机指令和字典
    SS:存放系统堆栈和多任务系统数据表等
    虚拟机工作原理

    1.指令堆栈指针:      RP → BP
    2.算术堆栈指针:      AP → DI
    3.指令指针:         IP → SI
    4.字指针:           WP → BX
    5.字指令执行:(NEXT)
    WP := ES:[IP]       ; WP的内容是字的CFP
    IP := IP+2           ; 下一条指令的IP
    ES:[WP] JMP          ; 执行机器代码
    6.虚拟指令执行:(DOVM)
    RP   := RP-2        ; 指令堆栈进栈准备
    [RP] := IP          ; 当前IP进堆栈
    WP   := WP+2        ; WP的内容是新的指令地址
    IP   := WP          ; 新的IP
    (NEXT)
    7.虚拟指令返回:(ENDVM)
    IP :=  [RP]          ; 老IP出堆栈
    RP :=  RP+2          ; 指令堆栈恢复
    (NEXT)

    虚拟机程序状态字:PSW

                   
     

    Bit (位)

     
     

    名称

     
     

    内容

     
     

    定义

     
     

    0x0080

     
     

    WorkState  

     
     

    工作状态

     
     

    0:执行状态

     

    1:编译状态

     

     

    虚拟机器码属性字节:VCB

                           
     

    Bit (位)

     
     

    名称

     
     

    内容

     
     

    定义

     
     

    0x80

     
     

    ImmediateWord  

     
     

    立即字

     
     

    0:普通字

     

    1:立即执行字

     
     

    0x40

     
     

    FinishedWord

     
     

    完成字

     
     

    0:正常字

     

    1:未结束定义字



    转载于:https://www.cnblogs.com/meihao1203/p/10645003.html

    展开全文
  • 通过对虚拟机工作原理的分析,以自主构建的JLP FORTH虚拟平台为例,描述了虚拟机的实现原理、指令定义、存储方法和算法,并且在存储上提出以分段的方式分离代码和数据,通过该方法构建的FORTH虚拟机具有了更高的系统...
  • 针对现有的Forth自生成器都与目标环境密切关联、缺少抽象层次、难以在异构新平台上有效生成新的Forth系统等问题,通过采用抽象code算法库、描述异构目标,并重构Forth虚拟机的方法,构建完成了一个面向嵌入式环境、...
  • 通过对虚拟机工作原理的分析,以自主构建的JLP FORTH虚拟平台为例,描述了虚拟机的实现原理、指令定义、存储方法和核心算法,并且在存储上提出以分段的方式分离代码和数据,通过该方法构建的FORTH虚拟机具有了更高的...
  • 一台FORTH虚拟机和一个紧凑的垃圾收集器; 将s表达式编译为FORTH虚拟机字节码的编译器; 接受s表达式作为输入并直接执行代码的解释器; 一个将类似Algol的语句翻译为s表达的翻译器。 语言 资料类型 基本类型: ...
  • 通过对虚拟机工作原理的分析,以自主构建的JLP FORTH虚拟平台为例,描述了虚拟机的实现原理、指令定义、存储方法和核心算法,并且在存储上提出以分段的方式分离代码和数据,通过该方法构建的FORTH虚拟机具有了更高的...

    摘要:在嵌入式领域,如何降低系统与运行环境之间的相关性,在各种异构的嵌入式平台上快速构建系统一直是研究的重点。本文基于FORTH语言,通过对虚拟机工作原理的分析,以自主构建的JLP FORTH虚拟平台为例,描述了虚拟机的实现原理、指令定义、存储方法和核心算法,并且在存储上提出以分段的方式分离代码和数据,通过该方法构建的FORTH虚拟机具有了更高的系统安全性,并且调试方便、扩展性强,特别适合应用于嵌入式系统。

    1.引言

    虚拟机最初是美国计算机科学家波佩克(Popek)与戈德堡(Gerald)在虚拟化需求中给出了定义,专指有效的、孤立的真实计算机的副本,现在则指可像真实计算机一样运行程序的软件实现,包括跟任何真实计算机无关的虚拟机。根据运用和与机器的相关性可分为系统虚拟机和程序虚拟机,一个提供了完整的操作系统,另一个则以运行单个计算机程序为主。

    在嵌入式应用领域,嵌入式系统相关的CPU芯片和微计算机硬件系统种类繁多,并且不断推陈出新,甚至多核处理器已被普遍采用。但是在新平台上,难以针对每一种芯片或平台制定一种计算机语言来编程。解决的方法一是可采用公共计算机语言,用不同的编译器来生成机器码,但该方法需要具有该语言的编译器,在新平台上往往难以具备。另一种方法即建立一个虚拟机,然后用一个计算机语言,用一个解释器来解释执行。采用该方法,难点在于嵌入式虚拟机的构建,要能够适应多种环境、快速构建、可扩展。

    FORTH是一种与众不同的计算机程序设计语言。它具有极强的扩展性,通过字的定义,可实现不断堆叠和扩展。同时,它又具有极好的交互性,指令可解释执行,这就为应用的调试带来了极大的便捷。本文基于FORTH语言,以自主构建的JLPFORTH虚拟平台为例,详细阐述FORTH虚拟机的实现原理和核心实现方法,模拟和实现了通用的交互式计算机结构,实现了真实计算机的典型工作流程[4],并且一改过去FORTH代码和数据混合存储的方式,在内存的存储上以分段的方式将内存分为CS、VS、DS、SS四个段,分别存储指令和数据,这样,就实现了系统指令和用户数据的分离,有效地提高了代码和系统的安全性,并且调试方便、扩展性强,尤其适合应用于对安全性、兼容性、移植性、扩展性、交互性要求高的嵌入式系统领域。

    2.FORTH虚拟机实现原理

    真实计算机的基本工作原理是存储和控制。计算机在控制器的指挥下,取出预先存储的指令序列(即程序)和数据,通过控制器译码,按指令的要求,取出数据完成运算,再把结果重新存储起来,如此循环,直至完成全部指令。对真实计算机来说,这个过程依托中央处理器CPU来实现,CPU包括运算器、控制器和寄存器。如果描述CPU核心工作过程,主要包括以下步骤:

    (1)提取程序计数器值,该值指向的地址即指令地址;

    (2)从该地址取出指令;

    (3)程序计数器增加指令长度,即指向下一条指令地址;

    (4)解码执行指令;

    (5)返回结果。

    由于FORTH虚拟机是工作在真实计算机上的,因此要实现FORTH虚拟机必须用对应关系依托真实计算机的代码来实现这个核心过程。

    在FORTH虚拟机中,用核心算法--NEXT模拟了这个过程,将虚拟机指令和真实计算机指令实现对应,通过建立字典表,设置地址跳转,以串线码的方式将虚拟机命令字和直接机器指令实现对应,依托真实计算机指令完成了CPU的处理过程。如图1所示。

    6dae1751bb9e4235947f2c6dbfb4e163.png

    具体过程是:在FORTH定义字时创建链结构的字典表,在其中存储各个字的名称、长度、状态、指令码以及链接指针。例如定义FORTH字S:S DUP *;在字典表存放了各个FORTH高级字的名称和代码执行地址,其中也有S字的定义,在S字的代码场中存有S字的代码执行地址,该代码执行地址与code所描述的直接机器执行代码相对应,构成间接串线编码。当执行该指令时,首先查找字典表,找到S定义后,取出其WPF指令码中存放的地址,然后跳转到代码场该地址中,由于是FORTH高级字定义,所以首先执行“:”机器码将程序计数器所记录的下一条指令返回地址压入栈,然后跳转到参数场地址依序执行,直到最后的“;”返回指令执行后,再将原先存入栈的返回地址弹出,这样即完成一条指令的执行。其中,代码场和参数场分别存储指令和参数。以下以JLP FORTH虚拟机为例,详细描述其字典表、代码场、参数场的定义、虚拟机存储和指针的分配,以及核心算法。

    3.指令的定义和存储

    FORTH虚拟计算机采用该虚拟指令的存储地址来表示该指令,称为“地址码”.虚拟计算机的每个指令用名称(例如+、-、*)来表示,称为“字(Word)”.FORTH虚拟计算机的指令包括“复合字”和“基本字”.基本字也称为“低级字”,由真实计算机机器码和数据组成的,低级字组合可构成“复合字”,所以,“复合字”也称为“高级字”.

    高级字和低级字都可通过定义扩展。扩展高级字用“:”冒号定义,通过高级字定义用已有的指令形成新的指令。格式如下:

    :名字 … leave … ;其中执行leave指令可以跳出该FORTH字的执行,忽略掉其后的指令。扩展低级字则用机器码定义,格式如下:

    CODE 名字 … … NEXT, END-CODE其中NEXT,指令可以让计算机执行下一条虚拟机指令。

    对于真实计算机,用编译器生成的指令码序列中不需要保留指令名称。FORTH虚拟计算机不同,由于需要虚拟机执行和构造新的虚拟机指令,因此在虚拟计算机中要保留FORTH字的名称,用于存储FORTH字的存储空间就是“字典表”.在JLP FORTH虚拟平台中,字典表结构如表1,在图1中也有标注。

    c062bd34db99095f22fa88dec6d071be.png

    WPF里存储的指令码即FORTH字在存储空间的地址。由于允许FORTH字的名称长度不一样,因此采用链表结构可有效地存储它们,在LPF中即存放了下一个字的定义地址。

    代码场和参数场用于共同存储FORTH字,如表2.

    769d06fbbc928e33597f857fb33438ee.png

    其中CFA存放实现虚拟机功能的CPU机器码开始地址。PFA依次存放组成它的虚拟机指令。对于基本字PFA的内容不一样。对于一个常数基本字,PFA就直接存放这个常数。对于一个变量基本字,PFA就存放数据段中这个变量的地址[6].

    4.内存和指针分配

    以往FORTH并未将代码和数据分开,在嵌入式应用中,往往指令和程序相对固定,而代码和数据混合致使调试不方便,同时在系统安全上也带来问题。在JLP FORTH虚拟机上,将内存分为代码段CS、代码空间VS、数据段DS、系统段SS四个部分。

    (1)代码段CS:存放真实计算机的机器指令、内存分配信息以及与硬件有关的系统数据。

    (2)“代码”空间VS:用来存放虚拟计算机的指令和字典。

    (3)数据段DS:用来存放用户数据和虚拟机的堆栈等数据。

    (4)系统段SS:用来存放系统堆栈和多任务系统数据表等,达到分离系统任务和用户,保证系统安全的目的。

    采用这种存放方式,就可将CS和VS放在FLASH中,将DS和SS放在RAM,如此实现程序和数据的分离。这种新的虚拟机架构不仅可以适合嵌入式系统,也适合PC结构系统,而且更有利于内存保护的实现。

    真实计算机主要依靠寄存器来实现加减乘除等运算。例如将AX和BX寄存器的内容相加结果放到AX中,因此寄存器的数量是衡量CPU运算能力的一个指标。FORTH虚拟计算机则采用直接面向运算过程的方法,采用堆栈的方式来实现简单的运算,例如取出堆栈顶上的两个数相加后,结果放回堆栈顶。对于复杂运算,直接用复合字或者机器码写出面向数据的算法,比如对矢量和矩阵的运算等。由于没有寄存器的概念,只有表示系统工作状态的各种系统变量以及实现系统运行的各种指针。为了提高虚拟计算机的执行效率,用间接寻址的CPU寄存器来实现。对应关系如下(注:箭头为在X86计算机中对应的寄存器)。

    b80d7d8691616b3065a42e7c96c7a428.png

    通过这些指针的定义,FORTH虚拟机可实现各种各样复杂的算法。

    5。NEXT核心算法与函数

    FORTH虚拟机的核心算法--NEXT,它完成了指令的控制执行过程。如借用以上描述,用形式化的方法表示为:

    由于FORTH虚拟机是工作在真实计算机上,因此要实现FORTH虚拟机必须用真实计算机的代码来实现这个核心过程,以X86汇编语言为例,其实现FORTH虚拟机核心过程的代码为(16位地址空间):

    ES:BX,SI MOV

    SI,#2 ADD

    ES:[BX]JMP

    从代码可以看出,它非常象一个子过程或函数的调用。在真实计算机中,函数是非常常用的一个功能,是若干指令的有序集合。

    在FORTH虚拟计算机中高级字就可认为是“函数”.表3是真实计算机和FORTH虚拟计算机在函数调用中的执行过程对比。

    69b00677d6e40d84ca9ea876d95b80aa.png

    6.实例

    以下采用自下而上的编程方法,构造FORTH字P_DUMP用于查看内存基本信息,以此为例说明FORTH虚拟计算机相关程序的设计方法。参数有查看内存的段地址、偏移地址和区域长度。

    8015075fff78025d7f79e4f630c0c3b7.png

    85723e6bbac97ab5c59cff18df727fc1.png

    bd173afd59dec52a04c8775d411c6771.png

    7.结论

    对于嵌入式应用来说,一个可扩展性好、可移植性好、可裁剪、实现快速,并且便于调试的嵌入式虚拟机,能给嵌入式应用的开发带来极大的方便。基于FORTH构筑的虚拟机,引入字典表完成指令和机器代码的对应,并用字定义来完成指令的扩展,使系统的结构具有了极大的灵活性和扩展性,仅仅通过对基本字的堆叠、组合就可完成高级字的层层定义,实现极其复杂的系统。在JLP FORTH中存储分段使得程序指令和数据能相对独立,有效地增强了系统的安全性。这些设计思路使得在其上构建的FORTH虚拟机具有了代码简单、调试方便、安全性高、扩展性强等特点,特别适合应用于嵌入式系统中。(作者:王丽清,杨为民,代红兵,周永录)

    展开全文
  • 为ARM处理器实现Machine Forth

    千次阅读 2005-03-07 16:44:00
    为 ARM 处理器实现 Machine Forth 作者 Reuben Thomas Computer Laboratory, University of Cambridge 23rd August 1999 摘要 Fox 和 Moore[2] 最近提出了一种新的 Forth 虚拟机模型,称为 Machine Forth 。...

    为 ARM 处理器实现 Machine Forth

    作者 Reuben Thomas

    Computer Laboratory, University of Cambridge

    23rd August 1999

    摘要

    Fox 和 Moore[2] 最近提出了一种新的 Forth 虚拟机模型,称为 Machine Forth 。使用一个简单而具体的模型,据说它可以很容易地适应不同的硬件,不需要转向汇编器就可以产生效率很高的代码,它也努力成为一个优秀的 Forth 编译器的基础。本文讨论了一个 ARM 处理器实现 Forth 的方方方面,比较了一个基于 MF 的 Forth 系统和一个使用 ARM 机器模型实现的传统 Forth 系统。

    1 介绍

    1999 年 3 月,在 comp.lang.forth 有一个关于 Charles Moore 的 MachineForth 的讨论。这个虚拟机模型据说将用于他自己全部的 Forth 编程,并已经在如 F21 一类的几个硅片上实现了。

    Jeff Fox 是 Moore 的助手,他说 Moore 认为 MF VM 对于 Forth 的底层程序员来说比经典的 Forth VM 好得多,它允许离机器更近,同时维护一个相同的虚拟处理机而不管它下面是什么样的真实处理器。另外,设计的简单性就意味着为了实现这个系统,所需要的工具不会多于一个小的宏汇编器。

    由此而激发兴趣,我决定通过在 ARM 处理器上实现一个 Forth 来为我测试这个模型。我想看看像自动增量寻址一类的新指令是如何有利于程序设计的,而缺少 SWAP 和 ROT 一类的指令又是如何妨碍程序设计的,系统的实现有多么简单,在速度和代码密度方面与传统的 Forth 系统有什么差异。当然,我也关心为了适应 ARM 硬件, MF VM 模型需要有哪些改变。

    我关于 MF Forth 的测试包括用 MF 写一个 Forth 编译器,它含有 Moore 的最小要求。(另一个显而易见的实验是把我平时使用的系统 -- 一个扩展的 ANS 兼容系统 -- 移植到 MF 上)。然后,我重新用 ARM 代码编写一个编译器,以比较直接为 ARM 编写系统和用 MF 编写之间的差异。在这两个系统上、在传统的 Forth 以及 C 编译器上都运行了基准测试程序。

    以下的讨论假设读者熟悉 MF 模型以及 F21 的细节。从这里开始,“Machine Forth ”简写为“MF”,而我自己的版本,不好意思,就称为“MF32”吧。

    机器模型的改变

    由于我只有 F21 的规范作为 MF 的指导,我不知道 Moore 是否在传统的处理器上实现了 MF 。

    数据宽度

    由于 ARM 是32 位的体系结构,数据宽度变成 32 位。

    测试进位

    在 F21 处理器上,指令 C=0 对堆栈元素的一个扩展位进行测试。如果在传统的处理器上实现,这个指令将特别慢,所以把这个指令变成测试 T31 位,该位通常用来测试数值是否为负,这对于测试进位没有帮助,除非我们把寄存器视为 31 位长。不过对于 32 位精度乘法的需要通常比 20 寄存器要少。

    堆栈

    F21 处理器将它的堆栈放置在芯片上,所以它们是固定大小的;由于 ARM 没有硬件堆栈,它们可以是任何大小的。

    子程序调用和返回

    和通常的 RISC 处理器类似, ARM 并不自动地把子程序返回地址放到堆栈上,而是把它转移到一个寄存器中,这样就可以避免末端子程序进行存储器访问。由于将返回地址压栈总是很慢,并且每个调用都需要 8 个字节而不是 4 个字节,所以增加了一个新的寄存器 L ( LINK ) , 它像数据栈顶元素寄存器 T 一样缓冲返回栈顶元素。两个新的指令是 RET 和 :(冒号),用于实现末端子程序优化。当考虑 L 寄存器的时候,与返回栈相关的指令其语义只需要有很小的变化。

    字节寻址

    由于 ARM 是字节寻址的,P的增量必须是 4,增加关于字节的读取和存储指令看起来是明智的。

    乘法

    ARM 有硬件乘法指令,所以 +* 可以被 * 代替( +* 除了乘法之外,还有其它的用途,但是,当硬件能够提供乘法时,删除一个很少使用的指令看来是合理的)。

    NOP

    ARM 不需要 no-op 操作,所以删除了 NOP 指令。这在任何需要的时候都可以通过 PUSH POP 或者 DUP DROP 一类的短语进行模拟。

    OS 访问

    增加了一个 SWI 指令以允许 ARM 的 SWI (软件中断指令)实现对操作系统的访问。

    2 修订的 VM 模型

    数据元素

    栈 : 数据栈 S, 返回栈 R

    寄存器 : T 、 L 、 A 、 P

    2.2 执行循环

    执行在 P 处的指令,如果指令没有修改 P 则 P = P + 4 ,重复

    2.3 指令集

    表 1 给出了指令集和它的语义。第一列给出了指令的名字,第二列是立即操作数的数目。它们被称为 V1 、V2 、…… 第三列给出了语义。使用如下的简化表示:“PUSH X TO T”意味着 “压 T 到堆栈 S ,将 X 的值置入 T”, “POP T TO X ”意味着“计算 X ,将 X 的值存入T ,从 S 中弹出 T”。

    指令 操作数 Operation

    # 1 push V to T

    else 1 jump to V

    T=0 1 jump to V if T = 0

    C=0 1 jump to V if T31 = 0

    call 1 set L to P_ 4, jump to V

    ret 0 set P to L

    : 0 push L to R

    ; 0 pop P from R

    A@ 0 push A to T

    A! 0 pop T to A

    @A 0 push [A] to T

    !A 0 pop T to [A]

    B@A 0 push [A]0-7 to T

    B!A 0 pop T0-7 to [A]0-7

    @A+ 0 push [A] to T, add 4 to A

    !A+ 0 pop T to [A], add 4 to A

    B@A+ 0 push [A]0-7 to T, add 1 to A

    B!A+ 0 pop T0-7 to [A]0-7, add 1 to A

    pop 0 push L to T, pop R to L

    push 0 push L to R, pop T to L

    @R+ 0 push [L] to T, add 4 to L

    !R+ 0 pop T to [L], add 4 to L

    B@R+ 0 push [L]0-7 to T, add 1 to L

    B!R+ 0 pop T0-7 to [L]0-7, add 1 to L

    com 0 one's complement T

    2* 0 shift T one place left

    2/ 0 shift T arithmetically one place right

    * 0 set T to [S] = T, pop S

    -or 0 set T to exclusive-or of [S] and T, pop S

    and 0 set T to and of [S] and T, pop S

    + 0 set T to [S]_ T, pop S

    dup 0 push T to T

    over 0 push S to T

    drop 0 pop T from S

    swi 3 pop V2 arguments from T into ARM registers R0 to RV2-1,

    call SWI V1, push V3 results from ARM registers R0 to RV3-1 to T

    表 1 MF32 指令集

    3 汇编器

    正如所承诺的那样,写汇编器很容易。我增加了常用的汇编控制结构以实现 IF …… THEN 条件和 BEGIN …… REPEAT/AGAIN/UNTIL 循环,增加了MF基于 -IF 的变体。

    在完成了编译器之后,我为汇编器增加了一个简单的窥孔优化以删除PUSH-POP 对;这可能比其它的汇编器需要更多的时间才能工作,但是代码却变短了。

    4 编译器

    编译器为最小的解释环境提供了足够的工具:一个解释器/编译器、数值输入和输出、具有创建一个新定义的字典能力。

    5 Machine Forth 的困难

    起步

    正如预先看到的那样,由于不熟悉堆栈和算术操作符,代码很难编写,我发现很难记住 A@/A! 和 @A/!A 都是干什么的,我偶尔通过把后者作为 @A+/!A+ 才成功地记住了它们。

    随着时间的推移,我开始发现一些普遍的习惯用法,比如使用 A 和 R 堆栈来改变元素的序列,有时使用 R 来存储循环计数和终值, DUP BEGIN DROP 去除条件循环的标志(因为 MF 的 IF 和 -IF 指令不弹出 T )。

    考虑可移植性

    不管从 MF 中得到了什么感觉,我发现在考虑如何最好地实现一个字时,如果不去比较不同的 MF 指令序列与 ARM 翻译之间的差异是非常困难的。例如,在我的 MF32 实现中,为了在堆栈顶得到常数 0 ,使用 0 常数定义的方法是最快的。在 F21 中,使用 DUP DUP - 可能是最好的。这看起来似乎与 MF 的可移植性相矛盾,尽管在不同的体系结构中使用不同的代码序列可以得到相同的结果。然而,这个问题在任何的可移植语言中都会出现,不过在 MF 这种简单的结构中更加明显罢了。

    指令 CACHE 同步

    有一个问题是任何的 StrongARM 动态代码生成器所必须解决的,这就是它的指令 CACHE 不能与数据 CACHE 自动同步,一个简单和安全的解决方法就是增加一个字 CODE!, 它在地址存入时同步,构造并使用它存入字典(在 MF32 中还有另外一个字就是 THEN )。

    增加原语

    我发现我需要几个 MF 没有提供的功能。我增加了 negate 、 minus 、 or 、 lshift 和 rshift 。我采用的笨拙的规则是:如果一个字用 ARM 指令来写可以比用 MF32 来写少几个指令,我就用 ARM 编码。

    事实上,所有以上提及的都是作为内嵌原语实现的,好像它们是 MF32 汇编器的一部分。

    其它用汇编编码的字

    有几个写给 comp.lang.forth 的邮件对省略 SWAP 进行了冗长的讨论。我没有参与这种讨论,而是在我的系统中增加了 SWAP ,不过它只用了 4 次;其它时候通过一个局部交换,在 A 或者在返回栈中结束,将更加有效。其它的附加原语也很少使用,一般使用 2 - 3 次,唯一的一个例外是 OR ,它使用了 8 次。

    EXECUTE 、 MIN 和依赖 OS 的 EMIT 、 SPACE 、 CR 和 BYE 也是用 ARM 汇编写成的。对于 EXECUTE 需要特别说明 : 在 F21 处理器中它是简单的 push ret, 但在 MF32 中却比较困难,尽管可以做。你可以进行一个练习,但在看第 9 部分的答案之前,先思考一下。

    缺乏堆栈捣弄

    MF 缺乏捣弄堆栈的字,这就给一般的 Forth 程序员增加了压力,要求他们避免捣弄堆栈,并且更加强烈地要求进行因子分解。初看起来这是一个紧箍咒,但我发现只有 1 、 2 个字由于缺少 PICK 和 ROLL ( NUMBER 特别狡猾)而变得难于编写。尽管如此,我仍然不习惯于 MF 。

    除法

    对于数值的输入和输出来说,除法是必须的。 MF 和 ARM 都没有除法指令,所以我使用除法子程序。

    读写堆栈指针

    一个严重的缺憾是 MF 不能够读写堆栈指针:它对于在 QUIT 中实现 DEPTH 复位堆栈非常重要。而在 F21 处理器中,由于堆栈是用硬件实现的,所以不太重要,但对于软件来说,这就非常不同了,因为这可以防止存储器泄漏。我避免这个问题的方法是:让 QUIT 简单地分支到初始化代码,重新设置堆栈指针。

    6 ARM Forth

    在结束了 ARM 的 MF32 之后,我用 ARM 代码编写了编译器。这听起来像 Moore 所谓的“硬件 Forth”, 但有一个不同:当 CMForth 编译器的硬件结构由一个机器指定时(在这种情况下, 是NOVIX Forth 芯片), ARM 的 Machine Forth 是严格地与 Machine Forth 一致的,仅仅是使用 ARM 机器模型而不再是 MF 模型。

    代码不仅更小,至少更容易编写(实际上,许多字第一次工作,它们不是 MF32 版本的本地码翻译,而是完全重写以便能够利用 ARM 的优点)。 ARM 小而且规则的指令集在代码尺寸上完全可以与 Machine Forth (它含有大约 20 条基本指令)相比,但它有更丰富的算术和逻辑操作、寻址模式和 Machine Forth 没有的特性,比如条件执行。

    另一方面,由于 ARM 是基于寄存器的机器,这就导致两个编译器:有些字在交互环境中非常有用,比如 DUP 和 + , 但是在编译代码中却很少使用,在编译代码中,需要开发寄存器的寻址能力。

    7 MF32 和 ARM Forth 的比较

    尺寸

    表 2 给出了 MF32 和 ARM Forth 系统的一些比较。表中指出代码密度是每个 MF32 指令为 1.5 ARM 指令或者说是 6 个字节。

    表 2: MF32 和 ARM Forth 的比较

    窥孔优化节省了大约 100 条指令,相当于全部生成代码的 9%。

    但是我们同时也看到, ARM Forth 比 MF32 多 66 条指令,因为 ARM 芯片的汇编器比 Machine Forth 汇编器更复杂,二进制代码小了 32 单元,包含 326 个更小的代码。此外,许多在两个系统中都有的指令,用 ARM 指令比用 MF32 指令要小。似乎 ARM 的代码密度是 MF32 的两倍。

    速度

    我们把两个基准程序分别在 MF32 系统、 ARM Forth 系统、一个本地码子程序串线 ANSI Forth 编译器( aForth 0.75, 可以从 http://sc3d.org/rrt/ 得到)和 GNU C 上运行。第一个代码是一个简单的随机数发生器,如图 1 所示(考虑篇幅的原因我们略去了 C 代码,它是一个 ANS Forth 版本的文字翻译,可以在 Machine Forth 发布中得到)。

    表 3: 随机数基准测试

    表 4 : 素数基准测试

    第一次测试运行了 10,000,000 次循环 , 第二次是一个简单的素数查找器,查找到了 10000 素数(最好是运行一些著名的基准测试,比如 Ertl 的整数测试集,但是没有足够的时间把它们翻译成 Machine Forth 和 ARM Forth )。

    ARM Forth 是最小和最快和版本,但是令人惊奇的是 ANSI Forth 代码也比 MF32 版本更小而且更快(素数基准测试花费了大约 60%的时间用于执行软件除法子程序,所以这是不重要的,尽管在随机数基准测试中也表现了同样的倾向)。

    在本文的一个早期版本中,我曾经愚蠢地写下了“MF32 的速度将明显地位于子程序串线和本地码编译器之间”。尽管通过几个基准测试就否定这一结论同样是愚蠢的,但是 MF 说明的速度和代码密度需要进一步考察,至少在典型的桌面体系结构中应该如此(在 INTEL 的实现中,也发现了类似的代码密度见 comp.lang.forth )。

    图 1 随机数基准测试程序

    编程的舒适性

    ANSI Forth 和 MF32 在编程的舒适性上是相同的。与具有编写编译程序的经验相反, ARM Forth 比较困难。 ARM 代码也比 Forth 更长更难读,实际上, ARM Forth 更难因子化,因为在 ARM Forth 中,返回标志的定义将要自然地修改 ARM 寄存器而不是在栈顶返回一个标志值,但这在当前是不可能的,因为标志阻止了跨子程序的调用。也许这一点是需要改变的。

    然而,这样比较 Machine Forth 和 ARM 代码是不公平的,因为前者是为 MF 而设计的,后者却不是。使用一个更自然的编码风格, ARM 汇编将和 Machine Forth 一样容易写,并且如果从一个传统的 Forth 编译器内部来使用它,它也是可以交互式测试的。

    8. 结论

    本文只是一个很少经验的总结,通过写一个编译器来得到关于 Forth 编程的结论总是不明智的。很明显, MF 容易实现,但那只是从机器模型的角度来观察而得到的结论。对于我来说, Machine Forth 落入了两难的选择:对于高级代码,我更愿意编写完全标准的 Forth ,对于低级代码,我更愿意有强大的,高速的、紧缩的汇编器(当然是在一个 Forth 编译器中使用)。

    这个印象也许来自我已经广泛编程的处理器(6502、MC68000 和 ARM )都有小的和简单的指令集。对于一个不熟悉的处理器,特别是对于那些大的和复杂的指令集的处理器,与学习本地汇编语言相比, MF 的简单性也许可以帮助我们更快地产生合理的代码。

    MF 的可移植性也可以作为它的特点被提及,不过那只是编写高级代码时的一个优点;当 MF 作为汇编语言的替代时,编码就无论如何也是机器相关的,这里谈论可移植性就没有任何意义了。

    然而, MF 也的确提供了一些有益的思想。对于那些不能提供优化器的小 Forth 编译器,显式地使用地址锁存器就是提高性能的最简单方法。更有趣的是它非破坏性的条件测试可以很容易地用于传统的 Forth 中。

    所以, MF 的新颖性和传统简单性的混合进行仔细研究并混合是有益的,尽管我不会因为这些就放弃了 Forth 和汇编器的传统组合。

    9 练习的答案

    EXECUTE 可以这样地用 MF32 写出

    A! pop A@ push push ;

    10 感谢

    Jeff Fox was kind enough to read and comment on the paper, a referee made several helpful comments, Hanno Schwalm pointed out the weakness of the primes benchmark, and Marcel Hendrix asked for the comparison with C.

    References

    [1] M. Anton Ertl. Performance of Forth systems, 1996. http://www.complang.

    tuwien.ac.at/forth/performance.html.

    [2] Charles Moore and Jeff Fox. Preliminary specification of the F21, 1995. http:

    //pisa.rockefeller.edu:8080/MISC/F21.specs.

    [3] VLSI Technology Inc., Eaglewood Cliffs, NJ. Acorn RISC Machine family Data Manual,

    1990.

    展开全文
  • CVM-Forth-开源

    2021-05-15 01:33:05
    Forth编译的虚拟机编译器
  • Forth 语言概要 - Forth: An underview 原作者 Peter Knaggs 原文标题《 Forth: An underview 》 译者: 未知 译文链接: http://blog.csdn.net/wxj729/article/details/313678 原文链接: ...

    Forth 语言概要 - Forth: An underview

    • 原作者 Peter Knaggs
    • 原文标题《 Forth: An underview 》
    • 译者: 未知
    • 译文链接: http://blog.csdn.net/wxj729/article/details/313678
    • 原文链接: http://www.softpanorama.org/Lang/Forth.shtml

    说明: 原文的这个官方链接已经失效, 所以费了点劲才找到上面的那个.

    本文的目的是给出 Forth 编程系统的一个整体轮廓,包括语言的历史、突出的特点和使用方法,讨论了最常用的实现方法,但更重要的是讨论了 Forth 编程的方法和哲学思想。

    1.Forth 的来历

    按照 Forth 语言的发明人 Charles MooreChuck )的说法:

    我第一次把各种想法组合成一个整体之后,它在“第三代计算机” IBM1130 上工作得如此有效,以致于我认为它是“第四代语言”,理所当然地应该被称为 FOURTH 。不过,当时的 IBM 计算机只允许 5 个字符的标识符。所以 FOURTH 变成了 Forth ,这是一个非常好的的文字游戏。

    2. 历史

    Forth 语言是 60 年代发明的,当时 Moore 在斯坦福线性加速器中心做计算机程序员工作,后来变成了一个自由工程师。当时的工程技术人员为了控制编译程序必须学习大量的方法,包括连接器、汇编器、伪指令以及高级语言,开发这个新工具的目标就是为了克服这些问题。

    第一个称为 Forth 的程序大约是在 1970 年编写的。第一个完整的实现是 1971 年在一台 PDP-11 上完成的,用于亚利桑那州国家射电天文台的 11 米射电望远镜。这个系统的责任是定向和跟踪望远镜,收集数据并记录到磁带上,支持一个交互式的图形终端,供天文学家分析以前记录的数据。系统的多任务特点允许这些功能同时执行,没有时间上和其它方面的冲突。

    这个系统取得了巨大的成功,世界各地的天文学家开始请求提供软件拷贝。Forth的使用范围迅速也扩大,国际天文学会于 1976 年接受了 Forth 作为标准语言。

    这个应用的成功还促使 MooreElizabeth Rather ( ("Bess") 于 1973 年成立了 Forth, Inc. 公司,目标是开发这种语言的商业应用。 Forth, Inc. 在小型机上开发了多用户的 Forth 版本,可以用于从数据库到图像处理等科学和应用领域。和第一个应用一样,它们需要不同工具的组合。

    1977 年,公司为刚刚出现的 8 位处理器开发了一个称为“microForth”的版本,对小型机上的“miniForth”做了扩展和补充。1979 年,称为“PolyForth”的产品替代了这些系统。从此以后,它就成了市场上销售量最大的 Forth 系统。

    microForth”系统在美国、欧洲和日本的嵌入式微处理器应用中取得了成功,由此产生了欧洲 Forth 用户团体 (EFUG) ;1978年,位于北加利佛尼亚的计算机爱好者成立了 Forth 兴趣组织 (FIG).
    FIG 从天文台得到 Forth 系统,再用这个系统开发出一个简单的模型,然后在几个不同的系统上实现(那当然是得到了 Forth,Inc 的许可之后)并以非常低的价格销售。这个模型后来变成了著名的 FIG-Forth 模型。所有这些使得对 Forth 的兴趣迅速增大。 FIG 目前在 15 个国家中有 60 个分支。

    3. 特点

    Forth 是一个交互式的程序设计环境,最初是为程序员在小型和微型计算机上开发应用程序而设计的。最早用于科学和工业应用,比如仪器、机器人、过程控制、图形和图像处理、人工智能和商业应用。 Forth 的主要优点是软件开发快速、交互式、计算机硬件的高效使用等。

    Forth 常常被作为一种语言,这当然也是它最常见的方面,然而 Forth 所提供的功能比传统的程序设计语言要多。传统的高级语言工具包含有许多分离的工具(编译器、编辑器、汇编器等等), Forth 把它们融为一体。与传统的高级语言相比,它是经过深思熟虑的,完全没有传统高级语言那么复杂的语法特性。

    最早实现的 Forth 是一个独立的系统,它包含独立操作系统的一般功能,还包括有编辑器、编译器、汇编器、调试器和其它工具。一个单一的、简单的、一致的规则支配这些能力。今天,尽管还能在许多处理器上见到独立的版本,但更多的版本是与 MSDOSWINDOWSUNIX 一类操作系统协同工作的。

    Forth 并不起源于其它已有的程序设计语言,所以它的外观和内部特点对于新用户来说是特殊的。但是 Forth 的简单性、高度模块化和交互式特性可以弥补初学者的陌生感,使得 Forth 非常易于学习和使用。一个新的程序员通常需要花一些时间来掌握 Forth 巨大的命令集,通过一个月左右的全面使用,程序员就可以理解它的整个内部工作机理,所学到的东西要比传统操作系统和编译器多得多。

    Forth 与传统语言最大的不同是它的可扩展性。 Forth 的编程过程就是定义新的字,字实际上就是语言的新命令。字可以用一系列以前定义的字来定义,这个过程与教育孩子的过程相似:我们总是用孩子们以前理解的概念来教给孩子们新的概念,而这些字被称为“高级定义”。同样,新的字也可以用汇编代码定义,因为在多数 Forth 实现中都包括宿主处理器的汇编器,而这些字被称为 CODE 字。

    可扩展性的结果是我们在开发一个应用的同时,也间接地开发了一个特殊的、针对这一类应用的“面向应用的语言”,它可以用于或者经过修改之后被用于相似的应用。

    Forth 的可扩展性并不仅仅是为语言自身增加新的命令,所以不要把定义字与传统高级语言定义函数、过程等同。可扩展性还能够创建一个可以定义其它字的字,这种字被称为“定义字”。在创建这样一个定义字的时候,程序员能够指定它所创建的字在编译时间、运行时间或者这两种状态下的特殊行为。这个能力允许我们定义特殊的数据类型,并对其行为和结构实施完全的控制。又由于这种字的运行时间行为可以用高级语言或者汇编语言来定义,所以由定义字创建的字将具有与其它 Forth 字一样的性能。系统也允许我们增加一个新的“编译指示符”以实现特殊类型的循环或者其它的控制结构,比如 CASE 结构。

    4. 编程

    Forth 语言和英语非常相似,它的基本元素是已命名的数据项、过程,以及创建用户化数据项的定义字的能力。过程和定义字可以使用以前定义的字或者汇编代码来定义,它们与其它语言的子程序相似,也与其它语言的命令等效。 Forth 允许我们在键盘上打入一个函数的名字,这个函数将被立即执行。然而,如果我们把功能的名字放到定义中,将编译成对于这个函数的引用。

    高级字是由其它字的集合来定义的,我们可以把这个过程想象成是其它语言的宏或者词典中的英语定义。新的字被加入到它们可以使用的存储器中,其定义被加入到字典中。在一个 Forth 字的命名规则中,只有很少的几个字符不能作为命名字符使用。许多程序组织使用更好的命名约定,通过可打印的字符以增加程序的可读性。

    当遇到一个字的时候, Forth 就通过字典搜索希望找到这个字的定义,如果找到,这个字定义的功能或者被立即执行,或者作为引用而被编译到新的定义中。然而,如果在字典中没有找到这个字,系统就试着把它转换成一个数。如果转换成功,就把它放在堆栈上。如果不能转换成数字,就显示这个字并打印出一个错误的信息来报告这个字是系统所不知道的。

    Forth 坚持“结构化程序设计”原理:

    • 字必须在引用之前被定义;
    • 逻辑流限制只有顺序、条件和循环,有专门的字用于实现常用的程序控制结构;
    • 程序员使用许多小的、独立的模块(字)来实现最大的可测试性和可靠性;

    这种方法有两个明显的优点:

    • 新的字总是用以前定义和测试过的字来构造,所以调试更容易。模块可以单独执行以测试它的功能;
    • 固有的模块性使 Forth 成为一个“设计性语言”,允许自顶向下的设计同时保持自底向上的测试。一个字可以在不同的程序中使用,但是它的功能只需要定义一次;

    这些都保证了 Forth 软件能够快速和有效地被开发,同时,如果管理得当,也可以作为自身文档的基础。

    Forth 的 5 个主要元素决定了它的特点:

    • 一个字典;
    • 两个堆栈,一个是参数栈,另一个是用于嵌套的返回栈;
    • 键盘(输入流)解释器;
    • 一个汇编器;
    • 虚拟存储;

    用 Forth 开发的项目

    以下是一些使用 Forth 开发的项目

    Atari 的许多投币游戏机都是用 Forth 开发的。他们相信开发高性能代码的最快方法是使用 Forth ,加上使用汇编语言来重写最内层的循环。

    按照最近与著名的 Infocom 高级游戏开发者的谈话,他们的游戏解释器也是用 Forth 写成的。

    Unison WorldCP/M 操作系统开发了许多游戏,全部都是用 FIG-Forth 编写的。按他们技术总监 Marc de Groot 的说法,把一个基于 Z80 的游戏移植到 6502 或者 MC6809 上,典型的时间不多于 3 个月。

    美国 Federal Express (联邦快递)公司的手持式行李分捡系统的程序是用 Forth 编写的。项目经理 Gene Farrar 说,他可以按需要在几个星期内升级新固件,相比而言,其它的小组维护 C 语言代码则至少需要 6 个月的时间。

    1990 年 11 月哥伦比亚航天飞机的 4 个载荷中有 3 个是用 Forth 编程的。按设计团队之一 Johns Hopkins University's Applied Physics LaboratoryJohn Hayes 说法,他们选择 Forth 来解决飞行中的硬件问题,灵活性是一个主要的因素。

    SUN 公司把 Forth 用于它的工作站可编程 Boot ROM 中,以每天 500-1000 台的速度发货,是可编程 Forth 系统中数量最大的。 1994IEEE 1275-1994Forth 用于 BOOT (初始配置) 固件的标准,这也是 POWER PC 通用硬件平台的基础。

    在电影《终结者 II :世界末日》中, Cyberdyne Systems T1000 系统的特技效果是基于 Morphing 软件包 Forth 产生的。

    5. 字典

    Forth 程序存储在字典中。字典占据了系统存储器的很大部分,它由一个串线链接的可变长度的项目组成,每个项目定义了一个字。每个定义的内容根据字的类型(数据项、常数、操作序列等)而有所不同,字典是可扩展的。

    字是由“定义字”加入字典的,最常用的定义字是 :(冒号)。当冒号执行的时候,它为后面的字建立一个字典项,然后进入“编译”模式。有许多不同的编译方法,最常用的是“串线编码”,这种方法把定义编译成一系列以前定义字的地址引用。定义由 ;(分号)结束。下面就是一个定义:

    : NETWORK ( -- ) OPEN LINK TRXT. ECHO CLOSE LINK ;

    995377-20170223155415757-1431092021.gif

    • 图 1 编译的字典项

    当一个名字项被编译到字典中的时候(称为定义的首部),它包含一个指向字典中前一个首部的指针。新字的名字加入字典(这里就是 NETWORK ),接着一个指向名字为“(:)”子程序调用的指针编译到字典中作为定义的第一部分,这个指针指向一段在解释定义体时需要执行的代码。当然,这里所说的不是唯一的编译技术,但它的应用最为普遍,这种技术称为间接串线编码,因为定义中的第一个项目是一段代码的引用,这段代码知道如何解释定义的其它部分。

    定义的其它部分称为这个定义的体。在编译模式下,系统将依次寻找每个字的首部。每个首部地址依次放到定义体中,这样就产生了一个地址列表。最后在到达 ; 时,一个称为“EXIT”的子程序地址被编译进定义。 EXIT 子程序用来将控制返回到调用字,就像一个子程序返回一样。

    6. 堆栈

    Forth 维护两个下推式堆栈,下推式堆栈也称为后进先出列表,它们提供了 Forth 字之间通信以及逻辑控制的有效机制。

    尽管两个堆栈的结构是相同的,但它们的用途却大不相同。与用户/程序员关系最为密切的是数据栈,它保存有调用字之间传递的参数,以替代传统语言的参数列表,同时也是一个实现定义重用的有效内部机制。第二个堆栈是返回栈,用于保存嵌套定义的返回地址,偶尔也用于临时保存其它的数据。

    数据栈的使用导致了一种操作数位于操作符后面的“后缀”表示方法,这种后缀表示方法常常被称为 RPN 或者“逆波兰表示法”,用以纪念 Lukasiewicz 教授,上个世纪 20 年代时, Lukasiewicz 教授在华沙大学工作,为 Sentential Calculus 开发了这种方法。

    作为一个例子,我们来看一下字 BLANK 。这个字希望堆栈上有一个地址和一个数,字 BLANK 将从指定地址开始填充指定数目的 ASCII 空格,于是:

    PAD 25 BLANK

    将向 Forth 系统的便笺区填入25个空格,这里地址是由字 PAD 放到堆栈上的。应用字通常按相似的方法定义,比如:

    100 SAMPLES

    将定义一个用于保存 100 个测量值的数据数组。算术操作也从堆栈上取值并将结果保存到堆栈上。例如, + 操作把栈顶的两个数相加,并用它们的和替代栈顶。由于操作的结果仍然留在栈顶,所以连续的操作就可以组合在一起而不需要临时存储变量。例如,表达式

    tempn + ((reading % interval) / interval) * (tempn1 - tempn)

    变成:

    reading interval % interval / tempn1 tempn - * tempn +

    7. 解释器

    Forth 本质上是一个解释系统,在这样的系统中,程序的执行是由数据项而不是由机器代码控制的。解释系统通常很慢,但是 Forth 却通过两级解释而保持了实时应用所需要的高速度。当然,我们这样说是假设系统使用普通的串线编码方法,如果使用编译技术来产生本地代码,就根本不会有任何速度上的损失了。

    • 第一个解释器是文本解释器,它扫描从终端(或者从海量存储器)得到的字符串,并在字典中查找每一个字。如果找到了这个字,就通过第二级地址解释器执行。

    • 第二级解释器是“地址解释器”。尽管不是所有的系统都用这种方法实现,但这种方法却是最早的和最基本的方法,地址解释器通过执行每个定义点的程序来处理地址(或者标记)串,这些定义点是由 : (冒号)创建并编译到定义中的。

    7.1 文本解释器

    上电之后。 Forth 启动一个称为 QUIT 的无限循环。这就是 Forth 文本解释器,也称为键盘解释器。

    : QUIT ( -- ) BEGIN RESET QUERY INTERPRET AGAIN ;
    • RESET 清除堆栈,
    • QUERY 等待用户从键盘(或者从海量存储设备)输入一个命令,
    • INTERPRET 寻找字典匹配,然后执行。
    • BEGINAGAIN 是程序控制字,用于构造无限循环。
    • QUIT 循环提供了语言的“交互式”特点,如果输入命令,它就可以立即被执行,而执行的结果可以使用相同的文本解释器来观察。

    与其它的编辑 - 编译 - 链接 - 测试程序开发过程相比,一个新的定义可以在极短的时间里被反复地测试和排错。

    7.2 地址解释器

    定义项首部的最后一个字段是指向功能执行的代码指针,这个字段所在的地址被称为“代码域地址”,简称 CFA 。对于所有的 Forth 高级定义字(使用 : 冒号定义的字),这个地址就是地址解释器的地址,它指向字 (:)

    地址解释器有一个寄存器 I ,其中包含被执行列表的下一个入口的地址。这个入口就是某个字的 CFA 地址,这个字被当前正在执行的高级定义字所调用。正是 CFA 决定了一个字的属性(或者类型)。

    在下面的例子中,字 A 调用字 B ,字 B 调用字 X 等等。 CFA 保存在中间寄存器 W 中。采用这种两级间接寻址和字典列表结构的 Forth 编码方式也被称为“间接串线编码”。

    995377-20170223155441882-1731146381.gif

    • 图 2 间接串线编码

    地址解释器读入 I 并使用列表中的下一个地址装入 W ,然后从 W 读出并执行由它指示的代码。 I 自动增量指向列表中的下一个入口,因为第一个入口是 CFA ,所以 I 现在指向了定义体。这对于查找表一类的数据结构非常有用,因为定义体就是表元素的存储区。

    在高级定义的情况下,代码域地址指向子程序 (:) ,它把当前的 I 保存到返回栈上,然后从 W 装入 I 并重复这一过程。

    在高级定义的结尾,字 EXIT 被执行,恢复原来的 I 值,程序像以前一样继续执行。这三个动作: “读 I 指针保存 I 指针恢复 I 指针”是地址解释器得以工作的基本机制。

    地址解释器有三个重要的特点:

    • 特别快。尽管实际的速度依赖于特定的实现,但专业化的实现是高度优化的,每个地址通常要求 1-2 个机器字。这相比纯的汇编代码只增加0%-50% 的开销。在许多基准程序测试中,好的 Forth 实现远远胜过诸如 BASIC 或者 LISP 一类的解释语言,可以与其它的编译高级语言相比;

    • 它使得 Forth 定义极其紧缩,每一个引用仅仅需要一个单元(可以把单元理解成机器字,但是“字”在 Forth 中是指一个定义项)。作为比较,我们可以考虑一下许多高级语言产生的子程序调用结构:一个 CALL 或者 JSR 指令,后随地址,在这之前和之后,还有参数序列的访问指令。

    • 使用返回栈保存地址的方法对于程序员是透明的,字也可以按需要嵌套许多层,这样的高级定义字序列可以被自动处理而不需要特殊的代码。

    Forth 系统中的许多字都是用 : 定义并通过地址解释器进行解释的,而许多 Forth 系统本身也是用这种方法定义的。

    8. 汇编器

    大多数 Forth 系统都包含一个宏汇编器,为它们所在的 CPU 进行汇编语言编程。通过使用定义字 CODE ,程序员可以创建由实际的机器代码组成的定义。 CODE 定义可以用来完成 I/O 、算术原语和其它依赖机器(时间紧迫)的处理功能。当程序员使用 CODE 时,他就和使用其它汇编器一样对 CPU 有完全的控制能力, CODE 定义的字以机器速度全速运行。

    这是 Forth 的一个重要特点。它允许那些明显地依赖机器的代码通过机器无关接口变换成为可管理的片断。当需要把应用移植到不同的处理器上时,我们仅仅需要重新编写 CODE 字,这些 CODE 字就可以严格地按相同的方法与其它 Forth 字进行交互。

    Forth 汇编器本身也是极其紧缩的(典型地为 1K 字节),它们可以和编译器、编辑器以及其它编程工具一起驻留在系统中。这就意味着程序员可以打入很短的 CODE 定义,然后立即执行它们,这个能力在调试客户硬件时特别有用。

    9. 虚拟存储

    Forth 最后一个独特的组成元素是它按数据和源程序虚拟存储器的方式使用磁盘(或者其它海量存储器)。在地址解释器的情况下,这种方法在历史上是典型的 Forth 方式,但现在并不通用。

    磁盘被分成 1024 字节大小的块,在内存中则准备两个或者多个缓冲区,数据在引用时被自动读入缓冲区。每个块有固定的块号,直接对应于本地存储系统的物理位置。任何时候程序需要访问时,它都会在内存中找到数据,并不需要显式的读写操作。

    这样一个面向块的磁盘管理方法对于 Forth 独立系统的实现是简单和高效的,结果是块为独立和协同驻留 Forth 实现中的源程序和数据处理提供了一个完全透明的机制。

    在源程序块中的定义通过 LOAD 命令编译到内存中。许多系统包含一个编辑器,它把每个块组织成 64 字符 16 行的显示模式并提供命令来修改源程序。

    源块在历史上曾经是 Forth 风格的一个重要组成元素。就像 Forth 的定义可以被视为自然语言中的句子,一个块相当于是一个段落,通常包含有与一个主题相关的定义,比如“向量处理”。在块文本的顶行含有这个主题的注释说明,应用程序可以按实际需要来选择装入块。

    块也被用于存储数据。小的记录可以组合进一个块,大的记录也可以分布在几个块中。程序员可以根据应用的需要分配块,独立的 Forth 系统还能够按磁头运动最少的原则来组织数据以优化系统,还有几个开发商提供了基于 Forth 块的文件和数据库系统。

    在主机操作系统之上运行的 Forth 版本使用文件系统来实现块机制,另外也提供基于操作系统环境的一般文件操作方法。

    10. 数据结构

    所有的高级字共享相同的数据结构,这种字的首部含有文本解释器识别一个字所需要的数据信息,见图 3 所示。

    995377-20170223155501648-2082037596.gif

    • 图 3 定义的首部

    LINK”字段包含字典中前一个命令的首部地址,在搜索字典时需要这个地址。

    名字长度”字段包含名字中全部字符的数量,后随这些字符,在解释过程中进行名字匹配时需要这些数据。许多 Forth 系统仅仅存储名字的前3个字符,这可以在占用空间最小的情况下避免名字冲突,而许多系统的名字长度允许在 3-31 个字符之间选择。

    文本解释器从字典的最后一个入口开始处理,并沿着链表向后查找直到匹配名字为止。现在还有许多系统提供散列算法,它们把字典分成几个表,每次只查找其中的一个,这种方式可以大大地节省查找时间。

    代码指针”是这个字将被执行的第一个指令的 CFA ,它形成了定义体的第一个入口。它也是代码的地址,这个地址解释定义的其它部分,对于不同的数据结构将指向不同的代码。

    995377-20170223155527960-2013905588.gif

    • 图 4 不同的数据类型所指向的行为也不同

    字的其它部分也就是定义体,它依不同的数据类型而不同,如 图 4 所示:

    • 在汇编 (CODE) 定义中,体中含有定义命令行为的机器操作码列表,因此 CFA 含有这个体的地址;

    • 在诸如 VARIBLECONSTANT 这样的数据结构命令中,字义的体中含有实际的数据。 CFA 含有处理这些数据所需要的子程序的入口地址,用户定义数据结构的例子如 图 5 所示。

    • 在高级 :(冒号)定义中,字的体中含有构成这个定义的所有以前定义字的地址列表。 CFA 是地址解释器 (:) 的地址。

    11. 程序举例

    下面是一个典型的 Forth 源程序块。这个应用程序用来控制 8LED 提示灯,它也说明了 Forth 定义是如何组合以形成应用环境的。

    995377-20170223155545304-698711508.png

    • 图 5 一个源程序块

    注意第一行 (LINE 0) 的注释说明了这个块中所列出的其它字的属性,这一行通常被称为索引行。多数 Forth 系统都有一个命令字来查找块的第一行以发现哪个块是应用程序所需要的。

    所有的 LED 通过一个位于地址 40H8 位口来访问。这个位置通过第一行的常数定义给出,于是这个口可以通过名字来引用,而如果以后硬件地址改变了,我们也仅仅需要调整这个常数。字 LIGHTS 在堆栈上返回这个地址,定义 LIGHT 得到栈顶值并把它发送到设备上。这个值的属性是位掩码,每一位对应一个 LED 。于是命令:

    255 LIGHTS

    将点亮所有的灯,而命令

    0 LIGHTS

    将关闭所有的灯。如果硬件变化了,我们也只需要改写字 LIGHTS 以适应新的硬件,而应用程序的其它部分则不需要做任何改变。

    4-6 含有对我们终端输入进行的处理,终端输入是为了能够进行简单的诊断以确认各个方面都能够工作正常。这里 DELAY 含有以微秒为单位的延时时间,执行字 DELAY 返回这个变量的地址。 DELAY 的两个值是由 FASTSLOW 定义的,使用 Forth 的操作!(读作 STORE )从栈顶得到地址和值,并把值存储到相应的地址中。

    定义 COUNT 运行一个从 0-255 的循环(在字 DOLOOP 之间)。字 I 把循环的当前值放到栈顶,然后发送给 LIGHTS 。接着系统等待由 DELAY 指定的时间。

    @ (读作 FETCH )从 DELAY 提供的地址读取一个值,并把这个值交给 MS 等待指定的毫秒。执行 COUNT 的结果就是以指定的速率从 0255 之间计数。可以这样调用:

    SLOW COUNTS 或者
    FAST COUNTS

    8-10 行提供单独命名灯的能力。在这个应用中,它们用作灯的指示器。

    LAMP 是一个使用位掩码作为参数的定义字。

    CREATE 把一个首部编译进字典,同时字 ,(逗号)把掩码放到定义体中。

    DOES> 把代码地址放到新字的 CFA 中。于是当新字执行时,它的动作就是获得所定义的新字体中的第一个项目的内容。

    910 使用 LAMP 来命名特别的指示灯。当其中的一个字比如 POWER 执行时,掩码就返回到栈顶。实际上,这种行为与 ForthCOSNTANT 一样。

    但是 LAMP 是一个例子,像这样使用 CREATEDOES> 定义字的能力是 Forth 语言最强大的功能之一,它允许我们定义基于数据结构的“智能应用”。

    最后,行 13-15 ,我们有了控制灯面板的字。 LAMPS 是一个变量,它包含有灯的当前状态。字 LAMP-ON 得到一个掩码(由其中一个 LAMP 字提供),然后点亮灯。 LAMP-OFF 将指定的灯关闭,同时改变 LAMPS 的状态。

    在应用程序的其它地方,灯的名字和 LAMP-ON 、 LAMP-OFF 可能才是需要直接执行的字。用法是:

    POWER LAMP-ON 或
    SAMPLING LAMP-OFF

    在系统上编译这个代码块的时间大约是半秒,包括从磁盘上读入的时间。这样程序员就有可能简单地打入一个定义然后立即执行它。另外我们总是具有与外部设备直接通信的能力。我们可以首先打入:

    HEX FF 40 OUTPUT

    来看看是不是所有的灯都亮。如果不是,可以假定有些地址不对,因为上面的句子是把全 1 直接发送给设备。这种类型的交互在与硬件打交道的时候特别有用,它们能够缩短硬件的开发时间。

    12. 扩展

    由于 Forth 是可扩展的,大量的开发商为 Forth 语言的应用提供许多扩展产品。这些扩展包括自动化的文档、终端驱动、磁盘文件管理、数据库管理、目标编译器、交叉编译器和 META 编译器。

    一个目标编译器允许我们使用一个主机 CPU 比如 PC 机来编写系统程序。程序可以通过键盘编辑和交互式地测试,之后可以把这些程序编译到目标环境中并产生对应的 ROM 代码。目标编译器的一个功能就是剔除目标系统中不需要的代码,比如编辑器、编译器和汇编器。通过这些工作,运行系统的 ROM 开销可以从开发系统所占用的 8K 字节减少到大约 600 个字节。

    交叉编译器与目标编译器类似,它允许用户在主机上开发和测试代码,然后交叉编译器将像目标编译器一样编译 Forth 系统,只是交叉编译器是使用不同的机器语言、为不同的目标 CPU 产生代码。这个特点允许快速地为新的 CPU 开发新的 Forth 系统,由于 Forth 系统主要是用 Forth 语言编写的,所以我们只需要为新的处理器编写一个汇编器,然后为新的处理器进行 Forth 系统的交叉编译就可以了。大多数的 Forth 系统就是用这种方式开发的,结果, Forth 通常成为一个新处理器上的首选语言之一。

    写一个 Forth 编译器的过程也被称为 META 编译。

    13. 多任务

    多任务在 Forth 中从一开始时就有了。这些系统不仅仅是语言处理器,而且包含操作系统的特点,许多集成系统完全是独立运行的,执行所有操作系统的功能。

    Forth 的操作环境运行速度快,所以基于 Forth 的系统就能够支持多用户和多任务,甚至在那些看似不能实现这些功能的计算机硬件上也是这样。例如,一个电话交换板的生产商在一个 Z80 上执行 50 个任务。在 IBM PC 上也有几个多任务产品,有些甚至能够支持多用户。在一般支持多用户操作的计算机上,可以支持的用户数就更多了,一个运行在单个 MC68000 处理器上的数据库应用系统能够支持 100 个终端更新和数据库请示,而运行速度却没有明显的降低。

    多用户系统可以支持多个程序员同时工作,每个程序员都有自己的私有字典、堆栈和一系列变量来控制任务。私有字典连接到一个共享的、可再入的、包含全部标准 Forth 功能的字典。私有字典可以用来开发应用程序代码,这些代码以后可以加入到共享字典中。

    图 6 给出了 Forth 系统实现多任务的典型方法。这是一个“轮循调度算法” 调度器,是 Forth 系统中实现多任务最常用的方法。然而,有一些实现使用时间片调度或者基于优先级的调度以及其它可剥夺的算法,在这样的系统中每个任务都有自己的用户区以保存控制变量、私有字典和堆栈。用户区的第一个字段是 STATUS 变量。这个变量有两个可能的值:唤醒或者休眠。

    995377-20170223155602788-12127924.gif

    • 图 6 在循环调度队列中的 4 个任务

    可以被选择调度执行的任务必须处于唤醒状态。当任务被选择执行时它的状态就被复位到休眠状态。任务一直执行直到调度器执行到字 PAUSE ,这将把任务的状态置为唤醒,控制重新返回到调度器。当调度器再次轮循到这个任务时,将从 PAUSE 的指令之后继续执行。

    除了 PAUSE 字之外,任务也可以执行 STOP 字将控制返回到调度器。这与 PAUSE 类似,但是任务的状态并不切换到唤醒状态。这样,当调度器再次轮循到这个任务时,当前的状态仍然是休眠。这意味着这个任务不能再被执行了,除非它的状态被另外的任务或者中断设置为唤醒。

    系统以这种方式编程并允许中断。当一个中断发生时,一些与机器有关的代码将指定的任务状态置为唤醒,这样当调度器再次到达这些任务时它们将被执行。当任务执行时, STATUS 变量被置为休眠,这就允许一个任务执行时可以发生中断。因此,如果一个任务执行了 STOP 指令而它的状态没有改变,在它执行中一个中断设置了它的状态为唤醒,它就可以再次被调度,于是我们能够缓冲一个中断。然而,这也就意味着当一个任务主动放弃处理器并希望下一次调度继续执行时,它必须把状态设为唤醒。

    轮循调度器使用存储在 LINK 用户变量中的地址作为下一个任务的地址。如果这个任务的 STATUS 是唤醒的,该任务将被调度执行,否则,调度器取出它的 LINK 地址转到下一个任务。

    这种方法有两个主要问题:

    • 当一个任务为了其它任务可以运行而主动放弃处理器时,从放弃到再次得到处理器的时间是不确定的;
    • 中断设置一个任务为唤醒状态到这个任务实际执行之间的时间也是不可知的。

    通过小心地使用 PAUSE ,再加上 Forth 的运行速度很快,已经在主要的应用系统中克服了这些问题。

    14.Forth 硬件

    早在 1980 年,ROCKWELL公司就生产了65F11处理器,这是一个6502处理器的变型,它在6502芯片的 ROM 中固化了 Forth 原语,这个芯片被成功地应用到了许多嵌入式系统中。

    1981年, Chuck Moore开始设计一个 Forth 虚拟机芯片。这个工作首先在 Forth,INC. 进行,后来专门成立了一家公司来开发这个芯片。 1984 完成设计, 1985 年生产了第一个样片。

    后来,HARRIS(INTERSIL)Johns Hopkins University 和其它人也开发 Forth 硬件。基于 Forth 的芯片提供了极高的性能,一般可与 RSIC 芯片相比,但是它没有传统 RISC 的程序设计复杂性。

    15. 标准

    Forth 界认识到需要一个标准,使得应用和扩展都以此为基础。第一个这样的标准从上个世纪 70 年代中期 FIG(Forth 兴趣组织 ) 开始,这个标准后来变成了 FIG-Forth 标准。

    第一个主要的 Forth 标准来自于 1977 年在 Utrecht 召开的一次会议,与会者提出了一个原始的标准并同意以后继续举行会议讨论, 1978 年的会议包括了 FIG 成员,经过一系列由用户和开发商参加的会议,产生了一个更加广泛的标准,称为 Forth-79.

    尽管 Forth-79 标准的影响力是巨大的,但是许多 Forth 用户和开发商发现这个标准中有一些致命缺点。 1983 年,两次进一步的会议产生了 Forth-83 标准。

    受到 Forth-83 标准被广泛接受的鼓舞,一组用户和开发商从 1986 开始讨论美国国家标准的可行性。美国国家标准 Forth 技术委员会,也称为 ANS ASC X3/X3J14 委员会,于 1987 年召开了第一次会议,目标是“达到一个可接受的标准,被 Forth 产品主要开发商接受,对现有在用产品的不利影响最小”。

    1994 年,也就是大约 7 年之后,新的标准最终产生了,这是所有标准中走得最远的。使用来自 5 个国家的说明,通过开发商向社会公开。两年之后,国际标准化组织接受这个标准为国际标准。

    16. 研讨会和定期出版物

    由于人们使用 Forth 进行工作并不断做出有益的扩展,所以 Forth 语言也在不断地发展。有三个年会关注着 Forth 语言的发展:

    • Forth Modification Laboratory (FORML)
      held at Mt. View in California and organised by the Forth Interest Group.

    • Rochester Forth Conference (RFC)
      held at the University of Rochester in New York and organised by the Institute for Applied Forth Research Inc.

    • European Forth Conference (euroForth)
      held in a different location each year. This is the only conference to provide a refereed (peer reviewed) section. Originally organised by the European Forth Interest Group, but now organised by various European based Forth vendors.

    对于 Forth 的许多新的思想最先在这些 Forth 相关的杂志上出现:

    • Forth Dimensions (ISSN 0884-0822)
      published six times a year by the Forth Interest Group for its members.

    • Journal of Forth Application and Research (ISSN 0738-2022)
      published irregularly by the Institute for Applied Forth Research Inc. This is the only peer review (refereed) journal directed to the Forth language. The Journal is now published electronically on the Internet. A paper version of the Journal will be published at irregular intervals.

    17. 总结

    FROTH 可以被看成是有两个堆栈(参数栈和返回栈)的、有可扩展汇编语言的处理器。 Forth 解释器可以看成是这个抽象处理器的完全宏汇编器和完全集成的操作系统。

    这就给我们提供了一个交互式的调试环境,使我们可以增加新的宏(高级定义)和新的指令(低级 CODE 定义)。它甚至允许我们通过定义新的数据类型(使用定义字 CREATE/DOES> )扩展宏系统本身。因为这个解释器也是一个全功能的操作系统,所以程序员只需要学习一种工具。

    Forth 有四个直接的优点:亲善、直接、可扩展和经济。它还有两个间接的优点:可理解和符号化。

    Forth 不仅仅是一种语言,它更是一种解决问题的哲学思想。这可以用缩写 K.I.S.S 来概括( Keep It Simple and Stupid ,保持它的简洁和易用)。我们可以引用 Jerry Boutelle (owner of Nautilus Systems in Santa Cruz, California) 的话,当被问及“使用 Forth 是怎么影响你的思维”时,他回答:

    Forth 以许多方式改变了我的思维。从学习 Forth 开始,我已经使用了各种语言编程,包括汇编、 BASICFORTRAN 。我发现我一直在使用 Forth 的问题分解方式,通过创建字的方式把它们组合在一起。例如,在处理字符串的时候,我会像 ForthCMOVE-TRAILINGFILL 那样来定义子程序。更基本地, Forth 坚定了我对简单性的信念。在面对一个问题的时候,许多人使用特别复杂的工具,但是简单的工具也可以使用而且更有用。我试着简化我生活的方方面面。”

    这里我引用中国哲学家老子的一句话:

    “为学日益,为道日损”

    或者引用 Antoine Lavoisier (1789) 的话:

    “把科学和语言分离是不可能的,因为每一项自然科学总是包含三件事情:科学所基于的一系列现象,在头脑中命名这些现象的抽象概念,表达这些概念的词汇。为了说明一个概念,我们需要一个词汇;为了描绘一个现象,我们需要一个概念。所有这三件事情都反映了同一个现实。”
    这就是包含在 Forth 语言背后的哲学。

    18. 参考文献

    • International Standards Organisation (1997).
      Information technology - Programming languages - Forth (First ed.), ISO/IEC 15145:1997

    • American National Standards Institute (1994).
      American National Standard for information systems: programming languages: Forth. ANSI/X3.215-1994.

    • IEEE 1275 Technical Committee (1994).
      IEEE Standard 1275-1994 - Standard for Boot (Initialization Configuration) Firmware: Core Requirements and Practices. IEEE.

    • C. L. Stephens and R. M. Rodriguez (1986).
      PolyForth: An electronics engineer's programming tool. Software Engineering Journal, 1:154-158.

    • Leo Brodie (1984).
      Thinking Forth. Prentice Hall International.

    • Leo Brodie (1982).
      Starting Forth. Prentice Hall International, second edition.

    • Charles Moore (1980).
      The evolution of Forth. Byte, 5(8):76-84.

    • Charles Moore (1974).
      Forth: A new way to program a mini-computer. Astronomy & Astrophsics Supplement, 15:497-511.

    • Jan Lukasiewicz (1963).
      Elements of Mathematical Logic, volume 31 of International Series of Monographs in Pure and Applied Mathematics. Pergamon Press Ltd., Headington Hill Hall, Oxford, England, second edition, 1963. First published in 1929.
      The Forth Monitor

    The Forth Monitor, the default mode in OpenBoot, is an interactive command interpreter that gives you access to an extensive set of functions for hardware and software diagnosis. You'll also see the Forth Monitor referred to as new command mode. These functions are available to anyone who has access to the system console.

    转载于:https://www.cnblogs.com/freeblues/p/6433869.html

    展开全文
  • Retro 是一种源于 Forth 的串联式、基于堆栈的编程语言。 它旨在清洁和实用。 除非来源中另有说明,否则所有代码、文档和任何包含的二进制文件均在 ISC 许可下提供。 请随意采用、使用和修改您认为合适的 Retro。 ...
  • Forth

    千次阅读 2010-12-22 16:02:00
    C 语言使你迷茫?Forth 可能是一个答案 程序语言2010-05-25 22:27:28... Forth May Be the Answer  原作者 Tom Napier 和 Eric Krieg 原文引自 www.Forth.org <br />曾经有个时期,人们不害怕从
  • Forth虚拟机源码(C版本),可以用来理解forth虚拟机架构
  • 4tH是一个Forth编译器,差别很小。 它具有标准的编译器,而不是标准的Forth引擎。 4tH是一个非常小的编译器,它可以创建字节码,C嵌入式字节码,独立的可执行文件,但作为脚本语言也可以正常工作。 它支持大约95%的...
  • Forth 常见问题解答

    千次阅读 2005-03-07 15:52:00
    Forth 常见问题解答 本文译自 comp.lang.forth Frequently Asked Questions (1/6): General/Misc 原文整理 M. Anton Ertl, anton@mips.complang.tuwien.ac.at Forth 是什么? Forth 是怎么来的? Forth 用在什么地方...
  • The force: Forth 语言

    2016-03-14 04:13:59
    The force: Forth 语言 MD Document: 2/24/2016 8:49:24 AM by Jimbowhy 这是一个可以靠美色搞钱的时代,这是一个可以靠权力搞钱的时代,可是我... - by Jimbowhy 本文是《VirtualNES虚拟机》关于 Forth语言的拓展内容
  • 根据运用和与机器的相关性可分为系统虚拟机和程序虚拟机,一个提供了完整的操作系统,另一个则以运行单个计算机程序为主。
  • Forth 语言概要

    千次阅读 2005-03-07 16:01:00
    Forth 语言概要 原作者 Peter Knaggs 原文标题《 Forth: An underview 》 本文的目的是给出 Forth 编程系统的一个整体轮廓,包括语言的历史、突出的特点和使用方法,讨论了最常用的实现方法,但更重要的是讨论了 For...
  • Forth 系统实现

    千次阅读 2005-03-07 16:42:00
    Forth 系统实现 原作者 Brad Rodriguez编译者 赵宇 张文翠 本文编译自 Brad Rodriguez 《 Moving Forth 》,原文首次在 The Computer Journal #59 (January/February 1993) 上发表,现在可在下面网站上取得 ...
  • Java虚拟机虚拟机内存区域 Java虚拟机内存区域 Java程序在JVM虚拟机中运行,当我们一个类被加载到虚拟机中时,JVM会给该类分配具体的内存空间/内存地址,而这被分配的区域就是Java虚拟机运行时内存区域。那么,该...
  • 并发故障模式主要是针对程序员对多线程的编码机制、各种同步方法、Java存储器模式和Java虚拟机的工作机制不清楚, 而且由于线程启动的任意性和不确定性,使用户无法确定所编写的代码具体何时执行而导致对公共区域...
  • The forth (final ,对象的可见性)

    千次阅读 2015-02-02 11:19:31
     用static修饰的代码块表示静态代码块,当Java虚拟机(JVM)加载类时,就会执行该代码块。   1、static变量                按照是否静态的对类成员变量进行分类可分两种:一种是被static修饰的变量...
  • 这是语言('I')及其虚拟机(所有这些都在PICO-8中使用)的核心引擎。 您可以扩展此引擎(请参见_SHW或_CLS的实现方式)。 您可以创建同义词以简化使用(请参见_ADD和_ +)。 程序必须写成一行。 术语之间用空格隔...
  • java虚拟机

    2016-08-10 18:55:39
    学习了一些java虚拟机基本的东西,总结如下。 参考文章: Java虚拟机学习:...java GC、新生代、老年代:https://zm12.sm-tc.cn/?src=http%3A%2F%2Fwww.th7.cn%2FProgram%2Fjava%2F201409%2F27627
  •  第四个女孩 数学系师姐forth  一个闷热的下午,我坐在梯形教室里,百无聊赖,听着讲台上一个白发大师的个人咏叹调。为加强理工科同学们的人文修养,出去泡妞不至于没词,丢我校的脸,学校新开了一批公共选修课,...
  • FVM factory-开源

    2021-04-15 04:10:47
    用于为嵌入式应用程序增量构建自定义的Forth虚拟机的工具。 令牌编译器将令牌描述转换为C代码模板。 PC控制台应用程序包括FVM,它用于编译和调试目标FVM的字节码。
  • Android虚拟机

    2013-07-01 18:03:56
    确切说不是模拟器,而是Android虚拟机,因为它需要VirtualBox环境,所以速度杠杠的,另外它跟Android Studio可无缝整合。 A Productive Android Development Environment JUN 27TH, 2013 I
  • 虚拟机扩容

    2019-05-06 22:20:00
    ls -lrt df -Th 1.虚拟机所在磁盘空间不够,能够把虚拟机复制到还有一块磁盘里。 2.进入VMware的安装文件夹,在命令提示符后输入"vmware-vdiskmanager",什么參数也不加直接按回车键,可显示这一命令的说明。 3...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,615
精华内容 2,646
关键字:

forth虚拟机