您现在的位置是:主页 > news > 网站建设 开发的团队需要几个人/重庆seo排名技术
网站建设 开发的团队需要几个人/重庆seo排名技术
admin2025/5/18 9:48:45【news】
简介网站建设 开发的团队需要几个人,重庆seo排名技术,59一起做网站,wordpress页面发布失败为什么开发操作系统,如何从汇编语言程序进入C语言内核程序,也是一个难点。对于这块内容,没有哪本讲述操作系统的书说得很清楚。经过本人的不懈摸索后得到了普遍方法,本章就来详细记录并说明。一、操作系统程序结构(一&#x…

开发操作系统,如何从汇编语言程序进入C语言内核程序,也是一个难点。对于这块内容,没有哪本讲述操作系统的书说得很清楚。经过本人的不懈摸索后得到了普遍方法,本章就来详细记录并说明。
一、操作系统程序结构
(一)Linux系统结构

(二)我的程序结构
基于Linux的结构,我通过如下的方式来组织操作系统程序文件:

具体的编译和链接工具,我沿用的是计算机自制操作系统(Windows篇):
计算机自制操作系统(Windows篇)www.zhihu.com
中的工具,在Windows环境下的有:cc1.exe,gas2nask.exe,nask.exe,obj2bim.exe等。这些工具在《30天》这本书中都有完整版本提供。
(三)文件组织方式
为最大限度的和Linux相仿,我们把操作系统镜像文件Linux.img放到一级目录下,把3个汇编程序文件放在二级目录boot下,把其它内核程序文件放在二级目录kernel下:



二、内核程序开发
进入内核之后,就需要用C语言了,我们先写个简单的main()来测试内核程序:
void printchar(char c,char line_x,char col_y,char corlor);
void printstr(char *s,char start_line_x,char start_col_y,char corlor);
void asmfunc(void);void Main(void)
{char *str="hello";char c1='C';printchar(c1,23,0,0x0c);printstr(str,23,5,0x0c);asmfunc(); /*C调用汇编测试*/ while(1){;}}/*打印一个字符,参数:字符,行号,列号,字符颜色*/
void printchar(char c,char line_x,char col_y,char corlor)
{
*(char *)(0xb8000+line_x*160+2*col_y) =c;
*(char *)(0xb8000+line_x*160+2*col_y+1) =corlor;
}/*打印一个字符串,参数:字符串首地址,开始行号,开始列号,字符颜色*/
void printstr(char *s,char start_line_x,char start_col_y,char corlor)
{do{printchar(*s,start_line_x,start_col_y,corlor);start_col_y++;}while (*(s++)!='0');
}
这个程序实现3个功能:1.C程序打印一个字符"C".2.C程序打印一个字符串"kernel".3.C程序调用汇编程序kernela.asm里的打印功能,打印一个字符"A"。通过全流程编译链接之后,运行结果如下:

为什么’kernel’字符串没有正常显示出来?必须要一步步的分析,首先看main程序的目标代码(obj,待重定位):

会发现:打印字母‘A’,参数传递是用的立即数入栈,而‘kernel'字符串在程序中定义到了堆区(.data),进一步分析最终的机器代码:

会发现'kernel'字符串首地址的参数传递机器代码从68 [00000000]变成了68 [00010000],而我们的操作系统中所有数据类寄存器在进入32位模式之后,全部为0。故这里要成功取到字符串'kernel'的条件是:必须要先把main程序中的“kernel”先放到内存[00010000]=1MB处。这个先决条件,在我们之前的操作系统制作windows篇中已经说过很多遍了,它叫:必须要提前将可执行文件中的所有变量从文件区挪动到可执行文件中规定的堆区。具体到这个hrb可执行文件格式,它规定的堆区地址(同时也是栈地址,通过链接器指定)在下面的位置提出:

为了实现这个功能,我们需要在内核前面的“head”程序中,添加这样一个过程:
call kernel_C_data ;
;对于数据段,先要把内核C程序的所有变量复制到正确内存位置才能运行内核
jmp C_start+0x24 ;
;程序段就不需要复制了(也可复制),直接跳转到入口地址(C程序的main入口)即可。
;因为hrb文件头的长度是0x24,随后便是代码段。
;需要把C程序main()编译链接之后的机器码文件直接贴在此程序机器码的后面;以下子程序为:分析hrb可执行文件的文件头,并从中提取出程序内核入口地址、
;内核程序中所有变量的文件偏移和长度,
;并把所有变量从hrb文件区挪动复制到hrb文件头中指定的堆区内存地址
kernel_C_data:
MOV EBX,C_start ;内核C程序main()开始的内存地址
MOV ECX,[EBX+16] ;内核C程序变量数据长度
ADD ECX,3 ; ECX += 3; 凑足4字节
SHR ECX,2 ; ECX /= 4;
JZ skip ; 没有变量需要传送时
MOV ESI,[EBX+20] ;内核C程序变量数据传送源地址
ADD ESI,EBX
MOV EDI,[EBX+12] ;内核C程序变量数据传送目的地址
;就是hrb文件中指定的变量堆区地址(在hrb文件中也是栈地址,大小由链接器指定)
CALL memcpy
skip: ret;内存复制子程序,以4字节为单位,源地址:ESI。目的地址:EDI。长度: ECX
memcpy: MOV EAX,[ESI]ADD ESI,4 ;以4个字节为单位进行传送 MOV [EDI],EAXADD EDI,4SUB ECX,1JNZ memcpy RET
这样一来,C语言内核程序运行的环境已经全部建立,我们再次验证程序:
