| 发表于:2007-10-17 22:04:04 楼主 |
代码如下,前面还有个引导程序,没有错误,这个程序在企图跳转到elf文件--kernel.bin, 即"jmp 0x08 : 0x30400"之前都没有出错,一到该跳转语句就出现错误,因为异常处理还没做好,所以不知道什么错误,而kernel.bin是一个打印单个字符的小程序,没有错误。 我编译kernel.bin用到的命令: nasm -f elf kernel.o -o kernel.asm, ld -s -ttext 0x30400 -o kernel.bin kernel.o 卡在这里一个下午了,郁闷啊,高手帮看看啊, 谢谢了 ~~~~~~~~ page_dir equ 0x100000 ;页表目录首地址 page0 equ 0x101000 ;页表0首地址 page1 equ 0x102000 page2 equ 0x103000 page3 equ 0x104000 begin: mov ax, cs mov es, ax mov ds, ax mov ss, ax mov sp, 0x200 ;打印提示信息 mov ah, 0x3 xor dh, dh int 0x10 mov cx, 29 mov ax, msg mov bp, ax mov ax, 0x1301 mov bx, 0x0007 int 0x10 ;向bootsect一样,将自己移动到物理内存开始处,即0x00000 mov ax, 0x0000 mov es, ax xor di, di xor si, si mov cx, 256 rep movsw jmp 0x0000: go go: mov ax, cs mov es, ax mov ds, ax mov ss, ax mov sp, 0x200 ;进入保护模式 lgdt [gdt_48] cli in al, 0x92 or al, 0x02 out 0x92, al mov eax, cr0 or eax, 1 mov cr0, eax jmp dword 0x08: protect_mode [section .s32] align 32 [bits 32] ;保护模式下运行 protect_mode: mov ax, 0x18 ;显示段 mov gs, ax mov ax, 0x10 ;内核数据段 mov ds, ax mov es, ax mov ss, ax mov esp, 0x800 ;保护模式下的堆栈大小, 2k ;================================================================= ; 设置分页机制, phoenix最大只支持16m的物理内存,所以只需要4个页表 ; 每个页表有1024项,每项占4个字节 ;================================================================= do_setup_paging: ;将页表目录项指向各个页表, pagex + 7,其中7是页表参数指的是该页在用户态存在,可读写 mov edi, page_dir mov eax, page0 + 7 mov ecx, 4 cld do_page_dir_ptr: stosd add eax, 0x1000 loop do_page_dir_ptr ;将各个页表项指向每个物理内存页, 使用倒退填充的方法 mov edi, page3 + 4092 ;最后一页表的最后一页表项 mov eax, 0xfff000 + 7 ;物理内存的最后一页 std do_page_ptr: stosd sub eax, 0x1000 jge do_page_ptr ;设置cr3指向页表目录并打开分页机制 mov eax, page_dir mov cr3, eax mov eax, cr0 or eax, 0x80000000 mov cr0, eax jmp ok ok: nop ;延迟 ;判断0x30000位置是否已经读入elf格式kernel.bin cmp byte [0x30000], 0x7f jne no_elf cmp byte [0x30001], 0x45 jne no_elf cmp byte [0x30002], 0x4c jne no_elf cmp byte [0x30003], 0x46 jne no_elf jmp elf no_elf: ;kernel.bin没有读入0x30000开始的物理内存地址 mov edi, (80 * 10 + 10) * 2 mov al, 'n' mov ah, 0x0c mov [gs:edi], ax jmp $ elf: ;================================================================= ; 将控制权交给kernel, head结束 ;================================================================= mov edi, (80 * 10 + 10) * 2 mov al, 'y' mov ah, 0x0c mov [gs:edi], ax ;jmp $ ;跳转到kernel.bin, 0x30400是kernel.bin的入口 jmp 0x08 : 0x30400 msg: db "begin into protect mode ...", 13, 10 gdt_48: dw 0x7ff dd 0x10000 + gdt gdt: dw 0, 0, 0, 0 ;第一项,空项 ;代码段 dw 0xffff ;段限长, 0x800 - 1, 最多只能有256个描述符,而一个描述符占8个字节 dw 0x0000 ;段基址 dw 0x9a00 ;参数 + 段基址, 可执行/只读 dw 0x00cf ;数据段 dw 0xffff ;段限长, 0x800 - 1, 最多只能有256个描述符,而一个描述符占8个字节 dw 0x0000 ;段基址 dw 0x9200 ;可读刻写 dw 0x00cf ;显示段(用于内核调试) dw 0xffff dw 0x8000 dw 0x920b dw 0x0000 times 252 * 8 db 0 ;填充剩余的描述符 |
|
|
|
|