本文共 4119 字,大约阅读时间需要 13 分钟。
注意,所有创建的文件均放在同一目录下(.c文件的反汇编最好在linux环境下进行)
创建boot.asm文件,内容:
;内核引导程序org 0x7c00;LOAD_ADDR EQU 0X9000jmp entryentry: mov ax, 0 mov ss, ax mov ds, ax mov es, ax mov si, axreadFloppy: mov CH, 0 ;CH 用来存储柱面号 mov DH, 0 ;DH 用来存储磁头号 mov CL, 2 ;CL 用来存储扇区号 mov BX, LOAD_ADDR ; ES:BX 数据存储缓冲区 mov AH, 0x02 ; AH = 02 表示要做的是读盘操作 mov AL, 2 ; AL 表示要练习读取几个扇区 mov DL, 0 ;驱动器编号,一般我们只有一个软盘驱动器,所以写死 ;为0 INT 0x13 ;调用BIOS中断实现磁盘读取功能 JC fin jmp LOAD_ADDRfin: HLTjmp fintimes 510-$+$$ db 0times 512 db 0times 512 db 0
需要修改的部分(默认就行):
LOAD_ADDR的值,表示内核加载进内存的位置由kernel.asm里面org确定
readFloppy内mov CH, 0 中的1的修改,表示内核存储的磁道数
readFloppy内mov CL, 2 中的2的修改,表示内核存储的扇区数
readFloppy内mov AL, 2中的2的修改,表示内核的跨越扇区的数量
运行
nasm -o system.img boot.asm
产生系统镜像文件
创建文件write_vga.c文件,内容
//一个对屏幕像素设置颜色的程序void CMain(void) { int i; char*p = 0; for (i = 0xa0000; i <= 0xaffff; i++) { p = i; *p = i & 0x0f; } for(;;) { io_hlt(); }}
先编译成.o文件
使用
gcc -m32 -fno-asynchronous-unwind-tables -s -c -fno-pie -o write_vga.o write_vga.c
命令
再反汇编成.asm文件
使用
objconv -fnasm write_vga.o write_vga.asm
命令(提示:记得用git安装objconv 反汇编工具,然后切换到objconv 目录下面)
然后删除无用的信息,如下划线的内容删除
创建文件pm.inc,内容:
%macro Descriptor 3 dw %2 & 0ffffh dw %1 & 0ffffh db (%1>>16) & 0ffh dw ((%2>>8) & 0f00h) | (%3 & 0f0ffh) db (%1>>24) & 0ffh%endmacroDA_32 EQU 4000h ;32位段DA_C EQU 98h ;存在的只执行代码段属性DA_DRW EQU 92h ;存在的可读写数据段属性值
创建文件kernel.asm,内容:
%include "pm.inc"org 0x9000 ;这是内核在加载进入内存的时候的地址jmp LABEL_BEGIN[SECTION .gdt] ; 段基址 段界限 属性LABEL_GDT: Descriptor 0, 0, 0 LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRWLABEL_DESC_VRAM: Descriptor 0, 0ffffffffh, DA_DRWLABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRW+DA_32GdtLen equ $ - LABEL_GDTGdtPtr dw GdtLen - 1 dd 0SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDTSelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDTSelectorStack equ LABEL_DESC_STACK - LABEL_GDTSelectorVram equ LABEL_DESC_VRAM - LABEL_GDT[SECTION .s16][BITS 16]LABEL_BEGIN: mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, 0100h mov al, 0x13 mov ah, 0 int 0x10 xor eax, eax mov ax, cs shl eax, 4 add eax, LABEL_SEG_CODE32 mov word [LABEL_DESC_CODE32 + 2], ax shr eax, 16 mov byte [LABEL_DESC_CODE32 + 4], al mov byte [LABEL_DESC_CODE32 + 7], ah ;set stack for C language xor eax, eax mov ax, cs shl eax, 4 add eax, LABEL_STACK mov word [LABEL_DESC_STACK + 2], ax shr eax, 16 mov byte [LABEL_DESC_STACK + 4], al mov byte [LABEL_DESC_STACK + 7], ah xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_GDT mov dword [GdtPtr + 2], eax lgdt [GdtPtr] cli ;关中断 in al, 92h or al, 00000010b out 92h, al mov eax, cr0 or eax , 1 mov cr0, eax jmp dword SelectorCode32: 0 [SECTION .s32] [BITS 32] LABEL_SEG_CODE32: ;initialize stack for c code mov ax, SelectorStack mov ss, ax mov esp, TopOfStack mov ax, SelectorVram mov ds, axC_CODE_ENTRY: %include "write_vga.asm" io_hlt: ;void io_hlt(void); HLT RETSegCode32Len equ $ - LABEL_SEG_CODE32[SECTION .gs]ALIGN 32[BITS 32]LABEL_STACK:times 512 db 0TopOfStack equ $ - LABEL_STACK
生成内核的二进制文件
使用
nasm kernel.asm -o kernel.bat
命令
最后手动链接system.img和kernel.bat二进制文件
将kernel.bat和system.img文件用二进制编辑器打开,并将kernel.bat的内容复制到system.img的55aa数据的后面并保存
使用visualbox运行system.img文件。
结果:
转载地址:http://byozi.baihongyu.com/