Zeal 8-bit OS系统调用终极指南:25+个API逐一详解与调用技巧
2026/8/18 15:01:38 网站建设 项目流程

Zeal 8-bit OS系统调用终极指南:25+个API逐一详解与调用技巧

【免费下载链接】Zeal-8-bit-OSAn Operating System for Z80 computers, written in assembly项目地址: https://gitcode.com/gh_mirrors/ze/Zeal-8-bit-OS

如果你正在为 Z80 计算机开发软件,那么Zeal 8-bit OS 系统调用(Syscall)就是你与操作系统内核打交道的唯一官方通道。Zeal 8-bit OS 是一款完全用 Z80 汇编语言编写的轻量级操作系统,内核代码不到 8KB,却提供了 27 个功能完整的系统调用 API,覆盖文件读写、目录操作、进程管理、时间日期与内存映射。本文将逐一详解全部Zeal 8-bit OS API,并分享新手最容易踩坑的调用技巧,帮你快速写出稳定高效的用户程序。

什么是 Zeal 8-bit OS 系统调用?

系统调用是用户程序请求内核执行特权操作的机制。Zeal 8-bit OS 借鉴了 Linux 与 CP/M 的设计思路,把"打开文件""读取键盘""映射内存"等硬件相关操作全部抽象成统一接口,用户程序只需把调用号放入 L 寄存器参数放入指定寄存器,然后执行一条RST $08指令即可进入内核。

调用完成后,返回值统一放在A 寄存器中:0表示成功,非0则是错误码。完整系统调用表可查看文档docs/system-calls.mddocs/details/syscalls.md,内核分发逻辑位于kernel/syscalls.asm,调用号常量定义在include/syscalls_h.asm

调用约定的核心规则

项目约定
调用号存入寄存器L(如ld l, 2表示 open)
参数按规则放入HDEBCA等寄存器
触发指令RST $08
返回值A寄存器,0 为成功
次要返回值BC(读写的字节数)、DE(时间值)等

⚠️最重要的限制:传给系统调用的任何缓冲区都不能跨越 16KB 虚拟页边界!例如缓冲区起点在0x7FFF、长度为 2 字节,就会跨越页 1 和页 2 而报错。遇到大缓冲区,请分多次调用。

文件操作类系统调用:读写文件的六个核心 API

文件操作是使用频率最高的系统调用组,包括readwriteopencloseseekdstatstat,共 7 个 API。

