一个简单的带图形的内核实践-bochs把玩
Tofloor
poster avatar
Android2013
deepin
2013-02-23 23:00
Author
还没有编写完成, 现在只是花了一个上午写了这些,下午继续.
这张图是简单内核加载起来的效果图, 还没有图形. 是通过引导 bootload.bin 调用 bios 中断 int 13 来加载 目录中的 test_kernel.sys, 文件格式是 fat12, 比较老的文件系统了, 本来今天研究了一下U盘的引导加载内核测试文件,后来没时间了,就暂时不搞了.
test_kernel 设置调用int 10 功能0 来设置0屏幕,然后输出 kernel load. 下一步是要 用C语言.
bochs-test.jpg
如果要编译之前请安装 nasm.
编译命令式: make -> make dd.
test_kernel 编译.  -> nasm -f bin test_kernle.asm -o test_kernel.sys
如果你要将test_kernel.sys放入目录的话, 需要用windows的UltraISO,先创建一个1.44MB的软盘,然后将test_kernel.sys放入,保存,然后将这个软盘放入编译目录,执行 make dd. 就OK了.


保护模式准备工作记录: 为了内核的兼容性,不得不适当的麻烦下, 可以对照 0.11 版本的保护模式 和 新版本的保护模式[文件是 pmjump.S]
[] [] [] [] 设置中断屏蔽位 OCW1 【详情查看 linux内核完全剖析, 文章 PS2键盘保护的另一种方法】,屏蔽所有中断请求.
MOV                AL,0xff
OUT                0x21,AL
nop
OUT                0xa1,AL
cli  ; 不允许中断
[] [] [] [] 设置a20 【详情查看 linux内核完全剖析,文章 A20地址线开闭 】. 开启 A20
  1.     CALL        waitkbdout
  2.     MOV                AL,0xd1
  3.     OUT                0x64,AL
  4.     CALL        waitkbdout   
  5.     MOV                AL,0xdf ; 开启A20.                       
  6.     OUT                0x60,AL
  7.     CALL        waitkbdout
  8. waitkdout:
  9.     in al, 0x64
  10.     test al, 0x02
  11.     jnz  waitkdout
  12.     ret
Copy the Code
上面所做的事情是 给 8042 发送命令 0xDF 置 A20 , 开启A20. [不得不吐槽一下 IBM的大叔们?为了兼容,搞的是蛋疼死人,一直用到现在,我.....]
[] [] [] [] 设置 cr0 和 加载(lgdt) 全局描述符. 【详情请参考 IA-32 卷3-系统编程指南, 这本是权威, 光看ia-32卷3,你真看不懂什么,实践一下或许懂的更多,更明白, 能开启保护模式,当然就有分页, 有分页 还有进程,有进程还有时钟, tss...., 有进程就关进程的调度... ..., 进入保护模式当然就无法调用 BIOS了,我们是不是要开始接触中断描述符表(IDT), 我们是不是, 要开始画图形 (0xa0000~0x...), 这个要如何办,只能去定义操作全局描述符还是其它呢?】
  1. GDT0:
  2.     dw 0x0000, 0x0000, 0x0000, 0x0000 ; gdt 空白 这是规定.
  3. GDT0_KERNEL_DATA: ; 非一致性-数据段描述符, 可读/写.
  4.     dw 0xffff ; 段限长公式: 段界限 = limit(0xFFFFF) * 4k + 0FFFFh
  5.     dw 0x0000 ; 基地址 ( Base addres : 00 )
  6.     dw 0x9200 ; p(1) DPL(00) S(1) TYPE(O[0], E[0], W[1], A[0]), 基地址为(00)
  7.     dw 0x00cf ; 基地址为(00), G(1) D(1) 0 AVL(0), 段限长(F)
  8. GDT0_KERNEL_CODE: ; 代码段描述符, 执行/可读.
  9.     dw 0xffff ; 段限长公式: 段界限 = limit(0x7FFFF) * 4k + 0FFFFh
  10.     dw 0x0000 ; 基地址 (00)
  11.     dw 0x9a28 ; P(1) DPL(00) S(1) TYPE(1, 0, 1, 0), 基地址(28) 非一致代码段
  12.     dw 0x0047 ; 基地址(00), G(0) D(1) 0 AVL(0), 段限长(7)
  13. GDTR0:
  14.     dw 8 * 3 - 1 ; GDTR表长度 ; GDT0_KERNEL_CODE
  15.     dd GDT0  ; 32位线性地址.
Copy the Code
QQ截图20130224023125.png
代码段.png

[] [] [] []: 进入保护模式, 调用C写的程序,刺手的问题,解决如何去掉 elf 格式头的问题.
测试程序. test.c
除了只能使用基本的语句外,头文件是不能导入的,试问在裸体上如何调用Linux系统的头文件,到时候可以编写头文件,然后调用.
  1. void test_main (void)
  2. {
  3. fin:
  4.     goto fin;
  5. }
Copy the Code
gcc -c test.c  // 生成一个 test.o ,这个是带 elf的.o
ld -o test -Ttext 0x00280000 -e test_main test.o  ; -Ttext 0x00280000  是我们在内存的什么位置.  -e test_main , 因为默认的入口参数是 _start, 我们没有,所以要指定.
objcopy -R .note -R .comment -S -O binary test test.bin ; 就生成了没有lef头格式的 纯二进制bin文件.
; 可以使用 ghex 来查看每个文件的变化.
这样我们就完成了可以调用C语言的bin了.

接下来要调用汇编写的库,先来个简单的例子.
例子:  io_hlt.asm
  1. [bits 32]
  2. [section .text]
  3. global io_htl
  4. io_hlt: ; void io_hlt(void)
  5.     hlt
  6.     ret
Copy the Code
例子:  test.c
  1. void io_hlt (void);
  2. void test_main (void)
  3. {
  4. fin:
  5.     io_hlt();
  6.     goto fin;
  7. }
Copy the Code
nasm -f elf test_asm.asm -o test_asm.o
gcc -c test.c
ld -o test -Ttext 0x00280000 -e test_main test.o test_asm.o
objcopy -R .note -R .comment -S -O binary test test.bin
================================================================
[] [] [] [] Bochs之美,调试的简约之美.

=============================================================================================
个bochs安装详解,本人很早的时候就已经配置好了,只要轻轻的设置一下目录路径,就OK了.
http://ishare.iask.sina.com.cn/f/154076 ... &retcode=0
项目地址.
https://github.com/hailongqiu/NOL_OS
Reply Favorite View the author
All Replies
pdlenovo
deepin
2013-02-23 23:24
#1
搞os的越来越多啊!!
Reply View the author
Android2013
deepin
2013-02-23 23:32
#2
搞os的越来越多啊!!
是你哈,是我哈,我们淡过的, 我是随便玩玩的哈,还没有写完,现在只是一个引导 加载文件test_kernel后,跳转到指定内存运行test_kernle测试程序而已. 你的源码都不公开哈,不然可以一起研究, 写个简单的图形.
不开放代码的话,只能一个人玩,也不能吸取别人的好代码和好建议,别人也不能从你的代码学习.
Reply View the author
New Thread

Popular Events

More
国际排名
WHLUG