重复的轮子通用操作系统内核

这篇博客详细记录了作者构建操作系统内核的过程,从环境准备到编写第一行汇编代码,再到创建虚拟软驱和虚拟机配置,最终启动并调试Bochs。内容涵盖了实模式切换、GDT设置等关键知识点,适合对操作系统底层原理感兴趣的读者。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

hello os


环境准备

第一行汇编

boost.asm 在屏幕打印hello os

org 07c00h ;指定代码加载到7c00地址处

mov ax, cs
mov ds, ax
mov es, ax
call DispStr ;显示字符串
jmp $ ;无线循环

DispStr:
    mov ax, BootMessage
    mov bp, ax  ;es:bp 串地址
    mov cx, 24  ;字符串长度
    mov ax, 01301h ;AH=13, AL=01h
    mov bx, 000ch  ;BH=0(页号0) BL=0CH(红底黑字高亮)
    mov dl, 0
    int 10h
    ret

BootMessage:   db  "lxhuster hello os world"
times 510-($-$$) db 0 ;填充剩余空间
dw 0xaa55 ;固定的结束标志数

编译代码

nasm boot.asm –o boot.bin

创建虚拟软驱

bximage 生成lxhuster.img软驱

创建虚拟机配置文件

  • 可以从例子dlxlinux借鉴bochsrc.bxrc
  • 1) 注意路径
  • 2) 注意floppya: 1_44=lxhuster.img 修改为自己创建软驱名称
###############################################################
# bochsrc.txt file for DLX Linux disk image.
###############################################################

# how much memory the emulated machine will have
megs: 32

# filename of ROM images
romimage: file=..\BIOS-bochs-latest
vgaromimage: file=..\VGABIOS-lgpl-latest

# what disk images will be used 
floppya: 1_44=lxhuster.img, status=inserted

# hard disk
#ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
#ata0-master: type=disk, path="hd10meg.img", cylinders=306, heads=4, spt=17

# choose the boot disk.
boot: floppy

# default config interface is textconfig.
#config_interface: textconfig
#config_interface: wx

#display_library: x
# other choices: win32 sdl wx carbon amigaos beos macintosh nogui rfb term svga

# where do we send log messages?
log: bochsout.txt

# disable the mouse, since DLX is text only
mouse: enabled=0

# set up IPS value and clock sync
cpu: ips=15000000
clock: sync=both

# enable key mapping, using US layout as default.
#
# NOTE: In Bochs 1.4, keyboard mapping is only 100% implemented on X windows.
# However, the key mapping tables are used in the paste function, so 
# in the DLX Linux example I'm enabling keyboard_mapping so that paste 
# will work.  Cut&Paste is currently implemented on win32 and X windows only.

keyboard: keymap=..\keymaps\x11-pc-us.map

烧写boot.bin

烧写boot.bin 到 lxhuster.img

  • 方法一: 使用二进制编辑器将boot.bin内容复制到lxhuster.img

  • 方法二:编写个小工具,使用二进制模式完成方法一的动作

启动bochs

bochs -q -f bochsrc.bxrc

这里写图片描述

调试bochs

bochsdbg -q -f bochsrc.bxrc

常用调试命令:

  • b addr 设置断点
  • c 继续执行
  • r 查看寄存器
  • trace-reg on 每一执行一个单步即显示寄存器指
  • x 显示内存地址
  • help 查看命令帮助

hint

  • 为了方便虚拟机的位置在bochs安装目录下

这里写图片描述

  • 参考资料
    Orange’S:一个操作系统的实现

进入实模式

概述

  • 为GDT分配空间,并设置三个基本表项目
  • 为lgdt分配临时空间
  • 16位指令设置GDT中32位代码段表项的基地址
  • 16位指令设置cr0跳转到实模式32位代码段地址处
  • 32位指令通过显存段操作屏幕显示lx

f**k code

%include "pm.inc"  ;定义的基础常量
org 0100h ;指定代码加载到100h地址处,因为我们使用dos执行编译的代码
jmp LABEL_BEGIN

[SECTION .gdt] ;定义gdt段
LABEL_GDT: Descriptor 0, 0 ,0 ; 占位的描述符
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len -1, DA_C + DA_32 ; DA_C(设置代码段,内存中存在) DA_32(32位代码段)
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 显存首地址

GdtLen equ $ - LABEL_GDT ; 定义GDT长度
GdtPtr dw GdtLen -1 ; 设置gdt长度大小
       dd 0         ; 4个字节的GDT起始地址

; 定义GDT各个段选择子
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo  equ LABEL_DESC_VIDEO - LABEL_GDT

[SECTION .s16] ; 16位初始代码
[BITS 16]
LABEL_BEGIN:
    mov ax, cs ;设置段寄存器
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0100h

    ; 初始化32位代码段描述符
    xor eax, eax
    mov ax, cs
    shl eax, 4
    add eax, LABEL_SEG_CODE32
    mov word [LABEL_DESC_CODE32 + 2], ax ; 填充基地址15:0

    shr eax, 16 ; 将高8位移动到ax
    mov byte [LABEL_DESC_CODE32 + 4], al ; 填充基地址 23:16
    mov byte [LABEL_DESC_CODE32 + 7], ah ; 填充基地址 31:24

    ; 加载gdtr
    xor eax, eax
    mov ax, ds
    shl eax, 4
    add eax, LABEL_GDT
    mov dword [GdtPtr + 2], eax ; 将gdt起始地址填充到内存当中

    lgdt [GdtPtr] ; 将内存中的gdt起始地址和大小信息填充到寄存器

    ; 关中断
    cli

    ; 打开地址线A20
    in  al, 92h
    or  al, 00000010b
    out 92h, al

    ; 切换到保护模式
    mov eax, cr0
    or eax, 1
    mov cr0, eax

    ; 进入保护模式跳转到32位代码段执行
    jmp dword  SelectorCode32:0

[SECTION .s32] ; 32位代码段
[BITS 32]   

LABEL_SEG_CODE32:
   mov ax, SelectorVideo
   mov gs, ax

   mov edi, (80 * 11 + 78) * 2 ; 屏幕第11行78列
   mov ah, 0ch ;0000: 黑底    1100: 红字
   mov al, 'l'
   mov [gs:edi], ax

   mov edi, (80 * 11 + 79) * 2 ; 屏幕第11行78列
   mov ah, 0ah ;0000: 黑底    1010: 绿字
   mov al, 'x'
   mov [gs:edi], ax

   jmp $

SegCode32Len equ $ - LABEL_SEG_CODE32

编译代码:

为突破512启动代码512字节的限制,使用freedos来执行编译的代码

nasm boot.asm -o boot.com

这里写图片描述

关键点:

  • GDT表项格式
  • 选择子的格式
  • cr0寄存器的格式

hint:

  • 1> 格式化软盘B可能会出错,最后执行两次,且格式化后img大小为1440 kb

    format b:


这里写图片描述
  • 2> 将boot.com文件复制到img镜像中时,需要使用linux系统,如果是使用的虚拟机请安装samba进行文件的共享,不要使用虚拟机的拖动文件功能
    这里写图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值