在OSzone论坛有篇帖子问一个编译问题,差不多就是用TC来写系统的可能性,虽然学C才起步,也去看了下,然后自己也去尝试了一下。我用的编辑器是Win-TC 1.9.1,编译器是Turbo C 2.0,感觉WinTC用起来方便些,毕竟是在Win下,对着个黑屏白字总有点感觉不太爽:)
帖子里的代码如下:
void printtext(char *text,int len){
int i;
for(i=1;i<=len;i++){
asm mov ah,0x0e
asm mov al,*text
asm mov bl,7
asm int 0x10
text++;
}
}
int main()
{
printtext("Hello World!",12);
return 0;
}
因为目的是为了写一个系统,所以文本输出函数不能用C的标准输出函数了,而应自己去写一个。但是上面的代码,在TC编译会出错,我把它给改了一下,成功通过编译,改后的代码如下:
void printtext(char *text,int len){
int i;
char c;
for(i=1;i<=len;i++){
c=*text;
asm mov ah,0x0e
asm mov al,c
asm mov bl,7
asm int 0x10
text++;
}
}
int main()
{
printtext("Hello World!",12);
return 0;
}
在printtext函数里加了一个char变量c用来放每个字符,然后在循环的开始读取字符,最后通过内嵌汇编调用BIOS子程序来显示字符。可能是因为内嵌汇编不支持用指针来读取内容的原因,导致原来的那段程序编译出错。
但是作为一个系统,并不能要求程序调用例程的时候去提供字符串的长度,那将是很不方便的,所以,我又把printtext函数改了一下,使它更好用一些,当然,只是“一些”:)
void printf(char *text) {
char c;
c=*text;
while(c!=0) {
asm mov ah,0x0e
asm mov al,c
asm mov bl,7
asm int 0x10
text++;
c=*text;
}
}
这样,就可以只传送一个字符串指针就行了,而不用去指定字符串的长度。
在搞定编译问题之后,我想能不能把它作为一个内核来试试呢,于是我就试着用exe2bin来把这个编译出来的exe转换为bin,不过给我来个错误……于是去WinTC的编译选项里找,然后找到有个内存模式,选择微存贮模式编译出来的exe可以成功转换为bin,估计在这个模式下整个exe只用了一个段,然后exe2bin把它转换成了com格式,为了验证这个猜想,我把生成的kernel.bin改名为kernel.com,在CMD成功运行,证明了我的猜想。
接下来我就准备把这个文件放到软盘映像来测试用这个做内核的可行性,于是我把WarmOS的启动扇区找出来,然后把一些选项改变一下,使这个文件被加载到内存的0x1000处,即中断向量表之后,但我试了好几次没成功,然后才发现忘了com起始处有0x100的偏移……于是把文件加载完成之后的跳转改成:
jmp 0x100:0x100
好了,编译,创建软盘映像,打开VPC,加载,启动,成功!
至此,完成了验证用TC来写一个系统的可能性,结论是:可以。
但也有一些方面需要注意:
1. 用TC编译出来的程序是16位的,也就是说,用TC只能写16位的系统。
2. 采用微存贮模式只能使用一个段,64K,可能也有com的限制,即文件大小在64K以内。
如果有什么错误见谅:)
帖子里的代码如下:
void printtext(char *text,int len){
int i;
for(i=1;i<=len;i++){
asm mov ah,0x0e
asm mov al,*text
asm mov bl,7
asm int 0x10
text++;
}
}
int main()
{
printtext("Hello World!",12);
return 0;
}
因为目的是为了写一个系统,所以文本输出函数不能用C的标准输出函数了,而应自己去写一个。但是上面的代码,在TC编译会出错,我把它给改了一下,成功通过编译,改后的代码如下:
void printtext(char *text,int len){
int i;
char c;
for(i=1;i<=len;i++){
c=*text;
asm mov ah,0x0e
asm mov al,c
asm mov bl,7
asm int 0x10
text++;
}
}
int main()
{
printtext("Hello World!",12);
return 0;
}
在printtext函数里加了一个char变量c用来放每个字符,然后在循环的开始读取字符,最后通过内嵌汇编调用BIOS子程序来显示字符。可能是因为内嵌汇编不支持用指针来读取内容的原因,导致原来的那段程序编译出错。
但是作为一个系统,并不能要求程序调用例程的时候去提供字符串的长度,那将是很不方便的,所以,我又把printtext函数改了一下,使它更好用一些,当然,只是“一些”:)
void printf(char *text) {
char c;
c=*text;
while(c!=0) {
asm mov ah,0x0e
asm mov al,c
asm mov bl,7
asm int 0x10
text++;
c=*text;
}
}
这样,就可以只传送一个字符串指针就行了,而不用去指定字符串的长度。
在搞定编译问题之后,我想能不能把它作为一个内核来试试呢,于是我就试着用exe2bin来把这个编译出来的exe转换为bin,不过给我来个错误……于是去WinTC的编译选项里找,然后找到有个内存模式,选择微存贮模式编译出来的exe可以成功转换为bin,估计在这个模式下整个exe只用了一个段,然后exe2bin把它转换成了com格式,为了验证这个猜想,我把生成的kernel.bin改名为kernel.com,在CMD成功运行,证明了我的猜想。
接下来我就准备把这个文件放到软盘映像来测试用这个做内核的可行性,于是我把WarmOS的启动扇区找出来,然后把一些选项改变一下,使这个文件被加载到内存的0x1000处,即中断向量表之后,但我试了好几次没成功,然后才发现忘了com起始处有0x100的偏移……于是把文件加载完成之后的跳转改成:
jmp 0x100:0x100
好了,编译,创建软盘映像,打开VPC,加载,启动,成功!
至此,完成了验证用TC来写一个系统的可能性,结论是:可以。
但也有一些方面需要注意:
1. 用TC编译出来的程序是16位的,也就是说,用TC只能写16位的系统。
2. 采用微存贮模式只能使用一个段,64K,可能也有com的限制,即文件大小在64K以内。
如果有什么错误见谅:)