Agon Light 和其他 Agon 平台版本均基于 Zilog eZ80 处理器。 eZ80 具有 24 位地址空间,支持 16 MB 内存,而原始 Z80 为 64 KB。 eZ80 有两种操作模式:标准 Z80 模式,具有 16 位寄存器,可以轻松寻址 64k 内存,但需要使用“banking”来访问超过 64k 的内存; ADL(地址数据长)操作模式,将寄存器扩展到 24 位,使整个地址空间易于访问。
当我们考虑高级编程语言时,Z80 有多种可用的语言,但它们仅限于 64k 内存,或者具有笨拙的存储体切换方法来访问更大的内存。
考虑到 C 编程语言,有许多可用的 Z80 C 编译器。迄今为止,Agon 社区主要关注两个方面:
Zilog ZDS II开发环境,可以生成eZ80 ADL代码。这是 Agon 开发人员使用的原始工具集,但它是闭源的,仅在 Windows 上运行,并且仅支持数据 C89 标准
SDCC(小型设备 C 编译器)是 8 位计算机的流行选择,并将其应用于 Agon 一直是 Agon 计算机中许多人关注的焦点。这是一个很好的 Z80 编译器,但它只支持 Z80,不支持 ADL 模式。
作为替代方案,CEdev C/C++ 工具链是一个可以生成 ADL 代码的开源编译器。它针对 TI-84 Plus CE 计算器(基于 eZ80 处理器),并拥有一个规模合理的社区。 CEdev 基于 eZ80 版本的 LLVM 编译器和 fasmg 汇编器。它生成具有 24 位指针、24 位整数、32 位长整型、16 位短整型和 32 位浮点型的 ADL 代码。还有相当广泛的 C 和 C++ 程序库(尽管它还不符合 ISO 标准……)。
AgDev 是修改 CEdev 以适应 Agon 平台的功能集和硬件设计的努力的结果。与 Agon 的其他选项相比,其结果是一个更强大且支持 C++ 的工具链。
下载发布版本或自行从源代码构建。将构建放在您选择的目录中。
然后,确保/bin
文件夹可以在PATH
中找到;如果您使用的是 Windows,请按照本指南操作,或者您也可以运行 cedev.bat 并从那里执行命令。在 Linux 上,在终端窗口中运行export PATH=/<insert path here>/bin:$PATH
。
这遵循与原始 CE 工具链相同的方法(请参阅 CEdev 入门页面的底部)。构建过程已被修改为在生成.bin
文件时停止。这是 Agon Light 可执行文件。
我建议使用:
使干净 使V=1
make clean
命令可用于删除先前编译的结果,从而强制重新编译。
构建过程经过以下步骤:
使用ez80-clang
将 .c 源文件编译为 LLVM 位码 (.bc)
使用ez80-link
链接 LLVM 位码。这包括链接时间优化
使用ez80-clang
为源程序生成 eZ80 汇编代码 (.src)
使用fasmg
将生成的汇编代码(来自步骤 3)与库和编译器运行时进行组装和链接 - 这包括构建针对特定内存位置的可执行文件。这是构建过程中需要调整的主要部分。
请参阅 Zilog 应用说明“从 asm.pdf 调用 C”。
被调用函数仅需要保留 IX 寄存器和堆栈。
参数从最后一个推到第一个,与 C 原型相对应。在 eZ80 中,无论实际大小如何,始终将 3 个字节压入堆栈。但是,汇编函数必须小心,仅使用推送的有效字节。例如,如果使用短类型,则压入堆栈的值的高字节将包含任意数据。此表列出了被调用函数内相对于sp的位置。请注意, sp + [0,2]
包含返回地址。
C/C++ 类型 | 尺寸 | 堆栈位置 |
---|---|---|
字符 | 1字节 | sp + [3] |
短的 | 2字节 | sp + [3,4] |
整数 | 3字节 | sp + [3,5] |
长的 | 4字节 | sp + [3,6] |
长长 | 8字节 | sp + [3,10] |
漂浮 | 4字节 | sp + [3,6] |
双倍的 | 4字节 | sp + [3,6] |
指针 | 3字节 | sp + [3,5] |
请注意,eZ80 是小端字节序 - 即首先存储最低有效字节。
该表列出了用于函数返回值的寄存器。类型的符号不会影响所使用的寄存器,但可能会影响返回的值。 LSB 位于表达式最右边的寄存器中,例如E:UHL
表示寄存器L
存储LSB。
C/C++ 类型 | 返回寄存器 |
---|---|
字符 | 一个 |
短的 | HL |
整数 | 超HL |
长的 | E:UHL |
长长 | BC:UDE:UHL |
漂浮 | E:UHL |
双倍的 | E:UHL |
指针 | 超HL |
不符合 ISO 标准!
由以下部分组成:
文件IO:
fopen()
、 freopen(),
fclose()
fputc()
, fputs()
fgetc()
、 ungetc()
、 fgets()
feof()
、 ferror()
、 fflush()
fread()
、 fwrite()
fseek()
、 rewind()
、 ftell()
clearerr()
remove()
标准输入/标准输出 IO:
putchar()
、 puts()
getchar()
、 gets_s()
格式化输出
printf()
(和vprintf()
)
sprintf()
(和vsprintf()
)
snprintf()
(和vsnprintf()
)
格式化输入
scanf()
sscanf()
这里还有一些其他的东西 - 比如stdint
等 - 但它应该主要符合对普通标准库的期望。大多。
stdio
重定向可以通过在stdout
或stderr
上使用freopen()
来重定向输出:
putchar()
- 输出到outchar()
除非输出被重定向,在这种情况下输出到fputc()
puts()
- 调用putchar()
printf()
(和vprintf()
) - 调用npf_putc_std()
,它在nanoprintf.c
中调用putchar()
fputc()
- 除非在调用 outchar mos_fputc()
时在stdout
上调用,否则调用 mos_fputc outchar()
- 避免调用putchar()
这样就不会出现函数调用循环的风险
可以通过在stdin
上使用freopen()
来重定向输入:
getchar()
- 调用inchar()
来获取字符,并调用outchar()
来回显该字符(即使输出已被重定向)。如果输出尚未重定向,则调用fgetc()
并且不回显该字符。
gets_s()
- 如果输入尚未重定向(行以 CR 终止),则调用getchar()
。输入的调用fgets()
已被重定向(行以 CR/LF 对终止)。
scanf()
- 调用uscan.c
中的getchar()
(不需要更新)
fgetc()
- 除非在调用inchar()
时在 stdin 上调用,否则调用mos_fgetc()
并使用outchar()
进行回显 - 避免调用getchar()
这样就不会出现函数调用循环的风险
需要FILE *
,它是指向fopen
返回的文件句柄的指针,并传递给文件 IO 例程以指示要对其执行操作的文件。
其他相关文件:
stdio.h
- 普通头文件,定义各种函数和FILE
的 typedef
files.c
- 实例化文件句柄的存储,包括:stdout、stderr、stdin。
定义了以下标准文件句柄:
stdout
- 默认输出
stderr
- 错误消息的默认输出
stdin
- 默认输入
MOS 没有实现输入/输出重定向,所以默认情况下这些都使用控制台。
有两个选项可用于命令行处理。
如果主函数定义为,则会自动包含此内容
int main( int argc, char* argv[] )
使用空格作为分隔符来分割命令行。命令行选项照常在argv[]
数组中可用。
如果应用程序 makefile 包含以下内容,则可以选择包含此内容:
LDHAS_ARG_PROCESSING = 1
这支持
用双引号引用
输入/输出重定向
>out_file.txt
- 将 stdout 重定向到out_file.txt
,创建一个新文件
>>out_file.txt
- 将 stdout 重定向到out_file.txt
,附加到文件末尾
<in_file.txt
- 将标准输入重定向到in_file.txt
有关 MOS 命令的最新文档,请参阅 Agon Console8 文档。
MOS(机器操作系统)提供了与 Agon 文件系统和一些硬件外设(如鼠标)的接口。它将系统变量的信息保存在一个大型SYSVAR
结构中,可以在 Z80 端访问。一般来说,你的 C 代码会声明一个指向该结构的指针,初始化如下:
静态易失性 SYSVAR* sv; sv = vdp_vdu_init();
有关更多信息,请参阅<mos_api.h>
。
有关 VDU 命令的最新文档,请参阅 Agon Console8 文档。
VDP(视频显示处理器)接受来自 MOS 的文本流,其作用类似于文本/图形终端。文本流可以包含:
普通文本
转义序列/命令来控制显示并发送图形/声音/等命令
当 MOS 作为发送命令的结果返回结果时,这些结果存储在SYSVAR
中,并且不会直接返回以响应命令。响应是异步的 - 检查结果是否已返回:
将SYSVAR
中的vdp_pflags
设置为零
发出VDU命令
等待vdp_pflags
中的相关位被设置 - 请参阅<mos_api.h>
了解位掩码
命令可以通过以下方式发送:
putch()
- 单个字符(这不是 C 标准库的一部分)
mos_puts()
- 多字符字符串
这两个输出都直接输出到 MOS/VDP - 请注意,它们不是 STDIO 库的一部分,并且不受 CR/LF 转换或重定向的影响。
AgDev 中提供了许多 VDU 命令的便捷功能。例如,要将屏幕模式更改为 3,C 调用vdp_mode(3);
将22,3
作为单个字节发送到输出,相当于putch(22); putch(3);
有关这些函数的列表,请参阅<vdp_vdu.h>
。与键盘处理相关的其他函数可在<vdp_key.h>
中找到。