[ 1] haribote ipl09.nas 引导程序阅读注释。
[ 2] haribote asmhead.nas 从实模式进入保护模式程序阅读注释。
[ 3] haribote dsctbl.c 设置GDT和IDT程序阅读注释。
[ 4] haribote memory.c 内存管理程序阅读注释。
[ 5] haribote int.c 可编程中断控制器(PIC)初始配置程序阅读注释。
[ 6] haribote timer.c 定时器管理程序阅读注释。
[ 7] haribote fifo.c 循环队列管理程序阅读注释。
[ 8] haribote keyboard.c 键盘管理程序阅读注释。
[ 9] haribote mouse.c 鼠标管理程序阅读注释。
[10] haribote graphic.c 由像素点阵转换显卡画面信息程序阅读注释。
[11] haribote sheet.c 窗口画面及显示管理程序阅读注释。
[12] haribote window.c 自制窗口画面信息程序阅读注释。
[13] haribote file.c 文件读取程序阅读注释。
[14] haribote mtask.c 多任务管理程序阅读注释。
[15] haribote console.c 命令行窗口交互管理程序阅读注释。
[16] haribote naskfunc.nas 汇编函数接口程序阅读注释。
[17] haribote bootpack.c 主任务程序代码阅读注释。

篇幅较长,可通过浏览器的搜索功能(Ctrl + f)搜索函数名了解相应函数的实现机制,如 open_console。

[18] baribote系统调用 工程管理及其应用程序阅读注释

此文更博就算是完成了对linux0.11和haribote的粗略阅读啦,从4月算起,约经历了半年时光。想到此刻正是更早岁月中积累的铺垫和推动,曾经努力光阴中的激动仿佛也已赶来。

