OS 开发(二)

📅 2026/7/18 3:39:52
OS 开发(二)
1. 主引导扇区编写 Makefileboot.bin: boot.asm nasm -f bin boot.asm -o boot.bin master.img: boot.bin yes | bximage -q -hd16 -funccreate -sectsize512 -imgmodeflat master.img dd ifboot.bin ofmaster.img bs512 count1 convnotrunc .PHONY: clean clean: rm -rf *.bin rm -rf *.img .PHONY: bochs bochs: master.img bochs -q1 BIOSBASIC INPUT OUTPUT SYSTEMBIOS 在加电自检将主引导扇区读到 0x7c00位置 并跳转到这里执行INT 0x10 BIOS 系统调用 显示器相关功能2 实模式8086 模式 16位保护模式从实模式进入保护模式实模式的寻址 有效地址 段地址 * 16 偏移地址EA 0xb800 * 0x10 0 0xb8000 (文本显示器的内存区域)16 bit寄存器 要访问 - 1M内存 - 需要20bit地址线 - 所以有两个寄存器来共同访问地址段地址 4保护模式32位的寄存器 - 4G的内存 所以段地址在保护模式中失效3 主引导扇区的结构代码 446B硬盘分区表 64B 4*16B魔数 0x55 0xaa4 MBR 主要功能读取内核加载器 并执行参考书本x86 汇编语言操作系统真象还原2. 实模式 print-ah 0x0e-al 字符-int 0x10xchg bx, bx ;bochs 魔数断点 mov si, booting call print jmp $ print: mov ah, 0x0e .next: mov al, [si] cmp al, 0 jz .done int 0x10 inc si jmp .next .done: ret booting: db Booting DanOS..., 10, 13, 0; \n\rmov si, booting 将字符串 booting 起始地址装入源变址寄存器si 在实模式下 si 常作为指向内存数据的指针mov ah, 0x0e 设置BIOS 中断int 0x10 功能号 ah 0x0e 表示teletype 输出 即上屏幕写入一个字符 并且自动将光标后移db define byte定义字节序列3. 硬盘读写0x1f0 16位端口 用来读写数据0x1f1 检测前一个指令的错误0x1f2 读取扇区的数量0x1f3 起始扇区的0-7位0x1f4 起始扇区的8-15位0x1f5 起始扇区的16-23 位0x1f6 0-3位起始扇区的24-27位 第4位为0表示主盘 1表示从盘第6位 为0表示CHS模式 为1表示LBA模式第5.7位固定为10x1f7 IN / 8bit 数据 0 ERR 3 DRQ 7BSYOUT 0xec 设别硬盘 0x20读硬盘 0x30 写硬盘; 参数 mov edi, 0x1000 ;读取的目标内存 ; 将读到的内容存到内存的某个地方 mov ecx, 0; 起始扇区 mov bl, 1; 读取的扇区数量 call read_disk read_disk: mov dx, 0x1f2 ;设置读写扇区的数量 mov al, bl out dx, al inc dx ; 0x1f3, 初始扇区低八位 mov al, cl out dx, al inc dx ; 0x1f4, 初始扇区中八位 shr ecx, 8 mov al, cl out dx, al inc dx ; 0x1f5, 初始扇区高八位 shr ecx, 8 mov al, cl out dx, al inc dx; 0x1f6 shr ecx, 8 and cl, 0b1111; 将高4位变为0 mov al, 0xb1110_0000; or al, cl out dx, al; 主盘 LBA 模式 inc dx; 0x1f7 mov al, 0x20 ; 读硬盘 out dx, al xor ecx, ecx mov cl, bl ;得到读写扇区的数量 .read: push cx call .waits ;等待数据准备完毕 call .reads ;读取一个扇区 pop cx loop .read ret .waits: mov dx, 0x1f7 .check: in al, dx jmp $2 jmp $2 jmp $2 and al, 0b1000_1000 cmp al, 0b0000_1000 jnz .check ret .reads: mov dx, 0x1f0 mov cx, 256 ; 一个扇区是256个字 512个字节 .readw: in ax, dx jmp $2 jmp $2 jmp $2 mov [edi], ax add edi, 2 loop .readw ret