open(#2):打开文件或驱动

open接受文件路径(存于BC)和标志位(存于H),成功返回描述符。路径支持三种写法:相对路径file.txt、当前磁盘绝对路径/dir/file.txt、跨磁盘绝对路径C:/dir/file.txt

常用标志位定义在头文件kernel_headers/sdcc/include/zos_vfs.h中:

  • O_RDONLY(0)只读、O_WRONLY(1)只写、O_RDWR(2)读写
  • O_TRUNC:打开即清空文件
  • O_APPEND:每次写入前自动移动游标到文件末尾
  • O_CREAT:文件不存在时创建
  • O_NONBLOCK:非阻塞模式(仅对驱动有效)

小技巧:打开驱动而非文件时,名称必须以#开头且不超过 4 个字符,例如#SER0

read(#0)与 write(#1):数据搬运

readH=描述符,DE=缓冲区,BC=字节数,返回时BC=实际读取字节数。write参数完全相同,只是方向相反。标准输出DEV_STDOUT(0)和标准输入DEV_STDIN(1)也通过它们读写。

close(#3):及时释放资源

关闭描述符。内核能同时打开的文件/驱动数量有限,用完务必立即关闭,否则后续open可能失败。注意:程序退出时内核会自动关闭其打开的所有设备并重置标准输入输出。

seek(#6):移动文件游标

H=描述符,BCDE=32 位偏移量,A=基准位置。基准值有三种:SEEK_SET(0,从文件头)、SEEK_CUR(1,相对当前位置)、SEEK_END(2,相对文件末尾)。偏移量超出文件大小时,游标会被钳制到文件末尾。

dstat(#4)与 stat(#5):获取文件信息

dstat针对已打开的描述符(H),stat针对文件路径(BC),两者都把结果写入DE指向的结构体,包含文件标志、32 位大小、日期和名称。

目录与路径操作:六个目录系统调用详解

Zeal 8-bit OS 支持真正的目录树(取决于文件系统),相关 API 共 6 个。

  • mkdir(#8):创建目录,路径存入DE。路径中任何一级不存在都会失败。
  • chdir(#9):切换当前工作目录,路径存入DE
  • curdir(#10):把当前工作目录写入DE指向的缓冲区,缓冲区至少要PATH_MAX(128)字节。
  • opendir(#11):打开目录,DE=路径,成功返回描述符。
  • readdir(#12):读取目录下一个条目,H=目录描述符,DE=缓冲区。返回ERR_NO_MORE_ENTRIES(21)表示条目已读完。
  • rm(#13):删除文件或目录,路径存入DE

目录条目结构为 1 字节标志 + 16 字节文件名,可用D_ISFILE/D_ISDIR宏判断类型。

进程管理:exec 与 exit 的进阶玩法

Zeal 8-bit OS 是单任务系统,但通过exec可以加载并运行子程序,形成嵌套执行树。

exec(#16):加载并执行程序

BC=程序路径,DE=字符串参数(可空),H=执行模式:

  • EXEC_OVERRIDE_PROGRAM(0):子程序直接覆盖当前程序,节省内存。
  • EXEC_PRESERVE_PROGRAM(1):当前程序保留在 RAM(需额外 48KB),子程序退出后自动恢复执行。

注意:子程序会继承父程序打开的全部描述符、当前目录和寄存器,因此子程序退出前必须关闭自己打开的描述符,否则会"泄漏"给父程序。嵌套深度由menuconfigCONFIG_KERNEL_MAX_NESTED_PROGRAMS决定。

exit(#15):退出并返回内核

H=退出码,退出后内核重新加载init.bin。若当前程序是被EXEC_PRESERVE_PROGRAM调起的子程序,则父程序会收到退出码(存于D)。

描述符技巧:dup 与 swap 重定向输入输出

  • dup(#17):把描述符H复制到新编号E,两个描述符共享同一个游标。注意:新编号必须是空的。
  • swap(#24):交换描述符HE的指向,非常适合临时重定向标准输出,用完再换回来,比 dup 更干净。

这两个 API 是编写"输出重定向"类程序(如把命令结果写入文件)的关键工具。

设备控制:ioctl 与 mount

  • ioctl(#7):对驱动执行控制命令。H=驱动描述符,C=命令号,DE=16 位参数。命令含义由具体驱动定义,例如控制串口波特率、键盘 LED 等。
  • mount(#14):挂载磁盘。H=磁盘驱动描述符,D=盘符(A~Z,大小写均可),E=文件系统类型。系统最多支持 26 个磁盘,盘符 A 是系统默认盘。

时间与日期:五个时间系统调用

  • msleep(#18):休眠指定毫秒数,DE=时长(最大 65 秒)。
  • settime(#19)/ gettime(#20):设置/读取毫秒计数器,DE返回当前值。精度依赖硬件实现(可能是 1ms、16ms 等),编程时不要假设固定粒度。
  • setdate(#21)/ getdate(#22):设置/读取系统日期,DE指向 8 字节日期结构(年、月、日、星期、时、分、秒,BCD 格式),结构定义见kernel_headers/sdcc/include/zos_time.h

无 RTC 的平台上,日期相关调用会返回ERR_NOT_IMPLEMENTED(2)。

内存管理:MMU 专属的三个系统调用

仅当内核启用 MMU(内存管理单元)时可用:

  • map(#23):把物理地址HBC映射到虚拟地址DE,地址会自动向下取整到 16KB 页边界。这是访问扩展内存、驱动帧缓冲的核心 API。
  • palloc(#25):分配一页 16KB RAM,返回页索引(存于B)。
  • pfree(#26):释放先前分配的页,只能释放自己分配的内存页。

完整系统调用一览表

编号名称一句话功能
0read从描述符读取数据
1write向描述符写入数据
2open打开文件或驱动
3close关闭描述符
4dstat获取描述符统计信息
5stat获取文件统计信息
6seek移动文件游标
7ioctl对驱动执行控制命令
8mkdir创建目录
9chdir切换当前目录
10curdir获取当前目录
11opendir打开目录
12readdir读取目录条目
13rm删除文件或空目录
14mount挂载磁盘
15exit退出程序
16exec加载并执行程序
17dup复制描述符
18msleep休眠毫秒
19settime设置时间计数器
20gettime读取时间计数器
21setdate设置系统日期
22getdate读取系统日期
23map物理地址映射到虚拟地址
24swap交换两个描述符
25palloc分配一页内存
26pfree释放一页内存

实战:用系统调用实现 echo 命令

来看内核自带的最小示例——romdisk/init/echo.asm,它演示了write的标准用法:

; HL = ARGV,BC = ARGC call strlen ; 计算参数字符串长度,结果在 BC ex de, hl ; DE 指向字符串地址 S_WRITE1(DEV_STDOUT) ; 把字符串写到标准输出 S_WRITE3(DEV_STDOUT, newline, 1) ; 再输出一个换行 xor a ; 返回 0 表示成功 ret

其中S_WRITE1S_WRITE3是头文件kernel_headers/z88dk-z80asm/zos_sys.asm提供的宏,会自动设置调用号并执行RST $08,比手写寄存器更不易出错。如果你用 C 语言(SDCC 4.2+)开发,可以直接调用kernel_headers/sdcc/include/下的zos_vfs.hzos_sys.h中的函数。

错误码速查:调试必备

失败时A返回的错误码定义在include/errors_h.asm,常用几个务必记住:

  • ERR_SUCCESS(0)成功
  • ERR_NOT_IMPLEMENTED(2)目标不支持该功能
  • ERR_NO_SUCH_ENTRY(4)文件/目录不存在
  • ERR_INVALID_PARAMETER(6)参数非法
  • ERR_NO_MORE_ENTRIES(21)目录条目已读完
  • ERR_NO_MORE_MEMORY(22)内存不足

总结

Zeal 8-bit OS 的 27 个系统调用 API 覆盖了 8 位机上开发所需的一切:文件、目录、进程、设备、时间、内存。牢记三条黄金法则即可少踩 90% 的坑:缓冲区不要跨 16KB 页边界、用完立即 close、子程序退出前清干净自己打开的描述符。现在就去kernel_headers/examples/目录下的示例程序里动手试试吧!

【免费下载链接】Zeal-8-bit-OSAn Operating System for Z80 computers, written in assembly项目地址: https://gitcode.com/gh_mirrors/ze/Zeal-8-bit-OS

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询