系统调用apilib
api001.nas
; api001.nas,系统调用号为1的系统调用-打印字符; 告知编译器
; 目标文件格式,本文件中包含 i486 指令;
; 编译成 32位机器码; 本程序原文件名。
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api001.nas"]; 告知编译器_api_putchar标号为全局标识符GLOBAL  _api_putchar; 告知编译器代码段开始
[SECTION .text]; _api_putchar,
; 打印字符c,见内核程序 hrb_api()
_api_putchar:   ; void api_putchar(int c);MOV EDX,1       ; EDX = 系统调用号,见 hrb_api()MOV AL,[ESP+4]  ; AL  = 参数INT 0x40        ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为1的子程序后将执行IRETD返回RET             ; 返回到调用本函数的下一语句处; 涉及特权级变化的 INT 指令相当于
; push ss
; push esp
; pushf
; push cs
; push eip
;
; IRETD 指令为 INT 指令逆操作
api002.nas
; api002.nas,系统调用号为2的系统调用-打印字符串; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api002.nas"]GLOBAL  _api_putstr0[SECTION .text]
; 同 api001.nas; _api_putstr0,
; 打印字符串s,见内核程序 hrb_api()
_api_putstr0:   ; void api_putstr0(char *s);PUSH EBX         ; 备份 EBX MOV  EDX,2       ; EDX=2,系统调用号,见 hrb_api()MOV  EBX,[ESP+8] ; EBX=参数s的值INT  0x40        ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为2的子程序后将执行IRETD返回POP  EBX         ; 恢复 EBX RET              ; 返回到调用本函数的下一语句处
api003.nas
; api003.nas,系统调用号为3的系统调用-打印指定数字符; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api003.nas"]GLOBAL  _api_putstr1[SECTION .text]
; 同 api001.nas; api_putstr1,
; 打印s所指字符序列前l个字符
_api_putstr1: ; void api_putstr1(char *s, int l);PUSH EBX          ; 备份 EBX MOV  EDX,3        ; EDX=3,系统调用号,见 hrb_api()MOV  EBX,[ESP+ 8] ; sMOV  ECX,[ESP+12] ; lINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBX          ; 恢复 EBX RET               ; 返回到调用本函数的下一语句处
api004.nas
; api004.nas,系统调用号为4的系统调用-结束应用程序; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api004.nas"]GLOBAL  _api_end[SECTION .text]
; 同 api001.nas; _api_end,
; 退出应用程序
_api_end:   ; void api_end(void);MOV EDX,4   ; EDX=系统调用号,见 hrb_api()INT 0x40    ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(); _asm_hrb_api 执行EDX=4的子程序后将调用 _asm_end_app 结束引用程序
api005.nas
; api005.nas,系统调用号为5的系统调用-打开运行在用户态的命令行窗口; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api005.nas"]GLOBAL _api_openwin[SECTION .text]
; 同 api001.nas; _api_openwin,
; 打开一个应用程序命令行窗口。
; 窗口画面信息存于buf所指内存段中,窗口宽高分别为xsiz,ysiz,
; col_inv标识窗口是否包含透明色,title所指字符为窗口标题。
_api_openwin:   ; int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);PUSH EDI          ; 依次备份 EDI ESI EBXPUSH ESIPUSH EBXMOV  EDX,5        ; EDX=5,系统调用号,见 hrb_api()MOV  EBX,[ESP+16] ; bufMOV  ESI,[ESP+20] ; xsizMOV  EDI,[ESP+24] ; ysizMOV  EAX,[ESP+28] ; col_invMOV  ECX,[ESP+32] ; titleINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBX          ; 依次恢复 EBX ESI EDI POP  ESIPOP  EDIRET               ; 返回到调用本函数的下一语句处
api006.nas
; api006.nas,系统调用号为6的系统调用-在应用程序窗口中打印字符串; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api006.nas"]GLOBAL  _api_putstrwin[SECTION .text]
; 同 api001.nas; _api_putstrwin,
; 在win所管理的应用程序窗口中(x,y)位置处以色号col打印字符串,字符串长len
_api_putstrwin: ; void api_putstrwin(int win, int x, int y, int col, int len, char *str);PUSH EDI    ; 依次备份 EDI ESI EBP EBXPUSH ESIPUSH EBPPUSH EBXMOV  EDX,6        ; EDX=6,系统调用号,见 hrb_api()MOV  EBX,[ESP+20] ; winMOV  ESI,[ESP+24] ; xMOV  EDI,[ESP+28] ; yMOV  EAX,[ESP+32] ; colMOV  ECX,[ESP+36] ; lenMOV  EBP,[ESP+40] ; strINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBX          ; 依次恢复 EBX EBP ESI EDIPOP  EBPPOP  ESIPOP  EDIRET               ; 返回到调用本函数的下一语句处
api007.nas
; api007.nas,系统调用号为7的系统调用-在应用程序窗口中绘制矩形; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api007.nas"]GLOBAL _api_boxfilwin[SECTION .text]
; 同 api001.nas; _api_boxfilwin,
; 在win所管理窗口[(x0,y0),(x1,y1)]区域绘制色号为col的矩形。
_api_boxfilwin: ; void api_boxfilwin(int win, int x0, int y0, int x1, int y1, int col);PUSH EDI          ; 依次备份 EDI ESI EBP EBXPUSH ESIPUSH EBPPUSH EBXMOV  EDX,7        ; EDX=7,系统调用号,见 hrb_api()MOV  EBX,[ESP+20] ; winMOV  EAX,[ESP+24] ; x0MOV  ECX,[ESP+28] ; y0MOV  ESI,[ESP+32] ; x1MOV  EDI,[ESP+36] ; y1MOV  EBP,[ESP+40] ; colINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBX          ; 依次恢复 EBX EBP ESI EDIPOP  EBPPOP  ESIPOP  EDIRET              ; 返回到调用本函数的下一语句处
api008.nas
; api008.nas,系统调用号为8的系统调用-初始化应用程序内存管理; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api008.nas"]GLOBAL _api_initmalloc[SECTION .text]
; 同 api001.nas; _api_initmalloc,
; 初始化应用程序内存管理
_api_initmalloc:    ; void api_initmalloc(void);PUSH EBXMOV  EDX,8           ; EDX=8,系统调用号,见 hrb_api()MOV  EBX,[CS:0x0020] ; 应用程序头部偏移20h处存储了堆内存在应用程序数据内存段中的偏移地址MOV  EAX,EBXADD  EAX,32*1024     ; 预留32KBMOV  ECX,[CS:0x0000] ; 应用程序头部0x0处存储了应用程序数据段大小SUB  ECX,EAX         ; ECX -= EAX,还剩下的数据段大小;该段内存用作堆内存INT  0x40            ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET                  ; 返回到调用本函数的下一语句处
api009.nas
; api009.nas,系统调用号为9的系统调用-内存分配; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api009.nas"]GLOBAL _api_malloc[SECTION .text]
; 同 api001.nas; _api_malloc,
; 从应用程序堆内存空间分配size大小内存
_api_malloc:    ; char *api_malloc(int size);PUSH EBXMOV  EDX,9           ; EDX=9,系统调用号,见 hrb_api()MOV  EBX,[CS:0x0020] ; 堆内存在数据段中的偏移,即管理; 应用程序堆内存分配的结构体偏移地址,见 _api_initmallocMOV  ECX,[ESP+8]     ; sizeINT  0x40            ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET                  ; 返回到调用本函数的下一语句处
api010.nas
; api0010.nas,系统调用号为10的系统调用-内存释放; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api010.nas"]GLOBAL _api_free[SECTION .text]
; 同 api001.nas; _api_free,
; 释放内存段[addr, addr+size)
_api_free:  ; void api_free(char *addr, int size);PUSH EBXMOV  EDX,10          ; EDX=10,系统调用号,见 hrb_api()MOV  EBX,[CS:0x0020] ; 堆内存在数据段中的偏移,即管理; 应用程序堆内存分配的结构体偏移地址,见 _api_initmallocMOV  EAX,[ESP+ 8]    ; addrMOV  ECX,[ESP+12]    ; sizeINT  0x40            ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET                  ; 返回到调用本函数的下一语句处
api011.nas
; api0011.nas,系统调用号为11的系统调用-绘制一个点; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api011.nas"]GLOBAL _api_point[SECTION .text]
; 同 api001.nas; _api_point,
; 在win所管理窗口的(x,y)处以色号col绘制一个点
_api_point: ; void api_point(int win, int x, int y, int col);PUSH EDIPUSH ESIPUSH EBXMOV  EDX,11       ; EDX=11,系统调用号,见 hrb_api()MOV  EBX,[ESP+16] ; winMOV  ESI,[ESP+20] ; xMOV  EDI,[ESP+24] ; yMOV  EAX,[ESP+28] ; colINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXPOP  ESIPOP  EDIRET               ; 返回到调用本函数的下一语句处
api012.nas
; api0012.nas,系统调用号为12的系统调用-刷新窗口指定区域画面; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api012.nas"]GLOBAL _api_refreshwin[SECTION .text]
; 同 api001.nas; _api_refreshwin,
; 刷新win所管理窗口[(x0,y0),(x1,y1)]区域画面
_api_refreshwin:    ; void api_refreshwin(int win, int x0, int y0, int x1, int y1);PUSH EDIPUSH ESIPUSH EBXMOV  EDX,12       ; EDX=12,系统调用号,见 hrb_api()MOV  EBX,[ESP+16] ; winMOV  EAX,[ESP+20] ; x0MOV  ECX,[ESP+24] ; y0MOV  ESI,[ESP+28] ; x1MOV  EDI,[ESP+32] ; y1INT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXPOP  ESIPOP  EDIRET               ; 返回到调用本函数的下一语句处
api013.nas
; api0013.nas,系统调用号为13的系统调用-绘制线条; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api013.nas"]GLOBAL _api_linewin[SECTION .text]
; 同 api001.nas; _api_linewin,
; 在win所管理窗口中以色号col绘制起于(x0,y0)终于(x1,y1)的线条
_api_linewin:   ; void api_linewin(int win, int x0, int y0, int x1, int y1, int col);PUSH EDIPUSH ESIPUSH EBPPUSH EBXMOV  EDX,13       ; EDX=13,系统调用号,见 hrb_api()MOV  EBX,[ESP+20] ; winMOV  EAX,[ESP+24] ; x0MOV  ECX,[ESP+28] ; y0MOV  ESI,[ESP+32] ; x1MOV  EDI,[ESP+36] ; y1MOV  EBP,[ESP+40] ; colINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXPOP  EBPPOP  ESIPOP  EDIRET              ; 返回到调用本函数的下一语句处
api014.nas
; api0014.nas,系统调用号为14的系统调用-释放管理窗口结构体内存资源; 同 api001.nas[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api014.nas"]GLOBAL _api_closewin[SECTION .text]
; 同 api001.nas; _api_closewin,
; 关闭由win所管理的窗口
_api_closewin:  ; void api_closewin(int win);PUSH EBXMOV  EDX,14      ; EDX=14,系统调用号,见 hrb_api()MOV  EBX,[ESP+8] ; winINT  0x40        ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET              ; 返回到调用本函数的下一语句处
api015.nas
; api0015.nas,系统调用号为15的系统调用-读取当前(任务循环队列)数据; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api015.nas"]GLOBAL _api_getkey[SECTION .text]
; 同 api001.nas; _api_getkey,
; 从当前任务内核循环队列中获取数据;
; mode=0,无数据直接返回;mode=1,等待直到有数据。
_api_getkey:    ; int api_getkey(int mode);MOV EDX,15      ; EDX=15,系统调用号,见 hrb_api()MOV EAX,[ESP+4] ; modeINT 0x40        ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回RET             ; 返回到调用本函数的下一语句处
api016.nas
; api0016.nas,系统调用号为16的系统调用-分配定时器; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api016.nas"]GLOBAL _api_alloctimer[SECTION .text]
; 同 api001.nas; _api_alloctimer,
; 分配(管理)定时器(结构体)。
_api_alloctimer:    ; int api_alloctimer(void);MOV EDX,16  ; EDX=16,系统调用号,见 hrb_api()INT 0x40    ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回RET         ; 返回到调用本函数的下一语句处
api017.nas
; api0017.nas,系统调用号为17的系统调用-初始化定时器; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api017.nas"]GLOBAL  _api_inittimer[SECTION .text]
; 同 api001.nas;_api_inittimer,
; 初始化timer所管理定时器,定时器基数为data.
_api_inittimer: ; void api_inittimer(int timer, int data);PUSH EBXMOV  EDX,17       ; EDX=17,系统调用号,见 hrb_api()MOV  EBX,[ESP+ 8] ; timerMOV  EAX,[ESP+12] ; dataINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET               ; 返回到调用本函数的下一语句处
api018.nas
; api0018.nas,系统调用号为18的系统调用-设置定时器; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api018.nas"]GLOBAL _api_settimer[SECTION .text]
; 同 api001.nas; _api_settimer,
; 设置timer所管理定时器超时时间为time(单位10ms)
_api_settimer:  ; void api_settimer(int timer, int time);PUSH EBXMOV  EDX,18       ; EDX=18,系统调用号,见 hrb_api()MOV  EBX,[ESP+ 8] ; timerMOV  EAX,[ESP+12] ; timeINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET               ; 返回到调用本函数的下一语句处
api019.nas
; api0019.nas,系统调用号为19的系统调用-释放定时器; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api019.nas"]GLOBAL _api_freetimer[SECTION .text]
; 同 api001.nas;_api_freetimer,
; 释放timer所管理定时器。
_api_freetimer: ; void api_freetimer(int timer);PUSH EBXMOV  EDX,19       ; EDX=19,系统调用号,见 hrb_api()MOV  EBX,[ESP+ 8] ; timerINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET               ; 返回到调用本函数的下一语句处
api020.nas
; api0020.nas,系统调用号为20的系统调用-蜂鸣发生器。; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api020.nas"]GLOBAL _api_beep[SECTION .text]
; 同 api001.nas; _api_beep,
; 蜂鸣发生器,tone为声音频率,0时关闭。
_api_beep:  ; void api_beep(int tone);MOV EDX,20      ; EDX=20,系统调用号,见 hrb_api()MOV EAX,[ESP+4] ; tone,声音频率INT 0x40        ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回RET             ; 返回到调用本函数的下一语句处
api021.nas
; api0021.nas,系统调用号为21的系统调用-打开文件。; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api021.nas"]GLOBAL _api_fopen[SECTION .text]
; 同 api001.nas; _api_fopen,
; 打开fname所指文件。
_api_fopen: ; int api_fopen(char *fname);PUSH EBXMOV  EDX,21      ; EDX=21,系统调用号,见 hrb_api()MOV  EBX,[ESP+8] ; fnameINT  0x40        ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET              ; 返回到调用本函数的下一语句处
api022.nas
; api0022.nas,系统调用号为22的系统调用-关闭文件。; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api022.nas"]GLOBAL _api_fclose[SECTION .text]
; 同 api001.nas; _api_fclose,
; 关闭fhandle对应的文件。
_api_fclose:    ; void api_fclose(int fhandle);MOV EDX,22      ; EDX=22,系统调用号,见 hrb_api()MOV EAX,[ESP+4] ; fhandleINT 0x40        ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回RET             ; 返回到调用本函数的下一语句处
api023.nas
; api0023.nas,系统调用号为23的系统调用-设置文件内容位置。; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api023.nas"]GLOBAL _api_fseek[SECTION .text]
; 同 api001.nas; _api_fseek,
; 从fhandle所管理文件的mode标识的位置移动offset。
_api_fseek: ; void api_fseek(int fhandle, int offset, int mode);PUSH EBXMOV  EDX,23       ; EDX=23,系统调用号,见 hrb_api()MOV  EAX,[ESP+8]  ; fhandleMOV  ECX,[ESP+16] ; modeMOV  EBX,[ESP+12] ; offsetINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET               ; 返回到调用本函数的下一语句处
api024.nas
; api0024.nas,系统调用号为24的系统调用-获取文件大小和位置信息。; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api024.nas"]GLOBAL _api_fsize[SECTION .text]
; 同 api001.nas; _api_fsize,
; mode=0,获取文件大小;
; mode=1,文件当前位置;
; mode=2,返回文件当前位置与文件末尾的偏移。
_api_fsize: ; int api_fsize(int fhandle, int mode);MOV EDX,24      ; EDX=24,系统调用号,见 hrb_api()MOV EAX,[ESP+4] ; fhandleMOV ECX,[ESP+8] ; modeINT 0x40        ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回RET             ; 返回到调用本函数的下一语句处
api025.nas
; api0025.nas,系统调用号为25的系统调用-读取文件内容。; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api025.nas"]GLOBAL _api_fread[SECTION .text]
; 同 api001.nas; _api_fread,
; 从fhandle所管理文件最多读取maxsize字节内容到buf所指内存段中。
_api_fread: ; int api_fread(char *buf, int maxsize, int fhandle);PUSH EBXMOV  EDX,25       ; EDX=25,系统调用号,见 hrb_api()MOV  EAX,[ESP+16] ; fhandleMOV  ECX,[ESP+12] ; maxsizeMOV  EBX,[ESP+8]  ; bufINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET               ; 返回到调用本函数的下一语句处
api026.nas
; api0026.nas,系统调用号为26的系统调用-获取窗口命令行数据。; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api026.nas"]GLOBAL _api_cmdline[SECTION .text]
; 同 api001.nas; _api_cmdline,
; 获取命令行数据到buf所指内存段,最多获取maxsize字节。
_api_cmdline:   ; int api_cmdline(char *buf, int maxsize);PUSH EBXMOV  EDX,26       ; EDX=26,系统调用号,见 hrb_api()MOV  ECX,[ESP+12] ; maxsizeMOV  EBX,[ESP+8]  ; bufINT  0x40         ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回POP  EBXRET               ; 返回到调用本函数的下一语句处
api027.nas
; api0027.nas,系统调用号为27的系统调用-获取语言模式。; 同 api001.nas
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
[FILE "api027.nas"]GLOBAL _api_getlang[SECTION .text]
; 同 api001.nas; _api_getlang,
; 获取语言模式。
_api_getlang:   ; int api_getlang(void);MOV EDX,27  ; EDX=26,系统调用号,见 hrb_api()INT 0x40    ; 进入内核执行 _asm_hrb_api,见 init_gdtidt(),; _asm_hrb_api 执行完系统调用号为3的子程序后将执行IRETD返回RET         ; 返回到调用本函数的下一语句处
apilib.h
/* apilib.h,声明 haribote 系统调用 */void api_putchar(int c);
void api_putstr0(char *s);
void api_putstr1(char *s, int l);
void api_end(void);
int api_openwin(char *buf, int xsiz, int ysiz, int col_inv, char *title);
void api_putstrwin(int win, int x, int y, int col, int len, char *str);
void api_boxfilwin(int win, int x0, int y0, int x1, int y1, int col);
void api_initmalloc(void);
char *api_malloc(int size);
void api_free(char *addr, int size);
void api_point(int win, int x, int y, int col);
void api_refreshwin(int win, int x0, int y0, int x1, int y1);
void api_linewin(int win, int x0, int y0, int x1, int y1, int col);
void api_closewin(int win);
int api_getkey(int mode);
int api_alloctimer(void);
void api_inittimer(int timer, int data);
void api_settimer(int timer, int time);
void api_freetimer(int timer);
void api_beep(int tone);
int api_fopen(char *fname);
void api_fclose(int fhandle);
void api_fseek(int fhandle, int offset, int mode);
int api_fsize(int fhandle, int mode);
int api_fread(char *buf, int maxsize, int fhandle);
int api_cmdline(char *buf, int maxsize);
int api_getlang(void);
Makefile
根目录Makefile
# haribote 工程根目录 Makefile
# 此文阅读工程管理文件欲粗略了解工程管理相关,
# 此文对其内所包含的一些工具的具体用法也不知祥。# haribote 工具路径,依赖头文件路径,可根据实际目录更改
TOOLPATH = ../z_tools/
INCPATH  = ../z_tools/haribote/# make 是解析 Makefile 的工具;
# eding.exe  是制作映像文件的工具;
# imgtol.com 是将映像文件写入软盘的工具;
# copy,del 是拷贝和删除命令。
MAKE     = $(TOOLPATH)make.exe -r
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
COPY     = copy
DEL      = del# make 默认解析规则;
# 由于目标 default 不存在,所以该规则下的命令会被无条件执行。
default :$(MAKE) haribote.img# 由目标 default 所在规则触发被解析,
# 当目标 haribote.img 不存在或其先决依赖文件改变时重新生成 haribote.img
haribote.img : haribote/ipl09.bin haribote/haribote.sys Makefile \a/a.hrb hello3/hello3.hrb hello4/hello4.hrb hello5/hello5.hrb \winhelo/winhelo.hrb winhelo2/winhelo2.hrb winhelo3/winhelo3.hrb \star1/star1.hrb stars/stars.hrb stars2/stars2.hrb \lines/lines.hrb walk/walk.hrb noodle/noodle.hrb \beepdown/beepdown.hrb color/color.hrb color2/color2.hrb \sosu/sosu.hrb sosu2/sosu2.hrb sosu3/sosu3.hrb \type/type.hrb iroha/iroha.hrb chklang/chklang.hrb \notrec/notrec.hrb bball/bball.hrb invader/invader.hrb \calc/calc.hrb tview/tview.hrb mmlplay/mmlplay.hrb gview/gview.hrb$(EDIMG)   imgin:../z_tools/fdimg0at.tek \wbinimg src:haribote/ipl09.bin len:512 from:0 to:0 \copy from:haribote/haribote.sys to:@: \copy from:ipl09.nas to:@: \copy from:make.bat to:@: \copy from:a/a.hrb to:@: \copy from:hello3/hello3.hrb to:@: \copy from:hello4/hello4.hrb to:@: \copy from:hello5/hello5.hrb to:@: \copy from:winhelo/winhelo.hrb to:@: \copy from:winhelo2/winhelo2.hrb to:@: \copy from:winhelo3/winhelo3.hrb to:@: \copy from:star1/star1.hrb to:@: \copy from:stars/stars.hrb to:@: \copy from:stars2/stars2.hrb to:@: \copy from:lines/lines.hrb to:@: \copy from:walk/walk.hrb to:@: \copy from:noodle/noodle.hrb to:@: \copy from:beepdown/beepdown.hrb to:@: \copy from:color/color.hrb to:@: \copy from:color2/color2.hrb to:@: \copy from:sosu/sosu.hrb to:@: \copy from:sosu2/sosu2.hrb to:@: \copy from:sosu3/sosu3.hrb to:@: \copy from:type/type.hrb to:@: \copy from:iroha/iroha.hrb to:@: \copy from:chklang/chklang.hrb to:@: \copy from:euc.txt to:@: \copy from:notrec/notrec.hrb to:@: \copy from:bball/bball.hrb to:@: \copy from:invader/invader.hrb to:@: \copy from:calc/calc.hrb to:@: \copy from:tview/tview.hrb to:@: \copy from:mmlplay/mmlplay.hrb to:@: \copy from:mmldata/kirakira.mml to:@: \copy from:mmldata/fujisan.mml to:@: \copy from:mmldata/daigo.mml to:@: \copy from:mmldata/daiku.mml to:@: \copy from:gview/gview.hrb to:@: \copy from:pictdata/fujisan.jpg to:@: \copy from:pictdata/night.bmp to:@: \copy from:nihongo/nihongo.fnt to:@: \imgout:haribote.img# make run
# 由于目标 run 不存在,所以该规则下的规则会被无条件执行。
# [1] 更新映像文件 haribote.img;
# [2] 将更新的映像文件拷贝到虚拟机 qemu.exe 同目录下的 fdimage0.bin中;
# [3] 启动虚拟机 qemu.exe 加载 fdimage0.bin运行。
run :$(MAKE) haribote.img$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin$(MAKE) -C ../z_tools/qemu# make install
# 由于目标 install 不存在,所以该规则下的命令会被无条件还行。
# [1] 更新映像文件 haribote.img;
# [2] 将更新的影响文件写入软盘中。
install :$(MAKE) haribote.img$(IMGTOL) w a: haribote.img# make full
# 由于目标 full 不存在,所以该规则下的命令将会被无条件执行。
# 根据最新工程源文件更新硬盘映像文件 haribote.img。
full :$(MAKE) -C haribote$(MAKE) -C apilib$(MAKE) -C a$(MAKE) -C hello3$(MAKE) -C hello4$(MAKE) -C hello5$(MAKE) -C winhelo$(MAKE) -C winhelo2$(MAKE) -C winhelo3$(MAKE) -C star1$(MAKE) -C stars$(MAKE) -C stars2$(MAKE) -C lines$(MAKE) -C walk$(MAKE) -C noodle$(MAKE) -C beepdown$(MAKE) -C color$(MAKE) -C color2$(MAKE) -C sosu$(MAKE) -C sosu2$(MAKE) -C sosu3$(MAKE) -C type$(MAKE) -C iroha$(MAKE) -C chklang$(MAKE) -C notrec$(MAKE) -C bball$(MAKE) -C invader$(MAKE) -C calc$(MAKE) -C tview$(MAKE) -C mmlplay$(MAKE) -C gview$(MAKE) haribote.img# make run_full
# 由于目标 run_full 不存在,所以规则下的命令将会无条件执行。
# [1] 根据工程最新源文件更新映像文件 haribote.img;
# [2] 将更新映像文件拷贝到虚拟机 qemu.ext 同目录下的 fdimage0.bin中;
# [3] 启动虚拟机 qemu.exe 加载 fdimage0.bin 运行。
run_full :$(MAKE) full$(COPY) haribote.img ..\z_tools\qemu\fdimage0.bin$(MAKE) -C ../z_tools/qemu# make install_full
# 由于目标 install_full 不存在,所以该规则下的命令将会被无条件执行。
# [1] 根据工程最新源文件更新映像文件 haribote.img;
# [2] 将更新的影响文件写入软盘中。
install_full :$(MAKE) full$(IMGTOL) w a: haribote.img# make run_os
# 由于目标 run_os 不存在,所以该规则下的命令将会被无条件执行。
# [1] 根据 haribote OS 最新源码更新映像文件 haribote.img;
# [2] 启动虚拟机 qemu.exe 加载映像文件运行。
run_os :$(MAKE) -C haribote$(MAKE) runclean :# make src_only
# 由于目标 src_only 不存在,所以该规则下的命令会被无条件执行。
# 删除映像文件 haribote.img。
src_only :$(MAKE) clean-$(DEL) haribote.img# make clean_full
# 由于目标 clean_full 不存在,所以该规则下的命令会被无条件执行。
# 在工程各子目录下执行 make clean 命令。
clean_full :$(MAKE) -C haribote     clean$(MAKE) -C apilib       clean$(MAKE) -C a            clean$(MAKE) -C hello3       clean$(MAKE) -C hello4       clean$(MAKE) -C hello5       clean$(MAKE) -C winhelo      clean$(MAKE) -C winhelo2     clean$(MAKE) -C winhelo3     clean$(MAKE) -C star1        clean$(MAKE) -C stars        clean$(MAKE) -C stars2       clean$(MAKE) -C lines        clean$(MAKE) -C walk         clean$(MAKE) -C noodle       clean$(MAKE) -C beepdown     clean$(MAKE) -C color        clean$(MAKE) -C color2       clean$(MAKE) -C sosu         clean$(MAKE) -C sosu2        clean$(MAKE) -C sosu3        clean$(MAKE) -C type         clean$(MAKE) -C iroha        clean$(MAKE) -C chklang      clean$(MAKE) -C notrec       clean$(MAKE) -C bball        clean$(MAKE) -C invader      clean$(MAKE) -C calc         clean$(MAKE) -C tview        clean$(MAKE) -C mmlplay      clean$(MAKE) -C gview        clean# make src_only_full
# 由于目标 src_only_full 不存在,所以该规则下的命令将会被执行。
# [1] 在工程各子目录下执行 make src_only;
# [2] 删除映像文件 haribote.img。
# 即只保留源文件。
src_only_full :$(MAKE) -C haribote     src_only$(MAKE) -C apilib       src_only$(MAKE) -C a            src_only$(MAKE) -C hello3       src_only$(MAKE) -C hello4       src_only$(MAKE) -C hello5       src_only$(MAKE) -C winhelo      src_only$(MAKE) -C winhelo2     src_only$(MAKE) -C winhelo3     src_only$(MAKE) -C star1        src_only$(MAKE) -C stars        src_only$(MAKE) -C stars2       src_only$(MAKE) -C lines        src_only$(MAKE) -C walk         src_only$(MAKE) -C noodle       src_only$(MAKE) -C beepdown     src_only$(MAKE) -C color        src_only$(MAKE) -C color2       src_only$(MAKE) -C sosu         src_only$(MAKE) -C sosu2        src_only$(MAKE) -C sosu3        src_only$(MAKE) -C type         src_only$(MAKE) -C iroha        src_only$(MAKE) -C chklang      src_only$(MAKE) -C notrec       src_only$(MAKE) -C bball        src_only$(MAKE) -C invader      src_only$(MAKE) -C calc         src_only$(MAKE) -C tview        src_only$(MAKE) -C mmlplay      src_only$(MAKE) -C gview        src_only-$(DEL) haribote.img# make refresh
# 由于目标 refresh 不存在,所以该规则下的命令会被无条件执行。
# [1] 根据工程最新源文件生成映像文件;
# [2-3] 删除各工程目录下的输出和映像文件。
refresh :$(MAKE) full$(MAKE) clean_full-$(DEL) haribote.img
haribote/Makefile
# 将目标文件集赋给变量 OBJS_BOOTPACK
OBJS_BOOTPACK = bootpack.obj naskfunc.obj hankaku.obj graphic.obj dsctbl.obj \int.obj fifo.obj keyboard.obj mouse.obj memory.obj sheet.obj timer.obj \mtask.obj window.obj console.obj file.obj tek.obj# haribote 工具路径,依赖头文件路径,可根据实际目录更改
TOOLPATH = ../../z_tools/
INCPATH  = ../../z_tools/haribote/# make 是解析 Makefile 的工具;
# nask.exe 是汇编编译器;
# ccl.exe 是C程序编译器;
# gas2nask.exe,obj2bim.exe,bin2obj.exe,bim2hrb.exe 是目标文件格式转换工具;
# makefont.exe 是将 hankaku.txt 文件转换为字库文件的工具;
# haribote.rul 相当于链接脚本;
# eding.exe  是制作映像文件的工具;
# imgtol.com 是将映像文件写入软盘的工具;
# golib00.exe 库文件制作工具;
# copy,del 是拷贝和删除命令。
MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
MAKEFONT = $(TOOLPATH)makefont.exe
BIN2OBJ  = $(TOOLPATH)bin2obj.exe
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
RULEFILE = ../haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
GOLIB    = $(TOOLPATH)golib00.exe
COPY     = copy
DEL      = del# make 默认解析规则,
# 由于目标 default 不存在,所以该规则下的命令将会被无条件执行。
# [1] 解析目标 ipl09.bin 所在规则;
# [2] 解析目标 haribote.sys 所在规则。
default :$(MAKE) ipl09.bin$(MAKE) haribote.sys# 由目标 default 所在规则触发解析。
# 当目标 ipl09.bin 不存在或其先决依赖文件 ipl09.nas Makefile 改变时,
# 该规则下的命令将会被执行: 将汇编引导程序 ipl09.nas 编译成目标文件
# ipl09.bin。
ipl09.bin : ipl09.nas Makefile$(NASK) ipl09.nas ipl09.bin ipl09.lst# 由目标 haribote.sys 所在规则触发解析
# 当目标 asmhead.bin 不存在 或其先决依赖文件 asmhead.nas Makefile 改变时
# 该规则下的命令将被执行, 将汇编程序 asmhead.nas 编译为 asmhead.bin 。
asmhead.bin : asmhead.nas Makefile$(NASK) asmhead.nas asmhead.bin asmhead.lst# 由目标 hankaku.obj 所在规则触发解析
# 当目标 hankaku.bin 不存在或其先决依赖条件 hankaku.txt Makefile 改变时,
# 该规则下的命令会被执行: 将文件 hankaku.txt 转换为 hankaku.bin 。
hankaku.bin : hankaku.txt Makefile$(MAKEFONT) hankaku.txt hankaku.bin# 由目标 bootpack.bim 所在规则触发解析
# 当目标 hankaku.obj 不存在或其先决依赖条件 hankaku.bin Makefile 改变时,
# 该规则下的命令会被执行: 将目标文件 hankaku.bin 转换为 hankaku.obj,
# 起始地址为 _hankaku 。
hankaku.obj : hankaku.bin Makefile$(BIN2OBJ) hankaku.bin hankaku.obj _hankaku# 由目标 bootpack.hrb 所在规则触发解析
# 当目标 bootpack.bim 不存在或其先决依赖条件 $(OBJS_BOOTPACK) Makefile 改变时,
#该改规则下的命令会被执行: 将目标文件 $(OBJS_BOOTPACK) 链接到 bootpack.bim 中。
#
# 该规则会引发目标 $(OBJS_BOOTPACK) 所在规则的解析(匹配第3个隐式规则)。
bootpack.bim : $(OBJS_BOOTPACK) Makefile$(OBJ2BIM) @$(RULEFILE) out:bootpack.bim stack:3136k map:bootpack.map \$(OBJS_BOOTPACK)
# 3MB+64KB=3136KB# 由目标 haribote.hrb 所在规则触发解析
# 当目标 bootpack.hrb 不存在或其先决依赖条件 bootpack.bim Makefile 改变时,
# 该规则下的命令会被执行: 将目标文件 bootpack.bin 转换为 bootpack.hrb。
#
# 该规则会引发目标 bootpack.bim 所在规则的解析。
bootpack.hrb : bootpack.bim Makefile$(BIM2HRB) bootpack.bim bootpack.hrb 0# 由目标 default 所在规则触发解析。
# 当目标 haribote.sys 不存在或其先决依赖文件 asmhead.bin bootpack.hrb Makefile
# 改变时,该规则下的命令将会被执行: 将 asmhead.bin 和 bootpack.hrb 拷贝到 haribote.sys
# 文件中。
#
# 该规则会检查目标 asmhead.bin 和 bootpack.hrb 所在规则的检查。
haribote.sys : asmhead.bin bootpack.hrb Makefilecopy /B asmhead.bin+bootpack.hrb haribote.sys# 以下是3个隐式规则,自动变量 $* 代表目标命名中 % 之前部分命名;
# 第3个隐式隐式规则由 bootpack.bim 目标所在规则匹配并被解析,遂
# 匹配第2个隐式规则并被解析,再匹配第1个隐式规则并被解析。
#
# 根据与 .gas 文件同名的 .c文件生成 .gas文件,
# 若相应的 .gas 文件不存在或 .c文件有变时。
#
# 如
# 由第2条隐式规则匹配并形成实际规则
# bootpack.gas : bootpack.c Makefile
#   $(CC1) -o $*.gas $*.c
# 该规则生成 bootpack.gas, 第2条规则再生成 bootpack.nas,
# 第3条规则再生成 bootpack.obj,这样就得到了 $(OBJS_BOOTPACK) 中的目标文件,
# 从而生成目标 bootpack.bim
%.gas : %.c bootpack.h Makefile$(CC1) -o $*.gas $*.c
#
# 根据与 .nas 文件同名的 .gas文件生成 .nas文件,
# 若相应的 .nas 文件不存在或 .gas文件有变时。
#
# 如
# 由第3条隐式规则匹配并形成实际规则
# bootpack.nas : bootpack.gas Makefile
#   $(GAS2NASK) $*.gas $*.nas
# 该规则会匹配第1条隐式规则并形成实际的规则而被解析。
%.nas : %.gas Makefile$(GAS2NASK) $*.gas $*.nas
#
# 根据与 $(OBJS_BOOTPACK) 中 .obj 文件同名的 .nas 文件生成 .obj 文件,
# 当相应 .obj 文件不存在或 %.nas 有变时。
#
# 如
# bootpack.obj : bootpack.nas Makefile
#   $(NASK) $*.nas $*.obj $*.lst
#
# 该规则会匹配第2条隐式规则并形成实际的规则而被解析。
%.obj : %.nas Makefile$(NASK) $*.nas $*.obj $*.lst
# 举个简单例子感受下吧。
# 文件 main.c Makefile
#
# Makefile 内容如下
# all: main.out
#
# main.out : main.o
#     gcc main.o -o main.out
#
# main.o : main.c
#
# %.o: %.c
#     gcc -c -o $*.o $*.c
#
# 在 Makefile 同目录下执行 Make
# gcc -c -o main.o main.c
# gcc main.o -o main.out# make clean
# 由于目标 clean 不存在,所以该规则下的命令会被无条件执行。
# 删除由 make 解析本 Makefile 时所生成的文件。
clean :-$(DEL) asmhead.bin-$(DEL) hankaku.bin-$(DEL) *.lst-$(DEL) *.obj-$(DEL) *.map-$(DEL) *.bim-$(DEL) *.hrb# make src_only
# 由于目标 src_only 不存在,所以该规则下的命令会被无条件执行。
# [1] 清理由 make 解析本 Makefile 时所生成的文件;
# [2] 删除引导程序目标文件;
# [3] 删除内核目标文件 haribote.sys。
# 即只保留源文件。
src_only :$(MAKE) clean-$(DEL) ipl09.bin-$(DEL) haribote.sys
apilib/Makefile
# haribote 系统调用库 Makefile# 将目标文件集赋给变量 OBJS_API
OBJS_API =  api001.obj api002.obj api003.obj api004.obj api005.obj api006.obj \api007.obj api008.obj api009.obj api010.obj api011.obj api012.obj \api013.obj api014.obj api015.obj api016.obj api017.obj api018.obj \api019.obj api020.obj api021.obj api022.obj api023.obj api024.obj \api025.obj api026.obj api027.obj alloca.obj# haribote 工具路径,依赖头文件路径,可根据实际目录更改
TOOLPATH = ../../z_tools/
INCPATH  = ../../z_tools/haribote/
# make 是解析 Makefile 的工具;
# nask.exe 是汇编编译器;
# ccl.exe 是C程序编译器;
# gas2nask.exe,obj2bim.exe,bin2obj.exe,bim2hrb.exe 是目标文件格式转换工具;
# makefont.exe 是将 hankaku.txt 文件转换为字库文件的工具;
# haribote.rul 相当于链接脚本;
# eding.exe  是制作映像文件的工具;
# imgtol.com 是将映像文件写入软盘的工具;
# golib00.exe 库文件制作工具;
# copy,del 是拷贝和删除命令。
MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
MAKEFONT = $(TOOLPATH)makefont.exe
BIN2OBJ  = $(TOOLPATH)bin2obj.exe
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
RULEFILE = ../haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
GOLIB    = $(TOOLPATH)golib00.exe
COPY     = copy
DEL      = del# make 默认解析规则,
# 由于目标 default 不存在,所以该规则下的命令将会被无条件执行。
# 即解析目标 apilib.lib 所在规则。
default :$(MAKE) apilib.lib# make apilib.lib
# apilib.lib 不存在或先决依赖文件 Makefile $(OBJS_API) 有改变时,
# 该规则下的命令将会被执行, 即将 $(OBJS_API) 目标文件打包到库文
# 件 apilib.lib 中。该命令将会匹配后续隐式规则。
apilib.lib : Makefile $(OBJS_API)$(GOLIB) $(OBJS_API) out:apilib.lib# 以下是隐式规则,自动变量 $* 代表目标命名中 % 之前部分命名;
# 该隐式规则由 apilib.lib 目标所在规则匹配并被解析, 即根据
# 与 $(OBJS_API) 中 .obj 文件同名的 .nas 文件生成 .obj 文件。
%.obj : %.nas Makefile$(NASK) $*.nas $*.obj $*.lst# make clean
# 由于目标 clean 不存在,所以改规则下的命令会被无条件执行,
# 即删除由 make 解析本 Makefile 时生成的中间文件。
clean :-$(DEL) *.lst-$(DEL) *.obj# make src_only
# 由于目标 src_only 不存在,所以该规则下的命令会被无条件执行,
# 即删除由 make 解析本 Makefile 时生成的所有文件,,只保留源文件。
src_only :$(MAKE) clean-$(DEL) apilib.lib
app_make.txt
# app_make.txt,haribote 应用程序 Makefile 公用 Makefile 部分,
# 会被各应用程序包含到其 Makefile 中。# haribote app 工具路径,依赖头文件路径,库路径,操作系统路径,
# 可根据实际目录更改
TOOLPATH = ../../z_tools/
INCPATH  = ../../z_tools/haribote/
APILIBPATH   = ../apilib/
HARIBOTEPATH = ../haribote/# make 是解析 Makefile 的工具;
# nask.exe 是汇编编译器;
# ccl.exe 是C程序编译器;
# gas2nask.exe,obj2bim.exe,bin2obj.exe,bim2hrb.exe 是目标文件格式转换工具;
# makefont.exe 是将 hankaku.txt 文件转换为字库文件的工具;
# haribote.rul 相当于链接脚本;
# eding.exe  是制作映像文件的工具;
# imgtol.com 是将映像文件写入软盘的工具;
# golib00.exe 库文件制作工具;
# copy,del 是拷贝和删除命令。
MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -I../ -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
MAKEFONT = $(TOOLPATH)makefont.exe
BIN2OBJ  = $(TOOLPATH)bin2obj.exe
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
BIM2BIN  = $(TOOLPATH)bim2bin.exe
RULEFILE = ../haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
GOLIB    = $(TOOLPATH)golib00.exe
COPY     = copy
DEL      = del# make 默认解析规则,
# 由于目标 default 不存在,所以该规则下的命令将会被无条件执行。
# 即解析目标 $(APP).hrb 所在规则。变量 APP 在应用程序 Makefile
# 中被定义,标识应用程序名。结合应用程序 harib27f/a 看下吧。
default :$(MAKE) $(APP).hrb# 该规则由目标 default 所在规则间接触发解析,
# 若 $(APP).bim 不存在或其先决依赖文件有变时,该规则下的命令被执行,即生成
# 目标文件 $(APP).bim, 从这里可以看出为应用程序栈设置了1Kb。
$(APP).bim : $(APP).obj $(APILIBPATH)apilib.lib Makefile ../app_make.txt$(OBJ2BIM) @$(RULEFILE) out:$(APP).bim map:$(APP).map stack:$(STACK) \$(APP).obj $(APILIBPATH)apilib.lib# make haribote.img 或被 make run 触发解析,
# 即将可执行应用程序 haribote 内核,$(APP).hrb 以及字库文件 nihong.fnt 加入映像文件中。
haribote.img : ../haribote/ipl09.bin ../haribote/haribote.sys $(APP).hrb \Makefile ../app_make.txt$(EDIMG)   imgin:../../z_tools/fdimg0at.tek \wbinimg src:../haribote/ipl09.bin len:512 from:0 to:0 \copy from:../haribote/haribote.sys to:@: \copy from:$(APP).hrb to:@: \copy from:../nihongo/nihongo.fnt to:@: \imgout:haribote.img# 以下是5条隐式规则,根据应用程序 Makefile,第5条隐式规则
# 将会被 default 目标所在规则匹配并被解析,随之匹配第4条
# 隐式规则,然后触发目标 $(APP).bim 所在规则被解析, 该规
# 则的 .obj 先决依赖文件将会匹配第3条隐式规则,第3条隐式
# 规则将会匹配第2条隐式规则, 第2条隐式规则将会匹配第1条
# 隐式规则。即由完成由源文件 $(APP).C 生成可执行文件 $(APP).hrb。
%.gas : %.c ../apilib.h Makefile ../app_make.txt$(CC1) -o $*.gas $*.c%.nas : %.gas Makefile ../app_make.txt$(GAS2NASK) $*.gas $*.nas%.obj : %.nas Makefile ../app_make.txt$(NASK) $*.nas $*.obj $*.lst%.org : %.bim Makefile ../app_make.txt$(BIM2HRB) $*.bim $*.org $(MALLOC)%.hrb : %.org Makefile ../app_make.txt$(BIM2BIN) -osacmp in:$*.org out:$*.hrb# make run
# 由于目标 run 不存在,所以该规则下的命令将会被无条件执行,
# [1] 即制作额外包含可执行应用程序 $(APP).hrb,字库的映像文件;
# [2] 将映像文件拷贝到虚拟机 qemu.exe 同目录的 fdimage0.bin 中;
# [3] 启动虚拟机 qemu.exe 加载 fdimage0.bin 运行。
run :$(MAKE) haribote.img$(COPY) haribote.img ..\..\z_tools\qemu\fdimage0.bin$(MAKE) -C ../../z_tools/qemu# make full
# 由于目标 full 不存在,所以该规则下的命令将会被无条件执行,
# [1] 到库文件所在目录执行 make 生成系统调用库文件;
# [2] 生成可执行应用程序 $(APP).hrb
full :$(MAKE) -C $(APILIBPATH)$(MAKE) $(APP).hrb# make run_full
# 由于目标 run_full 不存在,所以该规则下的命令将会被无条件执行,
# [1] 到库文件所在目录执行 make 生成系统调用库文件;
# [2] 到操作系统目录下执行 make 命令生成操作系统内核文件;
# [3] 在虚拟机 qemu.exe 中运行操作系统。
run_full :$(MAKE) -C $(APILIBPATH)$(MAKE) -C ../haribote$(MAKE) run# make clean
# 由于目标 clean 不存在,所以该规则下的命令将会被无条件执行,
# 即删除由 make 解析本 Makefile 时生成的中间文件。
clean :-$(DEL) *.lst-$(DEL) *.obj-$(DEL) *.map-$(DEL) *.bim-$(DEL) *.org-$(DEL) haribote.img# make src_only
# 由于目标 src_only 不存在,所以该规则下的命令将会被无条件执行,
# 即删除由 make 解析本 Makefile 时生成所有文件,只保留源文件。
src_only :$(MAKE) clean-$(DEL) $(APP).hrb
a/Makefile
# 应用程序 a.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = a
STACK    = 1k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处,
# 看看上层目录 app_make.txt 的内容吧。
include ../app_make.txt# ../app_make.txt 也会生成 $(APP).hrb,会不会冲突呢
$(APP).hrb : $(APP).org Makefile$(COPY) $(APP).org $(APP).hrb
bball/Makefile
# 应用程序 bball.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = bball
STACK    = 52k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
beepdown/Makefile
# 应用程序 beepdown.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = beepdown
STACK    = 1k
MALLOC   = 40k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
calc/Makefile
# 应用程序 calc.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = calc
STACK    = 4k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
chklang/Makefile
# 应用程序 chklang.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = chklang
STACK    = 1k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
color/Makefile
# 应用程序 color.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = color
STACK    = 1k
MALLOC   = 56k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
color2/Makefile
# 应用程序 color2.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = color2
STACK    = 1k
MALLOC   = 56k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
gview/Makefile
# 应用程序 gview Makefile, 因为有多个源文件,所以没有使用../app_make.txt# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = gview
STACK    = 4480k
MALLOC   = 0k# haribote 工具路径,依赖头文件路径,内核程序路径,可根据实际目录更改
TOOLPATH = ../../z_tools/
INCPATH  = ../../z_tools/haribote/
APILIBPATH   = ../apilib/
HARIBOTEPATH = ../haribote/# make 是解析 Makefile 的工具;
# nask.exe 是汇编编译器;
# ccl.exe 是C程序编译器;
# gas2nask.exe,obj2bim.exe,bin2obj.exe,bim2hrb.exe 是目标文件格式转换工具;
# makefont.exe 是将 hankaku.txt 文件转换为字库文件的工具;
# haribote.rul 相当于链接脚本;
# eding.exe  是制作映像文件的工具;
# imgtol.com 是将映像文件写入软盘的工具;
# golib00.exe 库文件制作工具;
# copy,del 是拷贝和删除命令。
MAKE     = $(TOOLPATH)make.exe -r
NASK     = $(TOOLPATH)nask.exe
CC1      = $(TOOLPATH)cc1.exe -I$(INCPATH) -I../ -Os -Wall -quiet
GAS2NASK = $(TOOLPATH)gas2nask.exe -a
OBJ2BIM  = $(TOOLPATH)obj2bim.exe
MAKEFONT = $(TOOLPATH)makefont.exe
BIN2OBJ  = $(TOOLPATH)bin2obj.exe
BIM2HRB  = $(TOOLPATH)bim2hrb.exe
BIM2BIN  = $(TOOLPATH)bim2bin.exe
RULEFILE = ../haribote.rul
EDIMG    = $(TOOLPATH)edimg.exe
IMGTOL   = $(TOOLPATH)imgtol.com
GOLIB    = $(TOOLPATH)golib00.exe
COPY     = copy
DEL      = del# make 默认解析规则,
# 即解析 $(APP).hrb 目标所在规则
default :$(MAKE) $(APP).hrb# 由第4条隐式规则触发被解析,即依赖 $(APP).obj 生成 $(APP).bim,
# 且触发目标为 $(APP).obj 规则的解析,即匹配第3条隐式规则被解析,即触发生成
# $(APP).obj bmp.obj jpeg.obj。
$(APP).bim : $(APP).obj bmp.obj jpeg.obj $(APILIBPATH)apilib.lib Makefile$(OBJ2BIM) @$(RULEFILE) out:$(APP).bim map:$(APP).map stack:$(STACK) \$(APP).obj jpeg.obj bmp.obj $(APILIBPATH)apilib.lib# 由 make run 触发解析,将应用程序加入映像文件中
haribote.img : ../haribote/ipl20.bin ../haribote/haribote.sys $(APP).hrb \Makefile$(EDIMG)   imgin:../../z_tools/fdimg0at.tek \wbinimg src:../haribote/ipl20.bin len:512 from:0 to:0 \copy from:../haribote/haribote.sys to:@: \copy from:$(APP).hrb to:@: \copy from:../nihongo/nihongo.fnt to:@: \imgout:haribote.img# 以下是5条隐式规则,自动变量 $* 代表目标命名中 % 之前部分命名;
# 第5条隐式规则由目标 default 下的命令 make $(APP).hrb 触发解析
# 即触发解析规则
# $(APP).hrb : $(APP).org Makefile
#   $(BIM2BIN) -osacmp in:$*.org out:$*.hrb
# 第5条规则触发解析第4条规则,第4条规则触发解析 $(APP).bim 目标所
# 在规则的解析,该规则将触发第3条隐式规则的解析,遂触发第2,1条规则
# 被解析,从而完成由源文件 $(APP).C 生成可执行程序 $(APP).hrb。
#
# 先决依赖文件后缀为 .gas 的规则将触发该规则被解析,即根据C源文件
# 生成同名的 .gas 文件。
%.gas : %.c ../apilib.h Makefile$(CC1) -o $*.gas $*.c
# 先决依赖文件后缀为 .nas 的规则将触发该规则被解析,即根据 .gas 文
# 件生成同名的 .nas 文件。
%.nas : %.gas Makefile$(GAS2NASK) $*.gas $*.nas
# 先决依赖文件后缀为 .obj 的规则将触发该规则被解析,即根据 .nas 文
# 件生成同名的 .obj 文件。
%.obj : %.nas Makefile$(NASK) $*.nas $*.obj $*.lst
# 先决依赖文件后缀为 .org 的规则将触发该规则被解析,即根据 .bim 文
# 件生成同名的 .org 文件。
%.org : %.bim Makefile$(BIM2HRB) $*.bim $*.org $(MALLOC)
# 先决依赖文件后缀为 .hrb 的规则将触发该规则被解析,即根据 .org 文
# 件生成同名的 .hrb 文件。
%.hrb : %.org Makefile$(BIM2BIN) -osacmp in:$*.org out:$*.hrb# make run
# 由于目标 run 不存在,所以该规则下的命令会被无条件执行
# [1] 生成包含内核和本可执行应用程序映像文件;
# [2] 将映像文件拷贝到虚拟机同目录的 fdimage0.bin 中;
# [3] 启动虚拟机 qemu.exe 加载 fdimage0.bin 运行。
run :$(MAKE) haribote.img$(COPY) haribote.img ..\..\z_tools\qemu\fdimage0.bin$(MAKE) -C ../../z_tools/qemu# make full
# 由于目标 full 不存在,所以该规则下的命令会被无条件执行
# [1] 重新生成系统调用库;
# [2] 重新生成本可执行应用程序。
full :$(MAKE) -C $(APILIBPATH)$(MAKE) $(APP).hrb# make run_full
# 由于目标 run_full 不存在,所以该规则下的命令会被无条件执行
# [1] 重新生成系统调用库;
# [2] 重新生成内核文件;
# [3] 启动虚拟机 qemu.exe 运行程序。
run_full :$(MAKE) -C $(APILIBPATH)$(MAKE) -C ../haribote$(MAKE) run# make clean
# 由于目标 clean 不存在,所以该规则下的命令会被无条件执行
# 删除由 make 解析本 Makefile 生成的中间文件。
clean :-$(DEL) *.lst-$(DEL) gview.obj-$(DEL) jpeg.obj-$(DEL) *.map-$(DEL) *.bim-$(DEL) *.org-$(DEL) haribote.img# make src_only
# 由于目标 src_only 不存在,所以该规则下的命令会被无条件执行
# 删除由 make 解析本 Makefile 生成的所有文件,即只保留源文件。
src_only :$(MAKE) clean-$(DEL) $(APP).hrb
hello3/Makefile
# 应用程序 hello3.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = hello3
STACK    = 1k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
hello4/Makefile
# 应用程序 hello4.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = hello4
STACK    = 1k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt# ../app_make.txt 也会生成 $(APP).hrb,会不会冲突呢
$(APP).hrb : $(APP).org Makefile$(COPY) $(APP).org $(APP).hrb
hello5/Makefile
# 应用程序 hello5.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = hello5
STACK    = 1k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt# ../app_make.txt 也会生成 $(APP).hrb,会不会冲突呢
$(APP).hrb : $(APP).org Makefile$(COPY) $(APP).org $(APP).hrb
invader/Makefile
# 应用程序 invader.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = invader
STACK    = 90k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
iroha/Makefile
# 应用程序 iroha.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = iroha
STACK    = 1k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt# ../app_make.txt 也会生成 $(APP).hrb,会不会冲突呢
$(APP).hrb : $(APP).org Makefile$(COPY) $(APP).org $(APP).hrb
lines/Makefile
# 应用程序 lines.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = lines
STACK    = 1k
MALLOC   = 48k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
mmlplay/Makefile
# 应用程序 mmlplay.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = mmlplay
STACK    = 132k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
noodle/Makefile
# 应用程序 noodle.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = noodle
STACK    = 1k
MALLOC   = 40k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
notrec/Makefile
# 应用程序 notrec.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = notrec
STACK    = 11k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
notrec/Makefile
# 应用程序 sosu.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = sosu
STACK    = 2k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
sosu/Makefile
# 应用程序 sosu.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = sosu
STACK    = 2k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
sosu2/Makefile
# 应用程序 sosu2.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = sosu2
STACK    = 11k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
sosu3/Makefile
# 应用程序 sosu3.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = sosu3
STACK    = 1k
MALLOC   = 42k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
star1/Makefile
# 应用程序 star1.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = star1
STACK    = 1k
MALLOC   = 47k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
stars/Makefile
# 应用程序 stars.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = stars
STACK    = 1k
MALLOC   = 47k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
stars2/Makefile
# 应用程序 stars2.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = stars2
STACK    = 1k
MALLOC   = 47k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
tview/Makefile
# 应用程序 tview.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = tview
STACK    = 1024k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
type/Makefile
# 应用程序 type.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = type
STACK    = 1k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
walk/Makefile
# 应用程序 walk.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = walk
STACK    = 1k
MALLOC   = 48k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
winhelo/Makefile
# 应用程序 winhelo.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = winhelo
STACK    = 8k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt# 会不会和 ../app_make.txt 生成的 $(APP).hrb 冲突呢
$(APP).hrb : $(APP).org Makefile$(COPY) $(APP).org $(APP).hrb
winhelo2/Makefile
# 应用程序 winhelo2.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = winhelo2
STACK    = 8k
MALLOC   = 0k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
winhelo3/Makefile
# 应用程序 winhelo3.c Makefile# 可执行应用程序名,应用程序栈内存大小,应用程序堆内存大小 变量
APP      = winhelo3
STACK    = 1k
MALLOC   = 40k# 将上层目录的 app_make.txt 内容拷贝到此处
include ../app_make.txt
应用程序

没有细读代码较多应用程序的细节了哦。

a
/* 应用程序 a.c,在执行本引用程序的命令行窗口中打印字符 'A' *//* 系统调用头文件 */
#include "apilib.h"/* 应用程序入口 */
void HariMain(void)
{/* 调用系统调用打印字符 'A',调用系统调用退出应用程序。*/api_putchar('A');api_end();
}
bball
/* 应用程序 bball.c, 绘制线条形成球状 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{int win, i, j, dis;char buf[216 * 237];struct POINT {int x, y;};static struct POINT table[16] = {{ 204, 129 }, { 195,  90 }, { 172,  58 }, { 137,  38 }, {  98,  34 },{  61,  46 }, {  31,  73 }, {  15, 110 }, {  15, 148 }, {  31, 185 },{  61, 212 }, {  98, 224 }, { 137, 220 }, { 172, 200 }, { 195, 168 },{ 204, 129 }};/* 打开一个(216*237)像素点标题为bbal无透明色的窗口;并* 在窗口[(8,29),(207,228)]区域填充色号0对应的黑色。*/win = api_openwin(buf, 216, 237, -1, "bball");api_boxfilwin(win, 8, 29, 207, 228, 0);/* 在窗口中绘制线条,* 点table[0]到点table[1,...,15]的线条,* 点table[1]到点table[2,...,15]的线条,* ...* 点table[14]到点table[15]的线条。* 色号从[0,7],table中的点安排合适即可形成球状。*/for (i = 0; i <= 14; i++) {for (j = i + 1; j <= 15; j++) {dis = j - i;if (dis >= 8) {dis = 15 - dis;}if (dis != 0) {api_linewin(win, table[i].x, table[i].y, table[j].x, table[j].y, 8 - dis);}}}/* 直到按下回车键时退出本应用程序 */for (;;) {if (api_getkey(1) == 0x0a) {break;}}/* 退出应用程序 */api_end();
}
beepdown
/* 应用程序 beepdown.c,在人类能听到声音频率范围内蜂鸣 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{int i, timer;/* 分配定时器,设置定时器超时数据基数为 128 */timer = api_alloctimer();api_inittimer(timer, 128);for (i = 20000000; i >= 20000; i -= i / 100) {/* 设置发出20KHz - 20Hz范围内的蜂鸣,声音频率每次递减1% */api_beep(i);/* 设置定时器超时为10ms,若获取到的数据不为所设置的128则退出循环 */api_settimer(timer, 1);if (api_getkey(1) != 128) {break;}}/* 关闭蜂鸣器并退出应用程序 */api_beep(0);api_end();
}
calc
/* 应用程序 calc.c, 命令行计算器 *//* 此程序用递归和优先级参数实现了命令行计算器,* 比较难以被理解。在 ktv 听菩萨坝党派人士唱歌* 的那段时间里也没有清晰地想明白该程序的实现方式。*//* 系统调用声明头文件,C标准库头文件 */
#include "apilib.h"
#include <stdio.h>  /* sprintf *//* 用32位有符号第2小负数(最大正数溢出2)作为无效数据标识 */
#define INVALID -0x7fffffff/* 声明 stdlib.h 中的函数 */
int strtol(char *s, char **endp, int base);char *skipspace(char *p);
int getnum(char **pp, int priority);void HariMain(void)
{int i;char s[30], *p;/* 获取本任务命令行参数 */api_cmdline(s, 30);/* 跳过应用程序名 calc */for (p = s; *p > ' '; p++) { }i = getnum(&p, 9);/* 在当前窗口中以十进制和十六进制输出计算结果 */if (i == INVALID) {api_putstr0("error!\n");} else {sprintf(s, "= %d = 0x%x\n", i, i);api_putstr0(s);}/* 退出应用程序 */api_end();
}/* 跳过p所指内存段中的空格,返回非空格字符的地址 */
char *skipspace(char *p)
{for (; *p == ' '; p++) { }return p;
}/* 命令行计算器支持的运算符及运算符优先级由高到低[0~6]* +, -, ~, ();* *, /, %;* +, -;* <<, >>;* &;* ^;* |;* 同优先级运算符结合性由左至右。** 如 1+2*3+4 用递归和优先级 priority 保证的计算顺序为 2*3, 1+6, 7+4;* 如 1-2+3   用递归和优先级 priority 保证的计算顺序为 1-2, -1+3 */
int getnum(char **pp, int priority)
{char *p = *pp;int i = INVALID, j;/* 跳过空格 */p = skipspace(p);/* 首先获取带单目运算符的数字,如 +1, -1, ~1 */if (*p == '+') {p = skipspace(p + 1);i = getnum(&p, 0);} else if (*p == '-') {p = skipspace(p + 1);i = getnum(&p, 0);if (i != INVALID) {i = - i;}} else if (*p == '~') {p = skipspace(p + 1);i = getnum(&p, 0);if (i != INVALID) {i = ~i;}/* 处理括号内的表达式 */} else if (*p == '(') {p = skipspace(p + 1);i = getnum(&p, 9);if (*p == ')') {p = skipspace(p + 1);} else {i = INVALID;}/* 将参与运算的数字字符串转换为十进制数字 */} else if ('0' <= *p && *p <= '9') {i = strtol(p, &p, 0);} else {i = INVALID;}/* 处理带两个操作数的运算符,保证高优先级运算符的* 表达式先被计算,同优先级表达式结合性由左至右。*/for (;;) {if (i == INVALID) {break;}p = skipspace(p);if (*p == '+' && priority > 2) {p = skipspace(p + 1);j = getnum(&p, 2);if (j != INVALID) {i += j;} else {i = INVALID;}} else if (*p == '-' && priority > 2) {p = skipspace(p + 1);j = getnum(&p, 2);if (j != INVALID) {i -= j;} else {i = INVALID;}} else if (*p == '*' && priority > 1) {p = skipspace(p + 1);j = getnum(&p, 1);if (j != INVALID) {i *= j;} else {i = INVALID;}} else if (*p == '/' && priority > 1) {p = skipspace(p + 1);j = getnum(&p, 1);if (j != INVALID && j != 0) {i /= j;} else {i = INVALID;}} else if (*p == '%' && priority > 1) {p = skipspace(p + 1);j = getnum(&p, 1);if (j != INVALID && j != 0) {i %= j;} else {i = INVALID;}} else if (*p == '<' && p[1] == '<' && priority > 3) {p = skipspace(p + 2);j = getnum(&p, 3);if (j != INVALID && j != 0) {i <<= j;} else {i = INVALID;}} else if (*p == '>' && p[1] == '>' && priority > 3) {p = skipspace(p + 2);j = getnum(&p, 3);if (j != INVALID && j != 0) {i >>= j;} else {i = INVALID;}} else if (*p == '&' && priority > 4) {p = skipspace(p + 1);j = getnum(&p, 4);if (j != INVALID) {i &= j;} else {i = INVALID;}} else if (*p == '^' && priority > 5) {p = skipspace(p + 1);j = getnum(&p, 5);if (j != INVALID) {i ^= j;} else {i = INVALID;}} else if (*p == '|' && priority > 6) {p = skipspace(p + 1);j = getnum(&p, 6);if (j != INVALID) {i |= j;} else {i = INVALID;}} else {break;}}p = skipspace(p);*pp = p;return i;
}
chklang
/* 应用程序 chklang.c, 获取当前任务语言模式并打印 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{/* 获取当前任务语言模式 */int langmode = api_getlang();static char s1[23] = {  /* "日语JIS模式" 的编码 */0x93, 0xfa, 0x96, 0x7b, 0x8c, 0xea, 0x83, 0x56, 0x83, 0x74, 0x83, 0x67,0x4a, 0x49, 0x53, 0x83, 0x82, 0x81, 0x5b, 0x83, 0x68, 0x0a, 0x00};static char s2[17] = {  /* "日语EUC模式" 的编码 */0xc6, 0xfc, 0xcb, 0xdc, 0xb8, 0xec, 0x45, 0x55, 0x43, 0xa5, 0xe2, 0xa1,0xbc, 0xa5, 0xc9, 0x0a, 0x00};/* 根据当前任务语言模式并在当前终端给出提示 */if (langmode == 0) {api_putstr0("English ASCII mode\n");}if (langmode == 1) {api_putstr0(s1);}if (langmode == 2) {api_putstr0(s2);}/* 退出应用程序 */api_end();
}
color
/* 应用程序 color.c,在窗口指定区域填充指定颜色 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{char *buf;int win, x, y, r, g, b;/* 内存分配初始化;分配144*164字节内存作为窗口画面信息缓冲区;* 打开144*164大小标题为color无透明色的窗口。*/api_initmalloc();buf = api_malloc(144 * 164);win = api_openwin(buf, 144, 164, -1, "color");/* 用指定颜色填充win所管理窗口[(8,28),(136,156)]区域画面信息 */for (y = 0; y < 128; y++) {for (x = 0; x < 128; x++) {r = x * 2;g = y * 2;b = 0;buf[(x + 8) + (y + 28) * 144] = 16 + (r / 43) + (g / 43) * 6 + (b / 43) * 36;}}/* 刷新win所管理窗口[(8,28),(136,156)]   区域画面信息 */api_refreshwin(win, 8, 28, 136, 156);/* 敲任意键退出本应用程序 */api_getkey(1);api_end();
}
color2
/* 应用程序 color2.c,在窗口指定区域填充指定颜色 *//* 系统调用声明头文件 */
#include "apilib.h"unsigned char rgb2pal(int r, int g, int b, int x, int y);void HariMain(void)
{char *buf;int win, x, y;/* 初始化应用程序内存管理;分配144*164字节内存用作窗口画面信息缓冲区;* 打开144*164标题为color2无透明色的应用窗口。*/api_initmalloc();buf = api_malloc(144 * 164);win = api_openwin(buf, 144, 164, -1, "color2");/* 用 rgb2pal() 子程序指定颜色填充窗口[(8,28),(136,156)]区域画面信息 */for (y = 0; y < 128; y++) {for (x = 0; x < 128; x++) {buf[(x + 8) + (y + 28) * 144] = rgb2pal(x * 2, y * 2, 0, x, y);}}/* 刷新窗口[(8,28),(136,156)]区域画面信息,按任意键可结束本应用程序 */api_refreshwin(win, 8, 28, 136, 156);api_getkey(1);api_end();
}/* 用于计算颜色号的子程序(不关注计算细节啦) */
unsigned char rgb2pal(int r, int g, int b, int x, int y)
{static int table[4] = { 3, 1, 0, 2 };int i;x &= 1;y &= 1;i = table[x + y * 2];r = (r * 21) / 256;g = (g * 21) / 256;b = (b * 21) / 256;r = (r + i) / 4;g = (g + i) / 4;b = (b + i) / 4;return 16 + r + g * 6 + b * 36;
}
gview
/* 应用程序 gview.c,用图片做窗口背景图片应用程序 *//* 系统调用声明头文件 */
#include "apilib.h"/* 64Kb字节类型 */
struct DLL_STRPICENV {  /* 64KB */int work[64 * 1024 / 4];
};struct RGB {unsigned char b, g, r, t;
};/* bmp.nasm */
int info_BMP(struct DLL_STRPICENV *env, int *info, int size, char *fp);
int decode0_BMP(struct DLL_STRPICENV *env, int size, char *fp, int b_type, char *buf, int skip);/* jpeg.c */
int info_JPEG(struct DLL_STRPICENV *env, int *info, int size, char *fp);
int decode0_JPEG(struct DLL_STRPICENV *env, int size, char *fp, int b_type, char *buf, int skip);unsigned char rgb2pal(int r, int g, int b, int x, int y);
void error(char *s);void HariMain(void)
{struct DLL_STRPICENV env;char filebuf[512 * 1024], winbuf[1040 * 805];char s[32], *p;int win, i, j, fsize, xsize, info[8];struct RGB picbuf[1024 * 768], *q;/* 获取应用程序所在窗口命令行输入,* 并跳过 gview 命令和空格。*/api_cmdline(s, 30);for (p = s; *p > ' '; p++) { }for (; *p == ' '; p++) { }/* 打开图片,获取图片大小,根据图片大小将图片读* 到缓冲区 filebuf 中后关闭管理图片的结构体。*/i = api_fopen(p); if (i == 0) { error("file not found.\n"); }fsize = api_fsize(i, 0);if (fsize > 512 * 1024) {error("file too large.\n");}api_fread(filebuf, fsize, i);api_fclose(i);/* 判读图片类型, 若非 BMP 或 JPG 则退出应用程序 */if (info_BMP(&env, info, fsize, filebuf) == 0) {if (info_JPEG(&env, info, fsize, filebuf) == 0) {api_putstr0("file type unknown.\n");api_end();}}/* info 各字节含义, *//*  info[0] : 图片类型(1:BMP, 2:JPEG) *//*  info[1] : 色彩模式 *//*  info[2] : 图片x方向像素点数 *//*  info[3] : 图片y方向像素点数 *//* 若图片x方向或y方向像素点数大于屏幕像素点数则进行错误提示并退出应用程序 */if (info[2] > 1024 || info[3] > 768) {error("picture too large.\n");}/* 打开画面信息缓冲区为winbuf(xsize, info[3]+37)标题为gview无透明色的窗口 */xsize = info[2] + 16;if (xsize < 136) {xsize = 136;}win = api_openwin(winbuf, xsize, info[3] + 37, -1, "gview");/* 将图片内容转换为RGB颜色信息到picbuf缓冲区中 */if (info[0] == 1) {i = decode0_BMP (&env, fsize, filebuf, 4, (char *) picbuf, 0);} else {i = decode0_JPEG(&env, fsize, filebuf, 4, (char *) picbuf, 0);}if (i != 0) {error("decode error.\n");}/* 将picbuf中的RGB信息转换为色号信息存于窗口缓冲区中,然后刷新窗口画面 */for (i = 0; i < info[3]; i++) {p = winbuf + (i + 29) * xsize + (xsize - info[2]) / 2;q = picbuf + i * info[2];for (j = 0; j < info[2]; j++) {p[j] = rgb2pal(q[j].r, q[j].g, q[j].b, j, i);}}api_refreshwin(win, (xsize - info[2]) / 2, 29, (xsize - info[2]) / 2 + info[2], 29 + info[3]);/* 窗口接收到 'Q' 或 'q' 时退出 */for (;;) {i = api_getkey(1);if (i == 'Q' || i == 'q') {api_end();}}
}unsigned char rgb2pal(int r, int g, int b, int x, int y)
{static int table[4] = { 3, 1, 0, 2 };int i;x &= 1; /* ̴Д©˯Д© */y &= 1;i = table[x + y * 2];   /* ҆˔цðάé½ßÌӨД */r = (r * 21) / 256;   /* ±êÅ 0 20 ÉÈé */g = (g * 21) / 256;b = (b * 21) / 256;r = (r + i) / 4;    /* ±êÅ 0 5 ÉÈé */g = (g + i) / 4;b = (b + i) / 4;return 16 + r + g * 6 + b * 36;
}void error(char *s)
{api_putstr0(s);api_end();
}/** JPEG decoding engine for DCT-baseline**      copyrights 2003 by nikq | nikq::club.** history::* 2003/04/28 | added OSASK-GUI ( by H.Kawai )* 2003/05/12 | optimized DCT ( 20-bits fixed point, etc...) -> line 407-464 ( by I.Tak. )* 2003/09/27 | PICTURE0.BIN(DLL) ( by 久美子 )* 2003/09/28 | BUG优化 ( by H.Kawai )**/typedef unsigned char UCHAR;struct DLL_STRPICENV { int work[16384]; };typedef struct
{int elem; //ضҦДunsigned short code[256];unsigned char  size[256];unsigned char  value[256];
}HUFF;typedef struct
{// SOFint width;int height;// MCUint mcu_width;int mcu_height;int max_h,max_v;int compo_count;int compo_id[3];int compo_sample[3];int compo_h[3];int compo_v[3];int compo_qt[3];// SOSint scan_count;int scan_id[3];int scan_ac[3];int scan_dc[3];int scan_h[3];int scan_v[3];int scan_qt[3];// DRIint interval;int mcu_buf[32*32*4];int *mcu_yuv[4];int mcu_preDC[3];// DQTint dqt[3][64];int n_dqt;// DHTHUFF huff[2][3];// FILE i/ounsigned char *fp, *fp1;unsigned long bit_buff;int bit_remain;int width_buf;int base_img[64][64];/* for dll JPEG *jpeg = (JPEG *)malloc(sizeof(JPEG) + 256);*/int dummy[64];}JPEG;/* for 16bit */
#ifndef PIXEL16
#define PIXEL16(r, g, b)    ((r) << 11 | (g) << 5 | (b))/* 0 <= r <= 31, 0 <= g <= 63, 0 <= b <= 31 */
#endifint info_JPEG(struct DLL_STRPICENV *env, int *info, int size, UCHAR *fp);
int decode0_JPEG(struct DLL_STRPICENV *env, int size, UCHAR *fp, int b_type, UCHAR *buf, int skip);void jpeg_idct_init(int base_img[64][64]);
int jpeg_init(JPEG *jpeg);
// int jpeg_header(JPEG *jpge);
void jpeg_decode(JPEG *jpeg, unsigned char *rgb,int b_type);/* ----------------- start main section ----------------- */int info_JPEG(struct DLL_STRPICENV *env,int *info, int size, UCHAR *fp0)
{JPEG *jpeg = (JPEG *) (((int *) env) + 128);jpeg->fp = fp0;jpeg->fp1 = fp0 + size;//  if (512 + sizeof (JPEG) > 64 * 1024)
//      return 0;if (jpeg_init(jpeg))return 0;
//  jpeg_header(jpeg);if (jpeg->width == 0)return 0;info[0] = 0x0002;info[1] = 0x0000;info[2] = jpeg->width;info[3] = jpeg->height;/* OK */return 1;
}int decode0_JPEG(struct DLL_STRPICENV *env,int size, UCHAR *fp0, int b_type, UCHAR *buf, int skip)
{JPEG *jpeg = (JPEG *) (((int *) env) + 128);jpeg->fp = fp0;jpeg->fp1 = fp0 + size;jpeg_idct_init(jpeg->base_img);jpeg_init(jpeg);//  jpeg_header(jpeg);//  if (jpeg->width == 0)//  return 8;jpeg->width_buf = skip / (b_type & 0x7f) + jpeg->width;jpeg_decode(jpeg, buf, b_type);/* OK */return 0;
}// -------------------------- I/O ----------------------------unsigned short get_bits(JPEG *jpeg, int bit)
{unsigned char  c, c2;unsigned short ret;unsigned long  buff;int remain;buff   = jpeg->bit_buff;remain = jpeg->bit_remain;while (remain <= 16) {if (jpeg->fp >= jpeg->fp1) {ret = 0;goto fin;}c = *jpeg->fp++;if (c == 0xff) { if (jpeg->fp >= jpeg->fp1) {ret = 0;goto fin;}jpeg->fp++;}buff = (buff << 8) | c;remain += 8;}ret = (buff >> (remain - bit)) & ((1 << bit) - 1);remain -= bit;jpeg->bit_remain = remain;jpeg->bit_buff   = buff;
fin:return ret;
}// ------------------------ JPEG ----------------// start of frame
int jpeg_sof(JPEG *jpeg)
{unsigned char c;int i, h, v, n;if (jpeg->fp + 8 > jpeg->fp1)goto err;/* fp[2]   bpp */jpeg->height = jpeg->fp[3] << 8 | jpeg->fp[4];jpeg->width  = jpeg->fp[5] << 8 | jpeg->fp[6];n = jpeg->compo_count = jpeg->fp[7]; // Num of compo, nfjpeg->fp += 8;if (jpeg->fp + n * 3 > jpeg->fp1)goto err;for (i = 0; i < n; i++) {jpeg->compo_id[i] = jpeg->fp[0];jpeg->compo_sample[i] = c = jpeg->fp[1];h = jpeg->compo_h[i] = (c >> 4) & 0x0f;v = jpeg->compo_v[i] = c & 0x0f;if (jpeg->max_h < h)jpeg->max_h = h;if (jpeg->max_v < v)jpeg->max_v = v;jpeg->compo_qt[i] = jpeg->fp[2];jpeg->fp += 3;}return 0;
err:jpeg->fp = jpeg->fp1;return 1;
}// define quantize table
int jpeg_dqt(JPEG *jpeg)
{unsigned char c;int i, j, v, size;if (jpeg->fp + 2 > jpeg->fp1)goto err;size = (jpeg->fp[0] << 8 | jpeg->fp[1]) - 2;jpeg->fp += 2;if (jpeg->fp + size > jpeg->fp1)goto err;while (size > 0) {c = *jpeg->fp++;size--;j = c & 7;if (j > jpeg->n_dqt)jpeg->n_dqt = j;if (c & 0xf8) {// 16 bit DQTfor (i = 0; i < 64; i++) {jpeg->dqt[j][i] = jpeg->fp[0];jpeg->fp += 2;}size += -64 * 2;} else {//  8 bit DQTfor (i = 0; i < 64; i++)jpeg->dqt[j][i] = *jpeg->fp++;size -= 64;}}return 0;
err:jpeg->fp = jpeg->fp1;return 1;
}// define huffman table
int jpeg_dht(JPEG *jpeg)
{unsigned tc, th;unsigned code = 0;unsigned char val;int i, j, k, num, Li[17];int len, max_val;HUFF *table;if (jpeg->fp + 2 > jpeg->fp1)goto err;len = (jpeg->fp[0] << 8 | jpeg->fp[1]) - 2;jpeg->fp += 2;while (len > 0) {if (jpeg->fp + 17 > jpeg->fp1)goto err;val = jpeg->fp[0];tc = (val >> 4) & 0x0f;th =  val       & 0x0f;table = &(jpeg->huff[tc][th]);num = 0;k = 0;for (i = 1; i <= 16; i++) {Li[i] = jpeg->fp[i];num += Li[i];for (j = 0; j < Li[i]; j++)table->size[k++] = i;}table->elem = num;jpeg->fp += 17;k=0;code=0;i = table->size[0];while (k < num) {while (table->size[k] == i)table->code[k++] = code++;if (k >= num)break;do {code <<= 1;i++;} while (table->size[k] != i);}if (jpeg->fp + num > jpeg->fp1)goto err;for (k = 0; k < num; k++)table->value[k] = jpeg->fp[k];jpeg->fp += num;len -= 18 + num;}return 0;
err:jpeg->fp = jpeg->fp1;return 1;
}int jpeg_init(JPEG *jpeg)
{unsigned char c;int r = 0, i;jpeg->width = 0;jpeg->mcu_preDC[0] = 0;jpeg->mcu_preDC[1] = 0;jpeg->mcu_preDC[2] = 0;jpeg->n_dqt = 0;jpeg->max_h = 0;jpeg->max_v = 0;jpeg->bit_remain = 0;jpeg->bit_buff   = 0;jpeg->interval = 0;//  return;
//}
//
//int jpeg_header(JPEG *jpeg)
//{
//  unsigned char c;
//  int r = 0, i;for (;;) {if (jpeg->fp + 2 > jpeg->fp1)goto err;if (jpeg->fp[0] != 0xff)goto err0;c = jpeg->fp[1];jpeg->fp += 2;if (c == 0xd8)continue; /* SOI */if (c == 0xd9)goto err; /* EOI */if (c == 0xc0)jpeg_sof(jpeg);else if (c == 0xc4)jpeg_dht(jpeg);else if (c == 0xdb)jpeg_dqt(jpeg);else if (c == 0xdd) {if (jpeg->fp + 4 > jpeg->fp1)goto err;jpeg->interval = jpeg->fp[2] << 8 | jpeg->fp[3];jpeg->fp += 4;} else if (c == 0xda) {if (jpeg->fp + 3 > jpeg->fp1)goto err;jpeg->scan_count = jpeg->fp[2];jpeg->fp += 3;if (jpeg->fp + jpeg->scan_count * 2 > jpeg->fp1)goto err;for (i = 0; i < jpeg->scan_count; i++) {jpeg->scan_id[i] = jpeg->fp[0];jpeg->scan_dc[i] = jpeg->fp[1] >> 4;   // DC Huffman Tablejpeg->scan_ac[i] = jpeg->fp[1] & 0x0F; // AC Huffman Tablejpeg->fp += 2;}jpeg->fp += 3; /* 3bytes skip */goto fin;} else {if (jpeg->fp + 2 > jpeg->fp1)goto err;jpeg->fp += jpeg->fp[0] << 8 | jpeg->fp[1];}}
err:jpeg->fp = jpeg->fp1;
err0:r++;
fin:return r;
}// MCU decodevoid jpeg_decode_init(JPEG *jpeg)
{int i, j;for (i = 0; i < jpeg->scan_count; i++) {// i:scanfor (j = 0; j < jpeg->compo_count; j++) {// j:frameif (jpeg->scan_id[i] == jpeg->compo_id[j]) {jpeg->scan_h[i]  = jpeg->compo_h[j];jpeg->scan_v[i]  = jpeg->compo_v[j];jpeg->scan_qt[i] = jpeg->compo_qt[j];break;}}//  if (j >= jpeg->compo_count)//      return 1;}jpeg->mcu_width  = jpeg->max_h * 8;jpeg->mcu_height = jpeg->max_v * 8;for (i = 0; i < 32 * 32 * 4; i++)jpeg->mcu_buf[i] = 0x80;for (i = 0; i < jpeg->scan_count; i++)jpeg->mcu_yuv[i] = jpeg->mcu_buf + (i << 10);return;
}int jpeg_huff_decode(JPEG *jpeg,int tc,int th)
{HUFF *h = &(jpeg->huff[tc][th]);int code,size,k,v;code = 0;size = 0;k = 0;while( size < 16 ){size++;v = get_bits(jpeg,1);if(v < 0){return v;}code = (code << 1) | v;while(h->size[k] == size){if(h->code[k] == code){return h->value[k];}k++;}}return -1;
}void jpeg_idct_init(int base_img[64][64])
{int u, v, m, n;int tmpm[8], tmpn[8];int cost[32];cost[ 0] =  32768; cost[ 1] =  32138; cost[ 2] =  30274; cost[ 3] =  27246; cost[ 4] =  23170; cost[ 5] =  18205; cost[ 6] =  12540; cost[ 7] =   6393;cost[ 8] =      0; cost[ 9] =  -6393; cost[10] = -12540; cost[11] = -18205; cost[12] = -23170; cost[13] = -27246; cost[14] = -30274; cost[15] = -32138;for (u = 0; u < 16; u++)cost[u + 16] = - cost[u];for (u = 0; u < 8; u++) {{int i=u, d=u*2;if (d == 0)i = 4;for (m = 0; m < 8; m++){tmpm[m] = cost[i];i=(i+d)&31;}}for (v = 0; v < 8; v++) {{int i=v,d=v*2;if (d == 0)i=4;for (n = 0; n < 8; n++){tmpn[n] = cost[i];i=(i+d)&31;}}for (m = 0; m < 8; m++) {for (n = 0; n < 8; n++) {base_img[u * 8 + v][m * 8 + n] = (tmpm[m] * tmpn[n])>>15;}}}}return;
}void jpeg_idct(int *block, int *dest, int base_img[64][64])
{int i, j ,k;for (i = 0; i < 64; i++)dest[i] = 0;for (i = 0; i < 64; i++) {k = block[i];if(k) {for (j = 0; j < 64; j++) {dest[j] += k * base_img[i][j];}}}for (i = 0; i < 64; i++)dest[i] >>= 17;return;
}int jpeg_get_value(JPEG *jpeg,int size)
{int val = 0;if (size) {val = get_bits(jpeg,size);if (val < 0)val = 0x10000 | (0 - val);else if (!(val & (1<<(size-1))))val -= (1 << size) - 1;}return val;
}int jpeg_decode_huff(JPEG *jpeg,int scan,int *block, UCHAR *zigzag_table)
{int size, len, val, run, index;int *pQt = (int *)(jpeg->dqt[jpeg->scan_qt[scan]]);// DCsize = jpeg_huff_decode(jpeg,0,jpeg->scan_dc[scan]);if(size < 0)return 0;val = jpeg_get_value(jpeg,size);jpeg->mcu_preDC[scan] += val;block[0] = jpeg->mcu_preDC[scan] * pQt[0];index = 1;while(index<64){size = jpeg_huff_decode(jpeg,1,jpeg->scan_ac[scan]);if(size < 0)break;// EOBif(size == 0)break;// RLErun  = (size>>4)&0xF;size = size & 0x0F;val = jpeg_get_value(jpeg,size);if(val>=0x10000) {return val;}// ZRLwhile (run-- > 0)block[ zigzag_table[index++] ] = 0;block[ zigzag_table[index] ] = val * pQt[index];index++;}while(index<64)block[zigzag_table[index++]]=0;return 0;
}void jpeg_mcu_bitblt(int *src, int *dest, int width,int x0, int y0, int x1, int y1)
{int w, h;int x, y, x2, y2;w = x1 - x0;h = y1 - y0;dest += y0 * width + x0;width -= w;for (y = 0; y < h; y++) {y2 = (y * 8 / h) * 8;for (x = 0; x < w; x++)*dest++ = src[y2 + (x * 8 / w)];dest += width;}
}int jpeg_decode_mcu(JPEG *jpeg, UCHAR *zigzag_table)
{int scan, val;int unit, i, h, v;int *p, hh, vv;int block[64], dest[64];for (scan = 0; scan < jpeg->scan_count; scan++) {hh = jpeg->scan_h[scan];vv = jpeg->scan_v[scan];for (v = 0; v < vv; v++) {for (h = 0; h < hh; h++) {val = jpeg_decode_huff(jpeg, scan, block, zigzag_table);//  if(val>=0x10000){//      printf("marker found:%02x\n",val);//  }// DCTjpeg_idct(block, dest, jpeg->base_img);p = jpeg->mcu_buf + (scan << 10);jpeg_mcu_bitblt(dest, p, jpeg->mcu_width,jpeg->mcu_width * h / hh, jpeg->mcu_height * v / vv,jpeg->mcu_width * (h + 1) / hh, jpeg->mcu_height * (v + 1) / vv);}}}
}// YCrCb=>RGBint jpeg_decode_yuv(JPEG *jpeg, int h, int v, unsigned char *rgb, int b_type)
{int x0, y0, x, y, x1, y1;int *py;int Y12, V;int mw, mh, w;int i;mw = jpeg->mcu_width;mh = jpeg->mcu_height;x0 = h * jpeg->max_h * 8;y0 = v * jpeg->max_v * 8;x1 = jpeg->width - x0;if (x1 > mw)x1 = mw;y1 = jpeg->height - y0;if (y1 > mh)y1 = mh;py = jpeg->mcu_buf;rgb += (y0 * jpeg->width_buf + x0) * (b_type & 0x7f);w = (jpeg->width_buf - x1) * (b_type & 0x7f);for (y = 0; y < y1; y++) {for (x = 0; x < x1; x++) {int b, g, r;Y12 = py[0] << 12;//  U = py[1024]; /* pu */V = py[2048]; /* pv *//* blue */b = 128 + ((Y12 - V * 4 + py[1024] /* pu */ * 0x1C59) >> 12);if (b & 0xffffff00)b = (~b) >> 24;/* green */g = 128 + ((Y12 - V * 0x0B6C) >> 12);if (g & 0xffffff00)g = (~g) >> 24;/* red */r = 128 + ((Y12 + V * 0x166E) >> 12);if (r & 0xffffff00)r = (~r) >> 24;if (b_type == 0x0004) {rgb[0] = b;rgb[1] = g;rgb[2] = r;py++;rgb += 4;} else if (b_type == 0x0002) {r &= 0xff;g &= 0xff;b &= 0xff;*(short *) rgb = PIXEL16(r >> 3, g >> 2, b >> 3);rgb += 2;}}py += mw - x1;rgb += w;}return;
}#define INIT_ZTABLE(i, b0, b1, b2, b3) *(int *) &zigzag_table[i] = b0 | b1 << 8 | b2 << 16 | b3 << 24void jpeg_decode(JPEG *jpeg, UCHAR *rgb, int b_type)
{int h_unit, v_unit;int mcu_count, h, v;int val;unsigned char m;UCHAR zigzag_table[64];INIT_ZTABLE( 0,  0,  1,  8, 16); INIT_ZTABLE( 4,  9,  2,  3, 10);INIT_ZTABLE( 8, 17, 24, 32, 25); INIT_ZTABLE(12, 18, 11,  4,  5);INIT_ZTABLE(16, 12, 19, 26, 33); INIT_ZTABLE(20, 40, 48, 41, 34);INIT_ZTABLE(24, 27, 20, 13,  6); INIT_ZTABLE(28,  7, 14, 21, 28);INIT_ZTABLE(32, 35, 42, 49, 56); INIT_ZTABLE(36, 57, 50, 43, 36);INIT_ZTABLE(40, 29, 22, 15, 23); INIT_ZTABLE(44, 30, 37, 44, 51);INIT_ZTABLE(48, 58, 59, 52, 45); INIT_ZTABLE(52, 38, 31, 39, 46);INIT_ZTABLE(56, 53, 60, 61, 54); INIT_ZTABLE(60, 47, 55, 62, 63);jpeg_decode_init(jpeg);h_unit = (jpeg->width + jpeg->mcu_width - 1) / jpeg->mcu_width;v_unit = (jpeg->height + jpeg->mcu_height - 1) / jpeg->mcu_height;mcu_count = 0;for (v = 0; v < v_unit; v++) {for (h = 0; h < h_unit; h++) {mcu_count++;jpeg_decode_mcu(jpeg, zigzag_table);jpeg_decode_yuv(jpeg, h, v, rgb, b_type & 0x7fff);if (jpeg->interval > 0 && mcu_count >= jpeg->interval) {jpeg->bit_remain -= (jpeg->bit_remain & 7);jpeg->bit_remain -= 8;jpeg->mcu_preDC[0] = 0;jpeg->mcu_preDC[1] = 0;jpeg->mcu_preDC[2] = 0;mcu_count = 0;}}}return;
}; BMP decode routine by I.Tak. 2003; BMP 解析程序,I.Tak不沿用已有汇编格式而选择nasm汇编格式编写 BMP 解析程序,
; 不太友好啊,这使得此文失去了了解 bmp.nasm 解析 BMP 图片细则的兴趣。丧失兴
; 趣这具有蔓延性,因为此文对解析 JPEG 图片的 jpeg.c 程序也丧失了兴趣。仅在
; 接口层面了解图片解析吧。section .text align=1
[bits 32]
;BMP File Structure (I can't understand MS.); BMP 文件头部信息
struc BMP;FILE HEADER,BMP文件头部信息.fType: resw 1  ;BM.fSize: resd 1  ;whole file sizeresd 1  ;reserved.fOffBits: resd 1 ;offset from file top to image(图像数据在图片文件中的偏移);INFO HEADER,BMP图像头部信息.iSize:     resd 1  ;INFO HEADER size.iWidth:    resd 1  ;Image Width in pixels.iHeight:   resd 1  ;Image Height in pixels.iPlanes:   resw 1  ;must be 1.iBitCount: resw 1  ;BitPerPixel 1, 4, 8, 24 (and 15,16 for new OS/2 ?).iCompression:  resd 1  ;Compress Type. 0 for none, then SizeImage=0.iSizeImage:    resd 1  ;Image Size(compressed).iXPPM:     resd 1      ;X Pixel Per Meter.iYPPM:     resd 1.iClrUsed:  resd 1      ;Number of used ColorQuad (0 for whole Quad).iClrImportant: resd 1  ;Number of Important ColorQuad.
endstruc; BMPOS2 文件头部信息
struc BMPOS2;FILE HEADER.fType: resw 1  ;BM.fSize: resd 1  ;whole file sizeresd 1  ;reserved.fOffBits:  resd 1  ;offset from file top to image;CORE HEADER.iSize:     resd 1  ;CORE HEADER size.iWidth:    resw 1  ;Image Width in pixels.iHeight:   resw 1  ;Image Height in pixels.iPlanes:   resw 1  ;must be 1.iBitCount: resw 1  ;BitPerPixel 1, 4, 8, 24 (and 15,16 for new OS/2 ?)
endstruc; B/W bmp can also have palettes. The first for 0, second for 1.struc CQuad.b: resb 1.g: resb 1.r: resb 1resb 1  ;reserved
endstruc%if 0
int info_BMP(struct DLL_STRPICENV *env, int *info, int size, UCHAR *fp);
int decode0_BMP(struct DLL_STRPICENV *env, int size, UCHAR *fp,int b_type, UCHAR *buf, int skip);
%endif[absolute 0]
bmpinfo:
.regs:      resd 4
.reteip:    resd 1
.env:       resd 1
.info:      resd 1
.size:      resd 1
.module:    resd 1
[absolute 0]info:
.type:  resd 1  ;1 for BMP, 2 for JPEGresd 1  ;0
.width:     resd 1
.height:    resd 1
[section .text]
[global  _info_BMP]; _info_BMP
; 解析 BMP 图片。
_info_BMP: ; int info_BMP(struct DLL_STRPICENV *env, int *info, int size, char *fp);push ebxpush ebppush esipush edimov esi, [esp+bmpinfo.module]mov eax, [esp+bmpinfo.size]call bmpHeadertest edi, edijz .retmov esi, [esp+bmpinfo.info]mov [esi+info.width], eaxmov [esi+info.height], ecxmov [esi+info.type], edi    ;=1dec edimov [esi+info.type+4], edi  ;=0inc edi
.ret:   mov eax, edipop edipop esipop ebppop ebxret;in: esi=module, eax=size
;ret:eax=width, ecx=hegiht, edx=paletteSize, ebx=palette
;    ebp=bpp, esi=endOfImage, edi=successFlag
bmpHeader:lea edx, [esi+eax]  ;moduleEndxor edi, edipush edxxor edx, edxcmp eax, byte BMP.iSize+4jbe ..@retcmp word[esi],'BM'je .notMACsub esi, byte -128add eax, byte -128pop ebxpush eaxcmp eax, byte BMP.iSize+4..@ret: jbe .retcmp word[esi], 'BM'jne .ret
.notMAC:;;MS,OS/2 格式mov ecx, [esi +BMP.iSize]cmp ecx, byte 12    ;OS/2 format.jne .MScmp eax, byte BMPOS2_sizejbe .ret  ;corelea ebx, [esi+ecx+14] ;palettemovzx eax, word[esi+BMPOS2.iWidth]    ;widthmovzx ecx, word[esi+BMPOS2.iHeight]   ;heightmovzx ebp, word[esi+BMPOS2.iBitCount] ;bppmov dl, 3 ;paletteSizejmp short .endif
.MS:    cmp eax, byte BMP_sizejbe .ret  ;infoƘƃƀŊķlea ebx, [esi+ecx+14]sub ecx,byte 40jne .ret    ;unknownFormatcmp ecx, [esi+BMP.iCompression]jne .ret    ;Compressed.mov   eax, [esi+BMP.iWidth]         ;widthmov   ecx, [esi+BMP.iHeight]        ;heightmovzx ebp, word[esi +BMP.iBitCount] ;bppmov dl, 4   ;paletteSize
.endif:add esi, [esi +BMP.fOffBits]push edxpush eaxmul ebp         ;eax=width*bppadd eax, byte 7shr eax, 3      ;lineSizeWithoutPuddingmov edx, eaxadd eax, byte 3 ;size<1GBand al, -4      ;lineSizeWithPuddingsub edx, eax    ;-puddingSizepush edxmul ecxpop edxadd esi, eaxadd esi, edx    cmp esi, [esp+8]    ;endOfModulepop eaxja .ret2sub esi, edx        ;esi=endOfImageinc edi             ;succeeded!
.ret2:  pop edx
.ret:   add esp, byte 4ret;***************************************************************[absolute 0]
decode:
.regs:      resd 4
.reteip:    resd 1
.env:       resd 1
.size:      resd 1
.module:    resd 1
.outputType:    resd 1
.dest:      resd 1
.skip:      resd 1
[section .text]
[global _decode0_BMP]
_decode0_BMP:push ebxpush ebppush esipush edimov esi, [esp+decode.module]mov eax, [esp+decode.size]call bmpHeader;ret:eax=width, ecx=hegiht, edx=paletteSize, ebx=palette;    ebp=bpp, esi=endOfImage, edi=successFlagtest edi,edijz .errormov edi, [esp+decode.dest]push dword[esp+decode.outputType]push dword[esp+4+decode.skip]push ecx    ;heightpush eaxpush edxmul ebpadd eax, byte 31shr eax, 3and al, -4push eaxmov edx, ebpmov ebp, espcall bmp2beta   ;ecx!=0 for erroradd esp, byte bb.sizemov eax, ecxtest ecx, ecxjz .ret
.error: push byte 1pop eax
.ret:   pop edipop esipop ebppop ebxret[absolute -4*2]
bb:
.col0:      resd 1
.reteip:    resd 1
.sw:        resd 1      ;byte
.paletteSize:   resd 1  ;byte
.w: resd 1  ;pixel
.h: resd 1
.s: resd 1
.t: resd 1
.size: equ $-$$
[section .text]
;eax=?, ecx=height, edx=bpp, ebx=palette
;ebp=bb, esi=endOfImage, edi=dest
bmp2beta:mov al, [ebp+bb.t]and al, 0x7fcmp al, 2je near buf16cmp al, 4je buf32mov ecx, esp    ;!=0ret
;===============================================================
;   Buffer mode 4
;===============================================================
buf32:dec edxje near .bpp1sub edx, byte 4-1je .bpp4sub edx, byte 8-4je .bpp8sub edx, byte 24-8je .bpp24mov ecx, esp    ;!=0ret
;---------------------------------------------------
;   24bpp BMP to 4byte bufer
;---------------------------------------------------
.bpp24:;ecx=height, edx=0, ebx=palette;esi=endOfImage, edi=destinationBuffer;bb.w=width(pixel), bb.s=skipByte, bb.h=height;bb.t=outputType, bb.sw=sourceWidthByte.do24.1:sub esi, [ebp+bb.sw]    ;esi=startOfLinepush ecxpush esimov ecx, [ebp+bb.w].do24.2:mov al, [esi]mov [edi+3], dlmov [edi], almov al, [esi+1]mov [edi+1], almov al, [esi+2]mov [edi+2], aladd esi, byte 3add edi, byte 4dec ecxjnz .do24.2pop esipop ecxadd edi, [ebp+bb.s]dec ecxjnz .do24.1ret;---------------------------------------------------
;   8bpp BMP to 4byte buffer
;---------------------------------------------------
.bpp8:;ecx=height, edx=0, ebx=palette;esi=endOfImage, edi=destinationBuffermov dl, 255mov eax, [ebp+bb.paletteSize]sub ebx, eaxshl eax, 8add ebx, eax    ;ebx += paletteSize*255.do8.1:mov eax, [ebx]sub ebx, [ebp+bb.paletteSize]and eax, 0x00ffffffdec edxpush eaxjns .do8.1.do8.2:sub esi, [ebp+bb.sw]    ;esi=firstLineStartpush ecxpush esimov ecx, [ebp+bb.w].do8.3:xor eax, eaxadd edi, byte 4mov al, [esi]inc esi;AGI stolemov eax, [esp+eax*4+8]dec ecxmov [edi-4], eaxjnz .do8.3pop esipop ecxadd edi, [ebp+bb.s]dec ecxjnz .do8.2add esp, 256*4  ;paletteret;---------------------------------------------------
;   4bpp BMP to 4byte buffer
;---------------------------------------------------
.bpp4:;ecx=height, edx=0, ebx=palette;esi=endOfImage, edi=destinationBuffermov dl, 16mov eax, [ebp+bb.paletteSize]sub ebx, eaxshl eax, 4add ebx, eax    ;ebx+=eax*15.do4.1mov eax, [ebx]sub ebx, [ebp+bb.paletteSize]and eax, 0x00ffffffdec edxpush eaxjnz .do4.1.do4.2:sub esi, [ebp+bb.sw]    ;esi=firstLineStartpush ecxpush esimov ecx, [ebp+bb.w].do4.3:xor edx, edxmov al, [esi]mov dl, alinc esishr dl, 4and eax, byte 15add edi, byte 4dec ecxmov edx, [esp+edx*4+8]mov eax, [esp+eax*4+8]mov [edi-4], edxjz .wendmov [edi], eaxadd edi, byte 4dec ecxjnz .do4.3
.wend:  pop esipop ecxadd edi, [ebp+bb.s]dec ecxjnz .do4.2add esp, 16*4   ;paletteret;---------------------------------------------------
;   1bpp BMP to 4byte buffer
;---------------------------------------------------
.bpp1:;ecx=height, edx=0, ebx=palette;esi=endOfImage, edi=destinationBuffermov eax, [ebx]add ebx, [ebp+bb.paletteSize]and eax, 0x00ffffffmov ebx, [ebx]and ebx, 0x00ffffffxor ebx, eax;push ebxpush eax.do1.1:sub esi, [ebp+bb.sw]    ;esi=firstLineStartpush ecxpush esimov ecx, [ebp+bb.w].do1.2:mov dl, [esi]inc esipush esimov esi, 8.do1.3:add edi, byte 4add dl, dlsbb eax, eaxand eax, ebxxor eax, [ebp+bb.col0]dec ecxmov [edi-4], eaxjz .wend1bppdec esijnz .do1.3pop esijmp short .do1.2
.wend1bpp:pop ecxpop esipop ecxadd edi, [ebp+bb.s]dec ecxjnz .do1.1pop eaxret;===============================================
;   Buffer mode 2byte
;===============================================
buf16:dec edxje near .bpp1sub edx, byte 4-1je near .bpp4sub edx, byte 8-4je .bpp8sub edx, byte 24-8je .bpp24mov ecx, espret
;---------------------------------------------------
;   24bpp BMP to 2byte bufer
;---------------------------------------------------
.bpp24:;ecx=height, edx=0, ebx=palette;esi=endOfImage, edi=destinationBuffer.do24.1:sub esi, [ebp+bb.sw]    ;esi=startOfLinepush ecxpush esimov ecx, [ebp+bb.w].do24.2:mov al, [esi+2]shl eax, 16mov ax, [esi]add esi, byte 3;eax=24bitColor, edx=work, ecx=counter, ebx=workshr ah, 2inc edishr eax, 3shl ax, 5inc edishr eax, 5dec ecxmov [edi-2], axjnz .do24.2pop esipop ecxadd edi, [ebp+bb.s]dec ecxjnz .do24.1ret;---------------------------------------------------
;   8bpp BMP to 2byte buffer
;---------------------------------------------------
.bpp8:;ecx=height, edx=0, ebx=palette;esi=endOfImage, edi=destinationBuffer;palletemov dl, 255mov eax, [ebp+bb.paletteSize]sub ebx, eaxshl eax, 8add ebx, eax    ;ebx += paletteSize*255.do8.1:mov eax, [ebx]sub ebx, [ebp+bb.paletteSize]call .paletteConvdec edxpush eaxjns .do8.1.do8.2:sub esi, [ebp+bb.sw]    ;esi=firstLineStartpush ecxpush esimov ecx, [ebp+bb.w].do8.3:xor eax, eaxadd edi, byte 2mov al, [esi]inc esi;AGI stolemov eax, [esp+eax*4+8]dec ecxmov [edi-2], axjnz .do8.3pop esipop ecxadd edi, [ebp+bb.s]dec ecxjnz .do8.2add esp, 256*4  ;paletteret;---------------------------------------------------
;   4bpp BMP to 2byte buffer
;---------------------------------------------------
.bpp4:;ecx=height, edx=0, ebx=palette;esi=endOfImage, edi=destinationBuffer;palletemov dl, 16mov eax, [ebp+bb.paletteSize]sub ebx, eaxshl eax, 4add ebx, eax    ;ebx+=eax*15.do4.1:mov eax, [ebx]sub ebx, [ebp+bb.paletteSize]call .paletteConvdec edxpush eaxjnz .do4.1.do4.2:sub esi, [ebp+bb.sw]    ;esi=firstLineStartpush ecxpush esimov ecx, [ebp+bb.w].do4.3:xor edx, edxmov al, [esi]mov dl, alinc esishr dl, 4and eax, byte 15add edi, byte 2dec ecxmov edx, [esp+edx*4+8]mov eax, [esp+eax*4+8]mov [edi-2], dxjz .wendmov [edi], axadd edi, byte 2dec ecxjnz .do4.3
.wend:  pop esipop ecxadd edi, [ebp+bb.s]dec ecxjnz .do4.2add esp, 16*4   ;paletteret;---------------------------------------------------
;   1bpp BMP to 2byte buffer
;---------------------------------------------------
.bpp1:;ecx=height, edx=0, ebx=palette;esi=endOfImage, edi=destinationBuffer;palletemov eax, [ebx]add ebx, [ebp+bb.paletteSize]call .paletteConvpush eaxmov eax, [ebx]call .paletteConvpop ebxxchg eax, ebxxor ebx, eaxpush eax.do1.1:sub esi, [ebp+bb.sw]    ;esi=firstLineStartpush ecxpush esimov ecx, [ebp+bb.w].do1.2:mov dl, [esi]inc esipush esimov esi, 8.do1.3:add dl, dlinc edisbb eax, eaxinc ediand eax, ebxxor eax, [ebp+bb.col0]dec ecxmov [edi-2], axjz .wend1bppdec esijnz .do1.3pop esijmp short .do1.2
.wend1bpp:pop ecxpop esipop ecxadd edi, [ebp+bb.s]dec ecxjnz .do1.1pop eaxret.paletteConv:shr ah, 2shr eax, 3shl ax, 5shr eax, 5ret
hello3
/* 应用程序 hello3.c,在当前终端输出hello *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{/* 通过系统调用在当前终端输出hello后结束应用程序 */api_putchar('h');api_putchar('e');api_putchar('l');api_putchar('l');api_putchar('o');api_end();
}
hello4
/* 应用程序 hello4.c,在当前终端输出hello *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{/* 调用在当前终端打印字符串的系统调用* 输出hello,world\n后退出应用程序。*/api_putstr0("hello, world\n");api_end();
}
hello5
[FORMAT "WCOFF"]
[INSTRSET "i486p"]
[BITS 32]
; hello5.nas,用汇编程序编写在当前终端输出 hello,world\n 的程序; 告知编译器源文件名
[FILE "hello5.nas"]; 声明 _HariMain 为全局标识符GLOBAL _HariMain; 告知编译器代码段开始
[SECTION .text]; 用汇编程序完成打印字符串的系统调用
_HariMain:MOV EDX,2   ; 系统调用号2MOV EBX,msg ; 字符串INT 0x40    ; 进入打印字符串msg的系统调用MOV EDX,4   ; 系统调用号4INT 0x40    ; 进入系统调用退出本应用程序; 告知编译器数据段开始
[SECTION .data]; 字符串信息
msg:DB "hello, world", 0x0a, 0
invader
/* 应用程序 invader.c, 一个枪机游戏应用程序 *//* 系统调用声明头文件,C标准库头文件 */
#include <string.h> /* strlen */
#include "apilib.h"void putstr(int win, char *winbuf, int x, int y, int col, unsigned char *s);
void wait(int i, int timer, char *keyflag);
void setdec8(char *s, int i);/* invader 游戏图标像素点阵 */
static unsigned char charset[16 * 8] = {/* invader(0) */0x00, 0x00, 0x00, 0x43, 0x5f, 0x5f, 0x5f, 0x7f,0x1f, 0x1f, 0x1f, 0x1f, 0x00, 0x20, 0x3f, 0x00,/* invader(1) */0x00, 0x0f, 0x7f, 0xff, 0xcf, 0xcf, 0xcf, 0xff,0xff, 0xe0, 0xff, 0xff, 0xc0, 0xc0, 0xc0, 0x00,/* invader(2) */0x00, 0xf0, 0xfe, 0xff, 0xf3, 0xf3, 0xf3, 0xff,0xff, 0x07, 0xff, 0xff, 0x03, 0x03, 0x03, 0x00,/* invader(3) */0x00, 0x00, 0x00, 0xc2, 0xfa, 0xfa, 0xfa, 0xfe,0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x04, 0xfc, 0x00,/* fighter(0) */0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x43, 0x47, 0x4f, 0x5f, 0x7f, 0x7f, 0x00,/* fighter(1) */0x18, 0x7e, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0xff,0xff, 0xff, 0xe7, 0xe7, 0xe7, 0xe7, 0xff, 0x00,/* fighter(2) */0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,0x80, 0xc2, 0xe2, 0xf2, 0xfa, 0xfe, 0xfe, 0x00,/* laser */0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00
};
/* invader:"abcd", fighter:"efg", laser:"h" */
/* abcd 与 invader 图标像素点阵映射,efg 与 fighter* 图标像素点阵映射,h 与炮弹图标像素点阵映射。*/void HariMain(void)
{int win, timer, i, j, fx, laserwait, lx = 0, ly;int ix, iy, movewait0, movewait, idir;int invline, score, high, point;char winbuf[336 * 261], invstr[32 * 6], s[12], keyflag[4], *p;static char invstr0[32] = " abcd abcd abcd abcd abcd ";/* 新建缓冲区为winbuf(336*261)标题为invader无透明色窗口,* 在新建窗口中绘制矩形[(6,27),(329,254)];分配定时器及其超时数据128。*/win = api_openwin(winbuf, 336, 261, -1, "invader");api_boxfilwin(win, 6, 27, 329, 254, 0);timer = api_alloctimer();api_inittimer(timer, 128);high = 0;putstr(win, winbuf, 22, 0, 7, "HIGH:00000000");restart:score = 0;point = 1;putstr(win, winbuf,  4, 0, 7, "SCORE:00000000");movewait0 = 20;fx = 18;putstr(win, winbuf, fx, 13, 6, "efg");wait(100, timer, keyflag);next_group:wait(100, timer, keyflag);ix = 7;iy = 1;invline = 6;for (i = 0; i < 6; i++) {for (j = 0; j < 27; j++) {invstr[i * 32 + j] = invstr0[j];}putstr(win, winbuf, ix, iy + i, 2, invstr + i * 32);}keyflag[0] = 0;keyflag[1] = 0;keyflag[2] = 0;ly = 0;laserwait = 0;movewait = movewait0;idir = +1;wait(100, timer, keyflag);for (;;) {if (laserwait != 0) {laserwait--;keyflag[2 /* space */] = 0;}/* 等待40ms获取键盘输入 */wait(4, timer, keyflag);/* fighter移动,* keyflag[0],left; keyflag[1],right; keyflag[2],发射 */if (keyflag[0 /* left */]  != 0 && fx > 0) {fx--;putstr(win, winbuf, fx, 13, 6, "efg ");keyflag[0 /* left */]  = 0;}if (keyflag[1 /* right */] != 0 && fx < 37) {putstr(win, winbuf, fx, 13, 6, " efg");fx++;keyflag[1 /* right */] = 0;}if (keyflag[2 /* space */] != 0 && laserwait == 0) {laserwait = 15;lx = fx + 1;ly = 13;}/* invader移动 */if (movewait != 0) {movewait--;} else {movewait = movewait0;if (ix + idir > 14 || ix + idir < 0) {if (iy + invline == 13) {break; /* GAME OVER */}idir = - idir;putstr(win, winbuf, ix + 1, iy, 0, "                         ");iy++;} else {ix += idir;}for (i = 0; i < invline; i++) {putstr(win, winbuf, ix, iy + i, 2, invstr + i * 32);}}/* 炮弹移动 */if (ly > 0) {if (ly < 13) {if (ix < lx && lx < ix + 25 && iy <= ly && ly < iy + invline) {putstr(win, winbuf, ix, ly, 2, invstr + (ly - iy) * 32);} else {putstr(win, winbuf, lx, ly, 0, " ");}}ly--;if (ly > 0) {putstr(win, winbuf, lx, ly, 3, "h");} else {point -= 10;if (point <= 0) {point = 1;}}if (ix < lx && lx < ix + 25 && iy <= ly && ly < iy + invline) {p = invstr + (ly - iy) * 32 + (lx - ix);if (*p != ' ') {/* hit ! */score += point;point++;setdec8(s, score);putstr(win, winbuf, 10, 0, 7, s);if (high < score) {high = score;putstr(win, winbuf, 27, 0, 7, s);}for (p--; *p != ' '; p--) { }for (i = 1; i < 5; i++) {p[i] = ' ';}putstr(win, winbuf, ix, ly, 2, invstr + (ly - iy) * 32);for (; invline > 0; invline--) {for (p = invstr + (invline - 1) * 32; *p != 0; p++) {if (*p != ' ') {goto alive;}}}/* invader被全部消灭则跳转 next_group处进行下一组invader */movewait0 -= movewait0 / 3;goto next_group;
alive:ly = 0;}}}}/* GAME OVER */putstr(win, winbuf, 15, 6, 1, "GAME OVER");wait(0, timer, keyflag);for (i = 1; i < 14; i++) {putstr(win, winbuf, 0, i, 0, "                                        ");}goto restart;
}/* putstr,* 将s所指字符串以色号col在win所管理窗口(x,y)处开始显示。*/
void putstr(int win, char *winbuf, int x, int y, int col, unsigned char *s)
{int c, x0, i;char *p, *q, t[2];x = x * 8 + 8;y = y * 16 + 29;x0 = x;i = strlen(s);api_boxfilwin(win + 1, x, y, x + i * 8 - 1, y + 15, 0);q = winbuf + y * 336;t[1] = 0;for (;;) {c = *s;if (c == 0) {break;}if (c != ' ') {if ('a' <= c && c <= 'h') {p = charset + 16 * (c - 'a');q += x;for (i = 0; i < 16; i++) {if ((p[i] & 0x80) != 0) { q[0] = col; }if ((p[i] & 0x40) != 0) { q[1] = col; }if ((p[i] & 0x20) != 0) { q[2] = col; }if ((p[i] & 0x10) != 0) { q[3] = col; }if ((p[i] & 0x08) != 0) { q[4] = col; }if ((p[i] & 0x04) != 0) { q[5] = col; }if ((p[i] & 0x02) != 0) { q[6] = col; }if ((p[i] & 0x01) != 0) { q[7] = col; }q += 336;}q -= 336 * 16 + x;} else {t[0] = *s;api_putstrwin(win + 1, x, y, col, 1, t);}}s++;x += 8;}api_refreshwin(win, x0, y, x, y + 16);return;
}/* wait,* 等待键盘输入,i个10ms超时。*/
void wait(int i, int timer, char *keyflag)
{int j;/* 设置定时器超时时间 */if (i > 0) {api_settimer(timer, i);i = 128;} else {i = 0x0a; /* Enter */}/* 获取键盘输入,超时退出 */for (;;) {j = api_getkey(1);if (i == j) {break;}/* 4, left; 6, right; 空格,发射炮弹 */if (j == '4') {keyflag[0 /* left */]  = 1;}if (j == '6') {keyflag[1 /* right */] = 1;}if (j == ' ') {keyflag[2 /* space */] = 1;}}return;
}/* setdec8,* 将数字i转换成字符串到s中。*/
void setdec8(char *s, int i)
{int j;for (j = 7; j >= 0; j--) {s[j] = '0' + i % 10;i /= 10;}s[8] = 0;return;
}
iroha
/* 应用程序 iroha.c,在当前终端输出半角字符 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{/* 一段半角字符串编码,最后两个字符分别为回车和0 */static char s[9] = { 0xb2, 0xdb, 0xca, 0xc6, 0xce, 0xcd, 0xc4, 0x0a, 0x00 };/* 输出半角字符串并退出应用程序 */api_putstr0(s);api_end();
}
lines
/* 应用程序 lines.c,在新建窗口中绘制线条 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{char *buf;int win, i;/* 初始化应用程序内存分配管理;分配160*100字节内存用作新建窗口画面缓冲区;* 打开160*100大小标题为lines无透明色的窗口。*/api_initmalloc();buf = api_malloc(160 * 100);win = api_openwin(buf, 160, 100, -1, "lines");/* 在win所管理窗口中绘制线条(win+1作甚)并刷新相应画面区域 */for (i = 0; i < 8; i++) {api_linewin(win + 1,  8, 26, 77, i * 9 + 26, i);api_linewin(win + 1, 88, 26, i * 9 + 88, 89, i);}api_refreshwin(win,  6, 26, 154, 90);/* 当前窗口接收到回车时关闭窗口并退出应用 */for (;;) {if (api_getkey(1) == 0x0a) {break;}}api_closewin(win);api_end();
}
mmlplay
/* mmlplay.c,一个音乐播放器应用程序 *//* 粗略理解 haribote mml播放器所播放的音乐文件。* C大调 12345678 与 CDEFGABC 对应,音符后 + 或 # 表示升高半音, - 表示降低伴音;* 再后面加上数字,4-4分音符;8-8分音符;1-全音符....* O 设定八度音区....* 如 mmldata/*.org。* * 各音与计算机蜂鸣器的映射关系见 HariMain tonetable 粗略理解。*//* 系统调用声明头文件,C标准库头文件 */
#include "apilib.h"
#include <string.h>/* strlen */int strtol(char *s, char **endp, int base);void waittimer(int timer, int time);
void end(char *s);void HariMain(void)
{char winbuf[256 * 112], txtbuf[100 * 1024];char s[32], *p, *r;int win, timer, i, j, t = 120, l = 192 / 4, o = 4, q = 7, note_old = 0;/* 音阶与频率映射静态表,* 如 O4A 映射 440000,* 第16八度的A与1802240000映射,* 以下为第16八度的映射表。*/static int tonetable[12] = {1071618315, 1135340056, 1202850889, 1274376125, 1350154473, 1430438836,1515497155, 1605613306, 1701088041, 1802240000, 1909406767, 2022946002};static int notetable[7] = { +9, +11, +0 /* C */, +2, +4, +5, +7 };/* 命令行解析 */api_cmdline(s, 30);for (p = s; *p > ' '; p++) { }for (; *p == ' '; p++) { }i = strlen(p);if (i > 12) {
file_error:end("file open error.\n");}if (i == 0) {end(0);}/* 准备播放音乐文件的窗口 */win = api_openwin(winbuf, 256, 112, -1, "mmlplay");api_putstrwin(win, 128, 32, 0, i, p);api_boxfilwin(win, 8, 60, 247,  76, 7);api_boxfilwin(win, 6, 86, 249, 105, 7);/* 打开音乐文件 */i = api_fopen(p);if (i == 0) {goto file_error;}/* 获取音乐文件大小 */j = api_fsize(i, 0);if (j >= 100 * 1024) {j = 100 * 1024 - 1;}/* 读取音乐文件内容 */api_fread(txtbuf, j, i);api_fclose(i);txtbuf[j] = 0;r = txtbuf;i = 0;/* 解析特定格式的音乐文件 */for (p = txtbuf; *p != 0; p++) {if (i == 0 && *p > ' ') {if (*p == '/') {if (p[1] == '*') {i = 1;} else if (p[1] == '/') {i = 2;} else {*r = *p;if ('a' <= *p && *p <= 'z') {*r += 'A' - 'a';}r++;}} else if (*p == 0x22) {*r = *p;r++;i = 3;} else {*r = *p;r++;}} else if (i == 1 && *p == '*' && p[1] == '/') {p++;i = 0;} else if (i == 2 && *p == 0x0a) {i = 0;} else if (i == 3) {*r = *p;r++;if (*p == 0x22) {i = 0;} else if (*p == '%') {p++;*r = *p;r++;}}}*r = 0;/* 准备定时器 */timer = api_alloctimer();api_inittimer(timer, 128);/* 音乐播放主循环 */p = txtbuf;for (;;) {/* 根据音符和休止符与字符的映射关系,计算频率 */if (('A' <= *p && *p <= 'G') || *p == 'R') {if (*p == 'R') {i = 0;s[0] = 0;} else {i = o * 12 + notetable[*p - 'A'] + 12;s[0] = 'O';s[1] = '0' + o;s[2] = *p;s[3] = ' ';s[4] = 0;}p++;if (*p == '+' || *p == '-' || *p == '#') {s[3] = *p;if (*p == '-') {i--;} else {i++;}p++;}if (i != note_old) {api_boxfilwin(win + 1, 32, 36, 63, 51, 8);if (s[0] != 0) {api_putstrwin(win + 1, 32, 36, 10, 4, s);}api_refreshwin(win, 32, 36, 64, 52);if (28 <= note_old && note_old <= 107) {api_boxfilwin(win, (note_old - 28) * 3 + 8, 60, (note_old - 28) * 3 + 10,  76, 7);}if (28 <= i && i <= 107) {api_boxfilwin(win, (i - 28) * 3 + 8, 60, (i - 28) * 3 + 10,  76, 4);}if (s[0] != 0) {api_beep(tonetable[i % 12] >> (17 - i / 12));} else {api_beep(0);}note_old = i;}/* 根据音长与数字的映射关系,计算音长 */if ('0' <= *p && *p <= '9') {i = 192 / strtol(p, &p, 10);} else {i = l;}for (; *p == '.'; ) {p++;i += i / 2;}i *= (60 * 100 / 48);i /= t;if (s[0] != 0 && q < 8 && *p != '&') {j = i * q / 8;waittimer(timer, j);api_boxfilwin(win, 32, 36, 63, 51, 8);if (28 <= note_old && note_old <= 107) {api_boxfilwin(win, (note_old - 28) * 3 + 8, 60, (note_old - 28) * 3 + 10,  76, 7);}note_old = 0;api_beep(0);} else {j = 0;if (*p == '&') {p++;}}waittimer(timer, i - j);} else if (*p == '<') { /* 8度-- */p++;o--;} else if (*p == '>') { /* 8度++ */p++;o++;} else if (*p == 'O') { /* 8度 */o = strtol(p + 1, &p, 10);} else if (*p == 'Q') { /* Q */q = strtol(p + 1, &p, 10);} else if (*p == 'L') { /* 默认音长 */ l = strtol(p + 1, &p, 10);if (l == 0) {goto syntax_error;}l = 192 / l;for (; *p == '.'; ) {p++;l += l / 2;}} else if (*p == 'T') { /* 速度 */t = strtol(p + 1, &p, 10);} else if (*p == '$') { /* 扩展 */if (p[1] == 'K') {  /* 卡拉OK命令 */p += 2;for (; *p != 0x22; p++) {if (*p == 0) {goto syntax_error;}}p++;for (i = 0; i < 32; i++) {if (*p == 0) {goto syntax_error;}if (*p == 0x22) {break;}if (*p == '%') {s[i] = p[1];p += 2;} else {s[i] = *p;p++;}}if (i > 30) {end("karaoke too long.\n");}api_boxfilwin(win + 1, 8, 88, 247, 103, 7);s[i] = 0;if (i != 0) {api_putstrwin(win + 1, 128 - i * 4, 88, 0, i, s);}api_refreshwin(win, 8, 88, 248, 104);}for (; *p != ';'; p++) {if (*p == 0) {goto syntax_error;}}p++;} else if (*p == 0) {p = txtbuf;} else {
syntax_error:end("mml syntax error.\n");}}
}/* 设置超时时间为time(单位10ms) */
void waittimer(int timer, int time)
{int i;api_settimer(timer, time);for (;;) {i = api_getkey(1);if (i == 'Q' || i == 'q') {api_beep(0);api_end();}if (i == 128) {return;}}
}
/* 输出s,关闭蜂鸣,结束应用程序 */
void end(char *s)
{if (s != 0) {api_putstr0(s);}api_beep(0);api_end();
}
noodle
/* 应用程序 noodle.c,在新建应用窗口中计时 *//* 标准库头文件;系统调用声明头文件 */
#include <stdio.h>
#include "apilib.h"void HariMain(void)
{char *buf, s[12];int win, timer, sec = 0, min = 0, hou = 0;/* 初始化应用内存分配;分配150*150字节内存用作窗口画面缓冲区;* 打开150*150大小标题为noodle无透明色窗口;分配并初始化定时器。*/api_initmalloc();buf = api_malloc(150 * 50);win = api_openwin(buf, 150, 50, -1, "noodle");timer = api_alloctimer();api_inittimer(timer, 128);for (;;) {sprintf(s, "%5d:%02d:%02d", hou, min, sec);/* win所管理窗口[(28,27),(115,41)]区域绘制色号为7的矩形 */api_boxfilwin(win, 28, 27, 115, 41, 7);/* 从(28,27)处以色号0输出s所指字符串 */api_putstrwin(win, 28, 27, 0, 11, s);/* 设置定时器超时时间为1s,任意键可退出本循环 */api_settimer(timer, 100);if (api_getkey(1) != 128) {break;}/* 更新秒,分,时 */sec++;if (sec == 60) {sec = 0;min++;if (min == 60) {min = 0;hou++;}}}/* 任意键退出循环后退出本应用程序 */api_end();
}
notrec
/* 应用程序 notrec.c,  *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{int win;char buf[150 * 70];/* 打开150*70大小标题为notrec透明色为255的窗口,* 在该窗口上绘制几个矩形区域。*/win = api_openwin(buf, 150, 70, 255, "notrec");api_boxfilwin(win,   0, 50,  34, 69, 255);api_boxfilwin(win, 115, 50, 149, 69, 255);api_boxfilwin(win,  50, 30,  99, 49, 255);/* 回车退出本应用程序 */for (;;) {if (api_getkey(1) == 0x0a) {break;}}api_end();
}
sosu
/* 应用程序 sosu.c,在当前终端显示[1,1000]间的素数 *//* 标准库头文件;系统调用声明头文件 */
#include <stdio.h>
#include "apilib.h"#define MAX 1000void HariMain(void)
{char flag[MAX], s[8];int i, j;for (i = 0; i < MAX; i++) {flag[i] = 0;}for (i = 2; i < MAX; i++) {if (flag[i] == 0) {sprintf(s, "%d ", i);api_putstr0(s);/* 标记当前素数的倍数不予显示 */for (j = i * 2; j < MAX; j += i) {flag[j] = 1;}}}/* 退出应用程序 */api_end();
}
sosu2
/* 应用程序 sosu2.c,在当前终端显示[1,10000]间的素数 *//* 标准库头文件;系统调用声明头文件 */
#include <stdio.h>
#include "apilib.h"#define MAX 10000void HariMain(void)
{char flag[MAX], s[8];int i, j;for (i = 0; i < MAX; i++) {flag[i] = 0;}for (i = 2; i < MAX; i++) {if (flag[i] == 0) {sprintf(s, "%d ", i);api_putstr0(s);/* 标记当前素数的倍数不予显示 */for (j = i * 2; j < MAX; j += i) {flag[j] = 1;}}}/* 退出应用程序 */api_end();
}
sosu3
/* 应用程序 sosu3.c,在当前终端显示[1,10000]间的素数 *//* 标准库头文件;系统调用声明头文件 */
#include <stdio.h>
#include "apilib.h"#define MAX 10000void HariMain(void)
{char *flag, s[8];int i, j;/* 初始化内存管理;分配MAX字节堆内存 */api_initmalloc();flag = api_malloc(MAX);for (i = 0; i < MAX; i++) {flag[i] = 0;}for (i = 2; i < MAX; i++) {if (flag[i] == 0) {sprintf(s, "%d ", i);api_putstr0(s);/* 标记当前素数的倍数不予显示 */for (j = i * 2; j < MAX; j += i) {flag[j] = 1;}}}/* 结束应用程序 */api_end();
}
star1
/* 应用程序 star1.c, *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{char *buf;int win;/* 初始化应用程序内存分配;分配150*100字节内存用作窗口画面缓冲区;* 创建150*100大小标题为star1无透明色的窗口,在窗口* [(6,26),(143,93)]绘制色号为0的矩形,在窗口(75,59)处绘制色号为3的点。*/api_initmalloc();buf = api_malloc(150 * 100);win = api_openwin(buf, 150, 100, -1, "star1");api_boxfilwin(win,  6, 26, 143, 93, 0);api_point(win, 75, 59, 3);/* 回车退出本应用程序 */for (;;) {if (api_getkey(1) == 0x0a) {break;}}api_end();
}
stars
/* 应用程序 stars.c, 在新建窗口指定区域随机描绘点 *//* 系统调用声明头文件 */
#include "apilib.h"/* 声明C标准库中的 rand()函数 */
int rand(void);void HariMain(void)
{char *buf;int win, i, x, y;/* 初始化应用内存分配;分配150*100字节用作窗口画面缓冲区;* 新建150*100大小标题为stars无透明色的窗口;* 在窗口[(6,26),(143,93)]区域绘制色号为0的矩形。*/api_initmalloc();buf = api_malloc(150 * 100);win = api_openwin(buf, 150, 100, -1, "stars");api_boxfilwin(win,  6, 26, 143, 93, 0);/* 在矩形区域随机位置描绘50个色号为3的点(星星) */for (i = 0; i < 50; i++) {x = (rand() % 137) +  6;y = (rand() %  67) + 26;api_point(win, x, y, 3;}/* 回车结束本应用程序 */for (;;) {if (api_getkey(1) == 0x0a) {break;}}api_end();
}
stars2
/* 应用程序 stars2.c, 在新建窗口指定区域随机描绘点 *//* 系统调用声明头文件 */
#include "apilib.h"/* 声明C标准库中的 rand()函数 */
int rand(void);void HariMain(void)
{char *buf;int win, i, x, y;/* 初始化应用内存分配;分配150*100字节用作新建窗口画面信息缓冲区;* 新建150*100大小标题为stars2无透明色窗口,在窗口[(6,26),(143,93)]绘制色号为0的矩形。*/api_initmalloc();buf = api_malloc(150 * 100);win = api_openwin(buf, 150, 100, -1, "stars2");api_boxfilwin(win + 1,  6, 26, 143, 93, 0;/* 在矩形区域随机位置描绘50个色号为3的点(星星)并刷新该区域画面信息 */for (i = 0; i < 50; i++) {x = (rand() % 137) +  6;y = (rand() %  67) + 26;api_point(win + 1, x, y, 3);}api_refreshwin(win,  6, 26, 144, 94);/* 回车结束本应用程序 */for (;;) {if (api_getkey(1) == 0x0a) {break;}}api_end();
}
tview
/* tview.c,一个文本阅读器应用程序 *//* 系统调用声明头文件,C标准库头文件 */
#include "apilib.h"
#include <stdio.h>int strtol(char *s, char **endp, int base);char *skipspace(char *p);
void textview(int win, int w, int h, int xskip, char *p, int tab, int lang);
char *lineview(int win, int w, int y, int xskip, unsigned char *p, int tab, int lang);
int puttab(int x, int w, int xskip, char *s, int tab);void HariMain(void)
{char winbuf[1024 * 757], txtbuf[240 * 1024];int w = 30, h = 10, t = 4, spd_x = 1, spd_y = 1;int win, i, j, lang = api_getlang(), xskip = 0;char s[30], *p, *q = 0, *r = 0;/*解析命令行参数 */api_cmdline(s, 30);for (p = s; *p > ' '; p++) { }for (; *p != 0; ) {p = skipspace(p);if (*p == '-') {if (p[1] == 'w') {w = strtol(p + 2, &p, 0);if (w < 20) {w = 20;}if (w > 126) {w = 126;}} else if (p[1] == 'h') {h = strtol(p + 2, &p, 0);if (h < 1) {h = 1;}if (h > 45) {h = 45;}} else if (p[1] == 't') {t = strtol(p + 2, &p, 0);if (t < 1) {t = 4;}} else {
err:api_putstr0(" >tview file [-w30 -h10 -t4]\n");api_end();}/* 成功找到文件名 */} else {if (q != 0) {goto err;}q = p;for (; *p > ' '; p++) { }r = p;}}if (q == 0) {goto err;}/* 准备窗口 */win = api_openwin(winbuf, w * 8 + 16, h * 16 + 37, -1, "tview");api_boxfilwin(win, 6, 27, w * 8 + 9, h * 16 + 30, 7);/* 载入文件 */*r = 0;i = api_fopen(q);if (i == 0) {api_putstr0("file open error.\n");api_end();}j = api_fsize(i, 0);if (j >= 240 * 1024 - 1) {j = 240 * 1024 - 2;}txtbuf[0] = 0x0a;api_fread(txtbuf + 1, j, i);api_fclose(i);txtbuf[j + 1] = 0;q = txtbuf + 1;for (p = txtbuf + 1; *p != 0; p++) {if (*p != 0x0d) {*q = *p;q++;}}*q = 0;/* 显示内容的主程序 */p = txtbuf + 1;for (;;) {textview(win, w, h, xskip, p, t, lang);i = api_getkey(1);if (i == 'Q' || i == 'q') {api_end();}if ('A' <= i && i <= 'F') {spd_x = 1 << (i - 'A');  /* 1, 2, 4, 8, 16, 32 */}if ('a' <= i && i <= 'f') {spd_y = 1 << (i - 'a');    /* 1, 2, 4, 8, 16, 32 */}if (i == '<' && t > 1) {t /= 2;}if (i == '>' && t < 256) {t *= 2;}if (i == '4') {for (;;) {xskip -= spd_x;if (xskip < 0) {xskip = 0;}if (api_getkey(0) != '4') {break;}}}if (i == '6') {for (;;) {xskip += spd_x;if (api_getkey(0) != '6') {break;}}}if (i == '8') {for (;;) {for (j = 0; j < spd_y; j++) {if (p == txtbuf + 1) {break;}for (p--; p[-1] != 0x0a; p--) { }}if (api_getkey(0) != '8') {break;}}}if (i == '2') {for (;;) {for (j = 0; j < spd_y; j++) {for (q = p; *q != 0 && *q != 0x0a; q++) { }if (*q == 0) {break;}p = q + 1;}if (api_getkey(0) != '2') {break;}}}}
}char *skipspace(char *p)
{for (; *p == ' '; p++) { }return p;
}void textview(int win, int w, int h, int xskip, char *p, int tab, int lang)
{int i;api_boxfilwin(win + 1, 8, 29, w * 8 + 7, h * 16 + 28, 7);for (i = 0; i < h; i++) {p = lineview(win, w, i * 16 + 29, xskip, p, tab, lang);}api_refreshwin(win, 8, 29, w * 8 + 8, h * 16 + 29);return;
}char *lineview(int win, int w, int y, int xskip, unsigned char *p, int tab, int lang)
{int x = - xskip;char s[130];for (;;) {if (*p == 0) {break;}if (*p == 0x0a) {p++;break;}if (lang == 0) {    /* ASCII */if (*p == 0x09) {x = puttab(x, w, xskip, s, tab);} else {if (0 <= x && x < w) {s[x] = *p;}x++;}p++;}if (lang == 1) {    /* SJIS */if (*p == 0x09) {x = puttab(x, w, xskip, s, tab);p++;} else if ((0x81 <= *p && *p <= 0x9f) || (0xe0 <= *p && *p <= 0xfc)) {if (x == -1) {s[0] = ' ';}if (0 <= x && x < w - 1) {s[x]     = *p;s[x + 1] = p[1];}if (x == w - 1) {s[x] = ' ';} x += 2;p += 2;} else {if (0 <= x && x < w) {s[x] = *p;}x++;p++;}}if (lang == 2) {    /* EUC */if (*p == 0x09) {x = puttab(x, w, xskip, s, tab);p++;} else if (0xa1 <= *p && *p <= 0xfe) {/if (x == -1) {s[0] = ' ';}if (0 <= x && x < w - 1) {s[x]     = *p;s[x + 1] = p[1];}if (x == w - 1) {s[x] = ' ';} x += 2;p += 2;} else {if (0 <= x && x < w) {s[x] = *p;}x++;p++;}}}if (x > w) {x = w;}if (x > 0) {s[x] = 0;api_putstrwin(win + 1, 8, y, 0, x, s);}return p;
}int puttab(int x, int w, int xskip, char *s, int tab)
{for (;;) {if (0 <= x && x < w) {s[x] = ' ';}x++;if ((x + xskip) % tab == 0) {break;}}return x;
}
type
/* 应用程序 type.c,将指定文件内容输出到当前终端 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{int fh;char c, cmdline[30], *p;/* 获取当前任务的输入 */api_cmdline(cmdline, 30);for (p = cmdline; *p > ' '; p++) { }for (; *p == ' '; p++) { }/* 打开指定文件并读取其内容输出到当前终端上后退出应用程序 */fh = api_fopen(p);if (fh != 0) {for (;;) {if (api_fread(&c, 1, fh) == 0) {break;}api_putchar(c);}} else {api_putstr0("File not found.\n");}api_end();
}
walk
/* 应用程序 walk.c,用'*'移动标识键盘输入 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{char *buf;int win, i, x, y;/* 初始化应用程序内存分配;分配160*100字节用作新建窗口画面信息缓冲区;* 新建160*100大小标题为walk无透明色的窗口,在窗口[(4,24),(155,95)]区* 域绘制色号为0的矩形,在窗口[76,56]位置处以色号3显示1个'*'号。*/api_initmalloc();buf = api_malloc(160 * 100);win = api_openwin(buf, 160, 100, -1, "walk");api_boxfilwin(win, 4, 24, 155, 95, 0);x = 76;y = 56;api_putstrwin(win, x, y, 3 1, "*");for (;;) {/* 获取向本任务输入的数据, */i = api_getkey(1);/* 在窗口(x,y)位置以色号0描绘1个'*'号 */api_putstrwin(win, x, y, 0 /* ͕ */, 1, "*");/* 当输入'4'时, 横坐标左移8个像素点;* 当输入'6'时, 横坐标右移8个像素点;* 当输入'8'时, 纵坐标下移8个像素点;* 当输入'2'时, 纵坐标上移8个像素点。* 输入回车结束循环。*/if (i == '4' && x >   4) { x -= 8; }if (i == '6' && x < 148) { x += 8; }if (i == '8' && y >  24) { y -= 8; }if (i == '2' && y <  80) { y += 8; }if (i == 0x0a) { break; }/* 最新移动点以色号3绘制一个'*'符号 */api_putstrwin(win, x, y, 3 /* ɩ */, 1, "*");}/* 关闭应用程序窗口退出应用程序 */api_closewin(win);api_end();
}
winhelo
/* 应用程序 winhelo.c,新建标题为hello应用程序窗口 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{int win;char buf[150 * 50];/* 新建150*150大小标题为hello无透明色窗口,* 在键入回车时退出。*/win = api_openwin(buf, 150, 50, -1, "hello");for (;;) {if (api_getkey(1) == 0x0a) {break;}}api_end();
}
winhelo2
/* 应用程序 winhelo2.c,在新建窗口中显示指定字符串 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{int win;char buf[150 * 50];/* 新建150*50大小标题为hello无透明色窗口;* 在窗口[(8,36),(141,43]区域以色号3绘制矩形;* 在窗口(28,28)处以色号0显示12个字符hello,world。* 键入回车结束应用程序。*/win = api_openwin(buf, 150, 50, -1, "hello");api_boxfilwin(win,  8, 36, 141, 43, 3;api_putstrwin(win, 28, 28, 0, 12, "hello, world");for (;;) {if (api_getkey(1) == 0x0a) {break;}}api_end();
}
winhelo3
/* 应用程序 winhelo3.c,在新建窗口中显示指定字符串 *//* 系统调用声明头文件 */
#include "apilib.h"void HariMain(void)
{char *buf;int win;/* 初始化应用程序内存分配,分配150*50字节内存用作窗口画面信息缓冲区;* 在窗口[(8,36),(141,43]区域以色号6绘制矩形;* 在窗口(28,28)处以色号0显示12个字符hello,world。* 键入回车结束应用程序。*/api_initmalloc();buf = api_malloc(150 * 50);win = api_openwin(buf, 150, 50, -1, "hello");api_boxfilwin(win,  8, 36, 141, 43, 6 );api_putstrwin(win, 28, 28, 0, 12, "hello, world");for (;;) {if (api_getkey(1) == 0x0a) {break;}}api_end();
}

haribote系统调用 工程管理及应用程序阅读注释相关推荐

  1. linux0.11磁盘映像制作及其剩余程序阅读注释笔记

    [ 1] linux0.11引导程序阅读注释. [ 2] linux0.11由实模式进入保护模式程序阅读注释 . [ 3] linux0.11护模式初始化程序阅读注释. [ 4] linux0.11主 ...

  2. haribote bootpack.c 主任务程序代码阅读注释

    [ 1] haribote ipl09.nas 引导程序阅读注释. [ 2] haribote asmhead.nas 从实模式进入保护模式程序阅读注释. [ 3] haribote dsctbl.c ...

  3. haribote mouse.c 鼠标管理程序阅读注释

    [ 1] haribote ipl09.nas 引导程序阅读注释. [ 2] haribote asmhead.nas 从实模式进入保护模式程序阅读注释. [ 3] haribote dsctbl.c ...

  4. linux0.11多任务管理程序阅读注释笔记

    [ 1] linux0.11引导程序阅读注释. [ 2] linux0.11由实模式进入保护模式程序阅读注释 . [ 3] linux0.11护模式初始化程序阅读注释. [ 4] linux0.11主 ...

  5. linux0.11字符设备驱动及访问请求管理程序阅读注释笔记

    [ 1] linux0.11引导程序阅读注释. [ 2] linux0.11由实模式进入保护模式程序阅读注释 . [ 3] linux0.11护模式初始化程序阅读注释. [ 4] linux0.11主 ...

  6. linux0.11缓冲区管理程序阅读注释笔记

    [ 1] linux0.11引导程序阅读注释. [ 2] linux0.11由实模式进入保护模式程序阅读注释 . [ 3] linux0.11护模式初始化程序阅读注释. [ 4] linux0.11主 ...

  7. 水利水电工程管理与实务电子版习题_水利水电工程管理与实务复习题集

    内容概要 为了帮助全国二级建造师执业资格考试水利水电专业应考人员进一步理解考试大纲和考试用书,加深对考点和知识点的理解和掌握,提高复习效率,巩固复习效果,提高应考人员的解题能力,本书编委会依据< ...

  8. 网络工程管理 第七章 应用层协议 万维网 DNS 电子邮件 FTP DHCP TELNET

    网络工程管理 第七章 应用层协议 应用层的具体内容就是规定应用进程在通信时所遵循的协议. 应用层的许多协议都是基于客户/服务器方式.客户是服务请求方,服务器是服务提供方. 常见的应用层协议 TCP/I ...

  9. 工程管理中的工程技术

    想想要贴21张图片,我还是放弃了. 请移步[https://zhuanlan.zhihu.com/p/31533288?group_id=919258106568839168]阅读有图的版本. 无图的 ...

最新文章

  1. oracle 统计信息字典表,Oracle数据字典表查询
  2. IBM投资4000万美圆,加强对SAP®应用的支持
  3. 3、leetcode35 搜索插入位置**
  4. 深入Managed DirectX9(二)
  5. Vue 高德地图使用总结
  6. 钢材规格解读的软件_东洲废旧机械设备回收整厂拆除详细解读
  7. excel导出_学习笔记—— 前端导出excel
  8. atitit.流程标准化--- mysql启动不起来的排查流程attilax总结
  9. 纪念工作一周年,也纪念我的blog开张。
  10. 类加载器的理解——基于Launcher类
  11. 10种优化Mac以获得最佳性能的简便方法
  12. 置信区间、置信水平、边际误差
  13. windows cmd 添加路由命令
  14. Source Monitor的使用
  15. ​​​​​​​墨画子卿第三章:初心第2节:回家
  16. 天正坐标标注显示不全_CAD命令栏坐标显示不全
  17. Android图片内存的计算
  18. VSC/SMC(十四)——全局快速Terminal滑模控制(含程序模型)
  19. Sequelize 大于_巴菲特买股三原则:毛利率大于30%+ROE大于15%+现金流大于100%
  20. 技嘉B360M AORUS PRO 小雕+8400 黑苹果安装 EFI 10.13.6-10.15.4

热门文章

  1. 男人都是流氓,女人都是破鞋。
  2. 1、TCP/IP体系结构
  3. 电脑录屏怎么录?人人都会用的录屏方法
  4. html可视化数学公式编辑,所见即所得的jQuery数学公式编辑器插件
  5. PMP认证的通过率怎么样?
  6. Android 微信分享后点击留在微信,仍然跳到app的解决方法
  7. ELK集群部署(八)之监控nginx日志
  8. Windows系统消息机制的详细理解!
  9. 红米手机android测试,大概是跟红米杠上了—红米note5体验测评(非专业只写个人体验)...
  10. 夺命金背后的真实香港情况