User:Arnie97/HP Saturn Intro
此用户页面尚未完工。原作者将会继续进行编写,而您也可以对该条目进行编辑。
本条目介绍的是 HP Apple 39gs 等 Saturn 系列计算器的基础知识。
Saturn
Saturn 是 HP 于上世纪 80 年代为其计算器开发的一种 4 位微处理器,该处理器有 Bert、Sacajawea、Lewis、Clarke、Yorke、New-Yorke 等子系列。[1]
Apple(Saturn+)系列
在 Saturn 处理器停产后,为了保持与 Saturn 平台原有程序的兼容性,HP 推出了一系列在 ARM 处理器上运行 Saturn 模拟器的计算器,与上面的那些子系列相对,软件模拟的 Saturn 处理器被称为 Apple 系列。这些模拟处理器相比之前真实的 Saturn 处理器拥有更多的功能,因此也被称作 Saturn+。 Apple 系列推出后,39、49 系列的图形计算器均发布了多款对应的新型号:
| 系列 | 原型号(Yorke 系列处理器) | 新型号(Apple 系列模拟处理器) |
|---|---|---|
| 39 | 39g 40g | 39g+ 39gs 40gs |
| 49 | 49g | 48gII 49g+ 50g |
这些新型号的系统软件与相对应的原有型号非常相近,只不过系统是运行在模拟器内,而不是运行在真实的 Saturn 处理器上。因此,很多相关的术语保留了下来。
值得注意的是,名为“HP ??gII”的计算器(“?”代指数字)往往与同编号的其他产品大相径庭,切勿混淆。例如,HP 48gII 不属于 HP 48 系列,而属于 HP 49 系列;而 HP 39gII 则不属于 Saturn 系列产品,而与后期推出的 HP Prime 有几分相近。
系统架构概述
Saturn 汇编语言
无论是原有 Saturn 系列还是 Apple 系列,由于使用了或真或假的 Saturn 处理器,显然都可以直接使用 Saturn 汇编语言编写程序。
Saturn 汇编常与编译型语言 System RPL 共同使用,相关内容详见下文,在此不再赘述。
RPN
RPN(Reverse Polish Notation,逆波兰表示法)将运算符置于操作数的后面,因此又称后缀表示法。与之相对的是绝大多数语言采用的代数表示法(Algebraic Notation,运算符位于操作数之间,又称中缀表示法)和 Lisp 等语言采用的波兰表示法(运算符位于操作数之前,又称前缀表示法)。
| 表达式记法 | 运算符位置 | 示例 | 采用该记法的语言 |
|---|---|---|---|
| 波兰表示法 | 前缀 | * - 3 4 5 | Scheme,Common Lisp 等 |
| 代数表示法 | 中缀 | (3 - 4) * 5 | C++,Python,TI-Lua,HP Basic 等 |
| 逆波兰表示法 | 后缀 | 3 4 - 5 * | Forth,System RPL 等 |
逆波兰表达式的解释器一般是基于栈(Stack)这一数据结构的。要理解 RPN,最好先理解栈的概念。 RPN 解释求值的过程一般是:遇到操作数时入栈;遇到运算符时,取对应数量的操作数出栈,求值,将结果入栈;最终栈顶就是表达式的值。
例如,常规中缀记法的 12 * (3 + 4) - 6 + 8 / 2 用 RPN 写作 12 3 4 + * 6 - 8 2 / +,其运算过程如下:
- 首先,12、3、4 依次入栈。
- 输入加号时,由于它是二元运算符,会弹出栈顶的两个数进行运算,并将结果 7 压入栈中。
- 乘法同样是二元运算,弹出栈顶的 12 和 7 两个数,并将结果 84 返回栈顶。
- 随后,数字 6 入栈。
- 之后是减法,取出栈顶的 84 和 6,并返回结果 78。
- 随后,8 和 2 入栈。
- 之后是除法,取出栈顶的 8 和 2,并将结果 4 压入栈中。
- 最后取出 4 和 78 做加法,得到最终结果 82。
RPN 的运算符之间不存在优先级的高低,不需要使用括号来表明运算的优先级,因此能减少输入部分复杂表达式时按键的次数。
例如,常规中缀记法中 3 - 4 * 5 与 (3 - 4) * 5 的意义不相同,需要用括号加以区分;但后缀记法中前者写做 3 4 5 * - ,后者则写做 3 4 - 5 * 。
System RPL
System RPL(其中 RPL 指 Reverse Polish Lisp)是 HP 计算器上广泛使用的一种编译型语言。顾名思义,该语言中的语句采用逆波兰表示法。
HP 38、39(40)、48、49(50)等系列的图形计算器均支持该语言[2],且大部分系统软件和很多第三方软件由该语言写就。HP 38、39(40)、49(50)等新系列计算器的很多第三方应用来源于对 HP 48 等早期系列中 System RPL 应用的移植和重新编译。
作为一种贴近底层的编译型系统编程语言,System RPL 常与 Saturn 汇编共同使用,这与 PC 平台上的 C 语言和 x86 汇编语言有着相通之处。这两种语言可以用 PC 上的 HP Tools 开发。此外,HP 49、50 等系列的计算器内置了 MASD,可以直接在计算器上进行编译、汇编、调试操作。注意 HP Tools 和 MASD 均是编译器本身,并不包含头文件(Entry Points,或简称 Entries),如果不希望手动声明系统提供的函数,需要自行下载头文件,其中的原理与 C 语言是相通的。HP 28、38、39(40)、48、49(50)系列的头文件互不相同,下载时需根据所针对的机型正确选择。
Library
Aplet
User RPL
User RPL 是 HP RPN 计算器上的一种解释型语言。顾名思义,该语言同样采用逆波兰表示法。
HP 28、48、49(50)等系列的计算器支持该语言代码的运行。如果在设置中选择 RPN 输入模式,那么用户在计算界面中输入的有效指令实际上均可以视为合法的 User RPL 代码。
与 System RPL 的关系
User RPL 的语法和 System RPL 相近,但代码可以直接在计算器上运行而不需要编译。运行时发生的大部分错误会被正确捕获,且部分较为危险的底层命令无法直接使用。这些特性使得 User RPL 的编写和调试更方便和安全,但也使它的运行速度较 System RPL 缓慢,在需要对系统底层进行操控及性能因素至关重要的场合(如某些游戏)应当选择 System RPL。
User RPL 能通过多种方式调用 System RPL 特有的函数,相关内容并入下文 HP Basic 的相关章节,在此不再赘述。
在 HP 49(50)系列计算器内置的文件管理器(Filer)中,User RPL 代码的文件类型为 PROG,System RPL 源码的类型为普通字符串 STRNG,而 System RPL 编译出的二进制对象类型为 CODE。
HP Basic
HP Basic 是 HP 38、39(40)系列计算器的解释型语言,其定位与 HP 48、49(50)系列中的 User RPL 相似——用户在 HOME 界面中输入的有效指令均为合法的 HP Basic 代码。由于该语言的代码通过解释器执行,且解释器本身又运行在 Saturn 处理器或模拟器上,因此速度是本文提及的所有语言中最慢的。
调用 System RPL
HPGCC
ARM Toolbox
Aplet 框架
内存布局与固件
数据类型与联机传输
数据对象的内部表示(变量)
数据在内存中以不同的方式(数据结构)储存着。这些数据结构当中有顺序的(例如线性表的数组形式),也有非顺序的(例如线性表的链表形式)。
数据对象的外部表示(文件)
为了将数据,尤其是非顺序的数据:
- 保存于外存(硬盘、光盘、闪存等)的某个文件中以备后用
- 通过网络等方式共享给另一台计算机
- 通过串口等方式传送至图形计算器等设备
我们需要将数据编码为字符串(字节流)方能储存或传输,这一编码过程称为序列化(Serialization)。
变量的类型系统:静态类型与动态类型
变量是代指数据的名称、符号。
- 在 C++、Java 等语言中,每个变量均对应一个特定的数据类型,使用前必须声明每个变量的数据类型,这样的类型系统称为静态类型。
- 在 Haskell 等语言中,虽然很多情况下不需手动声明变量的数据类型,而是通过计算机的自动推导来确定数据类型,但每个变量均有特定的类型——类似 C++ 11 中使用
auto的情形——因此同样属于静态类型。 - 在 Python、JavaScript 等语言中,类型依附于变量中储存的数据本身,数据有类型而变量无类型,这样的类型系统称为动态类型。
文件的类型系统:扩展名与特征签名
类比变量,文件名(和路径)是代指文件的符号。对于文件来说,同样有数种不同的方式来记录它的类型,其中就包括:
- 文件名称的某个特定部分指示一个文件的类型——通常是最后一个小数点后的部分,也就是扩展名(Extension)。
- 文件内容的某个特定部分,即特征签名(File Signature)指示一个文件的类型——通常是最前面的部分,也就是头部(Header)。
扩展名最早在 CP/M 操作系统中被采用,而后又随一脉相承的 DOS 和 Windows 得到了推广;特征签名则在 Unix 中被广泛应用,而后又被 Linux 等操作系统所继承下来。由于两类操作系统均得到了广泛的应用,现实中两种方式常常共存:
| 文件类型 | 扩展名 | 特征签名 |
|---|---|---|
| MZ 可执行文件
PE 可执行文件 |
com exe
exe dll sys ocx cpl scr 等 |
MZ(设计者 Mark Zbikowski)
(为向下兼容 DOS,PE 文件头部与之相同) |
| ELF 可执行文件 | 无 | \x7F E L F
|
| PDF 文档 | %PDF
| |
| ZIP 压缩文件 | zip docx pptx xlsx 等 | PK(设计者 Phil Katz)
|
| RAR 压缩文件 | rar | Rar!
|
| CAB 压缩文件 | cab | MSCF(Microsoft Cabinet File)
|
| PNG 图片 | png | \x89 P N G
|
| GIF 图片 | gif | GIF89a 或 GIF87a
|
| JPEG 图片 | jpg jpeg | 以 \xFF \xD8开始,\xFF \xD9 结束
|
| Midi 音轨 | midi | MThd(MIDI Track header)
|
| Java 字节码 | class | \xCA \xFE \xBA \xBE,即十六进制 CAFEBABE
|
从上面的例子中可以看出,既有一个扩展名对应多种特征签名的情况,也有多种扩展名对应单一特征签名的情况。此外,由于两种方式共存,很多软件只选择其一来判断文件的类型。例如,将 JPEG 图片的扩展名更改为 png 仍能用多数图片查看器正常打开,说明这些软件仅通过文件内容中的特征签名来判断文件的格式,扩展名无关紧要。同样,HP Saturn 系列计算器也仅判定文件的特征签名,而扩展名的作用只是辅助人类的辨识:
| 文件类型 | 常见扩展名 | 特征签名 |
|---|---|---|
| HP 39(40)系列 | 000 apt lib 等 | HP39Asc?(文本,ASCII)
|
| HP 48 系列 | 不固定 | HPHP48-?
|
| HP 49(50)系列 | hp lib 等 | HPHP49-?
|
上表中,? 代指表示文件类型的一个大写拉丁字母;同一字母在不同系列中有着不同的意义,详见下文各章节。另外,由于扩展名并无实际作用,用户可根据自己的喜好和实际情况选择不同的扩展名——例如,为了方便用记事本打开,可以用 txt 作为扩展名;[3]为了方便用户区分不同机种的文件,跨平台应用的开发者有时直接用 48、49 等作为扩展名。[4]
内部表示(变量)外部表示(文件)与间的关系
表面上看,HP 39(40)、48、49(50)的文件格式互不相同,PC 上的官方联机工具(Connectivity Kit)也形式各异。但是,多项证据已经表明,不同系列的 Saturn 机种使用相同的方式来储存 RAM 中的对象。
例如,我们用含有 HP 48gII 固件的 ROM 替换 HP 39gs 原有的闪存,且期间保持电源供给以免 RAM 中的数据丢失。那么,当进入 49 系列的系统后,我们将看到之前在 39 系列系统中储存的所有文件(和文件夹)。鉴于 39 系列系统中并未提供完整的文件管理器,如果想探查 39 系列计算器的目录结构,除了选择自己编写文件管理器外,亦可利用上述特性,借助 49 系列内置的文件管理器来达到目的。
综上所述,不同系列间文件格式的差异,本质上是相同对象类型的不同序列化形式,传入计算器后的生成的对象是相同的,可谓“换汤不换药”。