• 30天自制操作系统(第28天)


    28.1 alloca

    __alloca 会在下述情况下被 C 语言的程序调用(采用 near-CALL 的方式)。
    1、要执行的操作从栈中分配 EAX 个字节的内存空间( ESP -= EAX;
    2、要遵守的规则不能改变 ECX EDX EBX EBP ESI EDI的值(可以临时改变它们的值,但要使用 PUSH/POP 来复原)
    RET 返回的地址保存在了ESP(“RET”指令实际上相当于“POP EIP”,“POP EIP”实际上又相当于下面两条指令:MOV EIP,[ESP]    ADD ESP,4)。为实现类似RET功能指令,所以编写了如下 __alloca函数指令。
    __alloca:
            SUB  ESP,EAX
            ADD  ESP,4
            JMP  DWORD [ESP+EAX-4] ; 代替 RET
    注:C语言中,在函数外部声明的变量和带static的变量一样,都会被解释为DB和RESB;在函数内部不带static声明的变量则会从栈中分配空间。

    28.2 文件操作API 

    需要实现的功能:打开、定位、读取、写入和关闭文件。思路:打开文件时需要指定文件名,如果打开成功,操作系统将返回文件句柄。在随后的操作中,只要提供这个文件句柄就可以进行读写操作了,操作结束后将文件关闭。读取和写入API基本上需要指定需要读取(写入)的数据长度以及内存地址,文件的内容会被传送至内存(写入操作时是由内存传送至文件)。
    打开文件
    关闭文件
    文件定位
    获取文件大小
    文件读取
    EDX=21
    EBX= 文件名
    EAX= 文件句柄(为 0 时表示打开失败)(由操作系统返回)
    EDX=22
    EAX= 文件句柄
    EDX=23
    EAX= 文件句柄
    ECX= 定位模式
            =0:定位的起点为文件开头
            =1:定位的起点为当前的访问位置
            =2:定位的起点为文件末尾
    EBX= 定位偏移量
    EDX=24
    EAX= 文件句柄
    ECX= 文件大小获取模式
           =0:普通文件大小
           =1:当前读取位置从文件开头起算的偏移量
           =2:当前读取位置从文件末尾起算的偏移量
    EAX= 文件大小(由操作系统返回)
    EDX=25
    EAX= 文件句柄
    EBX= 缓冲区地址
    ECX= 最大读取字节数
    EAX= 本次读取到的字节数(由操作系统返回)
    1. /* bootpack.h */
    2. struct TASK {
    3. (中略)
    4. int ds_base, cons_stack;
    5. struct FILEHANDLE *fhandle; /*从此开始*/
    6. int *fat; /*到此结束*/
    7. };
    8. struct FILEHANDLE { /*从此开始*/
    9. char *buf;
    10. int size;
    11. int pos;
    12. }; /*到此结束*/
    13. /* console.c */
    14. void console_task(struct SHEET *sheet, int memtotal)
    15. {
    16. (中略)
    17. struct FILEHANDLE fhandle[8];
    18. (中略)
    19. for (i = 0; i < 8; i++)
    20. fhandle[i].buf = 0; /*未使用标记*/
    21. task->fhandle = fhandle;
    22. task->fat = fat;
    23. (中略)
    24. }
    25. if (finfo->size >= 36 && strncmp(p + 4, "Hari", 4) == 0 && *p == 0x00) {//cmd_app代码片段
    26. (中略)
    27. start_app(0x1b, 0 * 8 + 4, esp, 1 * 8 + 4, &(task->tss.esp0));
    28. (中略)
    29. for (i = 0; i < 8; i++) { /*将未关闭的文件关闭*/ /*从此开始*/
    30. if (task->fhandle[i].buf != 0) {
    31. memman_free_4k(memman, (int) task->fhandle[i].buf, task->fhandle[i].size);
    32. task->fhandle[i].buf = 0;
    33. }
    34. } /*到此结束*/
    35. (中略)
    36. }
    37. int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax){
    38. (中略)
    39. struct FILEINFO *finfo;
    40. struct FILEHANDLE *fh;
    41. struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
    42. (中略)
    43. /*开始*/}else if(edx == 21){//打开文件
    44. for(i = 0; i < 8; i++){
    45. if(task->fhandle[i].buf == 0)
    46. break;
    47. }
    48. fh = &task->fhandle[i];
    49. reg[7] = 0;
    50. if(i < 8){
    51. finfo = file_search((char*)ebx+ds_base, (struct FILEINFO*)(ADR_DISKIMG+0x002600), 224);
    52. if(finfo != 0){
    53. reg[7] = (int)fh;
    54. fh->buf = (char *) memman_alloc_4k(memman, finfo->size);
    55. fh->size = finfo->size;
    56. fh->pos = 0;
    57. file_loadfile(finfo->clustno, finfo->size, fh->buf, task->fat, (char *)
    58. (ADR_DISKIMG+0x003e00));
    59. }
    60. }
    61. }else if(edx == 22){//关闭文件
    62. fh = (struct FILEHANDLE*)eax;
    63. memman_free_4k(memman, (int)fh->buf, fh->size);//与打开文件操作中的memman_alloc_4k对应
    64. fh->buf = 0;
    65. }else if(edx == 23){//文件定位
    66. fh = (struct FILEHANDLE*)eax;
    67. if(ecx == 0){//定位的起点为文件开头
    68. fh->pos = ebx;
    69. }else if(ecx == 1){//定位的起点为当前的访问位置
    70. fh->pos += ebx;
    71. }else if(ecx == 2){//定位的起点为文件末尾
    72. fh->pos = fh->size + ebx;
    73. }
    74. if(fh->pos < 0)fh->pos = 0;
    75. if(fh->pos > fh->size)fh->pos = fh->size;
    76. }else if(edx == 24){//获取文件大小
    77. fh = (struct FILEHANDLE*)eax;
    78. if(ecx == 0){//普通文件大小
    79. reg[7] = fh->size;
    80. }else if(ecx == 1){//当前读取位置从文件开头起算的偏移量
    81. reg[7] = fh->pos;
    82. }else if(ecx == 2){//当前读取位置从文件末尾起算的偏移量
    83. reg[7] = fh->pos - fh->size;
    84. }
    85. }else if(edx == 25){//文件读取,写入到ebx缓存区中
    86. fh = (struct FILEHANDLE*)eax;
    87. for(i = 0; i < ecx; i++){
    88. if(fh->pos == fh->size)break;
    89. *((char *) ebx + ds_base + i) = fh->buf[fh->pos];
    90. fh->pos++;
    91. }
    92. reg[7] = i;
    93. /*结束*/}
    94. return 0;
    95. }

    28.3 命令行API 

    需要实现的功能:在用户输入“type ***.nas”这样的命令时获取后面的文件名。
    获取命令行
    EDX=26
    EBX= 存放命令行内容的地址
    ECX= 最多可存放多少字节
    EAX= 实际存放了多少字节(由操作系统返回)
    1. /* a_nask.nas */
    2. _api_cmdline: ; int api_cmdline(char *buf, int maxsize);
    3. PUSH EBX
    4. MOV EDX,26
    5. MOV ECX,[ESP+12] ; maxsize
    6. MOV EBX,[ESP+8] ; buf
    7. INT 0x40
    8. POP EBX
    9. RET
    10. /* bootpack.h */
    11. struct TASK {
    12. (中略)
    13. char *cmdline;
    14. };
    15. /* console.c */
    16. void console_task(struct SHEET *sheet, int memtotal)
    17. {
    18. (中略)
    19. task->cons = &cons;
    20. task->cmdline = cmdline; /*这里!*/
    21. (中略)
    22. }
    23. int *hrb_api(int edi, int esi, int ebp, int esp, int ebx, int edx, int ecx, int eax)
    24. {
    25. (中略)
    26. } else if (edx == 26) {
    27. i = 0;
    28. for (;;) {
    29. *((char *) ebx + ds_base + i) = task->cmdline[i];
    30. if (task->cmdline[i] == 0) {
    31. break;
    32. }
    33. if (i >= ecx) {
    34. break;
    35. }
    36. i++;
    37. }
    38. reg[7] = i;
    39. }
    40. return 0;
    41. }
  • 相关阅读:
    操作系统内存换入-请求调页---14
    Netty解决粘包和拆包问题的四种方案,简单易懂
    【ES专题】ElasticSearch功能详解与原理剖析
    Harmony 页面之间的跳转
    java毕业设计——基于java+MyBatis+jsp的网上招聘系统设计与实现(毕业论文+程序源码)——网上招聘系统
    java-单列集合List详解
    跟我学Python图像处理丨基于灰度三维图的图像顶帽运算和黑帽运算
    高耗能工厂实现ESG能源管控的策略与实践-天拓四方
    commons-lang3
    Eclipse环境基于HDFS的API进行开发
  • 原文地址:https://blog.csdn.net/Amnesiac_seven/article/details/136506233