; haribote-os boot asm ; TAB=4 BOTPAK EQU 0x00280000 ; 加载bootpack DSKCAC EQU 0x00100000 ; 磁盘缓存的位置 DSKCAC0 EQU 0x00008000 ; 磁盘缓存的位置(实模式) ; BOOT_INFO 相关 CYLS EQU 0x0ff0 ; 引导扇区设置 LEDS EQU 0x0ff1 VMODE EQU 0x0ff2 ; 关于颜色的信息 SCRNX EQU 0x0ff4 ; 分辨率X SCRNY EQU 0x0ff6 ; 分辨率Y VRAM EQU 0x0ff8 ; 图像缓冲区的起始地址 ORG 0xc200 ; 这个的程序要被装载的内存地址 ; 画面设置 MOV AL,0x13 ; VGA显卡,320x200x8bit MOV AH,0x00 INT 0x10 MOV BYTE [VMODE],8 ; 屏幕的模式(参考C语言的引用) MOV WORD [SCRNX],320 MOV WORD [SCRNY],200 MOV DWORD [VRAM],0x000a0000 ; 通过 BIOS 获取指示灯状态 MOV AH,0x02 INT 0x16 ; keyboard BIOS MOV [LEDS],AL ; PIC关闭一切中断 ; 根据AT兼容机的规格,如果要初始化PIC, ; 必须在CLI之前进行,否则有时会挂起。 ; 随后进行PIC的初始化。 MOV AL,0xff OUT 0x21,AL NOP ; 如果连续执行OUT指令,有些机种会无法正常运行 OUT 0xa1,AL CLI ; 禁止CPU级别的中断 ; 为了让CPU能够访问1MB以上的内存空间,设定A20GATE CALL waitkbdout MOV AL,0xd1 OUT 0x64,AL CALL waitkbdout MOV AL,0xdf ; enable A20 OUT 0x60,AL CALL waitkbdout ; 切换到保护模式 [INSTRSET "i486p"] ; 说明使用486指令 LGDT [GDTR0] ; 设置临时GDT MOV EAX,CR0 AND EAX,0x7fffffff ; 设bit31为0(禁用分页) OR EAX,0x00000001 ; bit0到1转换(保护模式过渡) MOV CR0,EAX JMP pipelineflush pipelineflush: MOV AX,1*8 ; 可读写的段 32bit MOV DS,AX MOV ES,AX MOV FS,AX MOV GS,AX MOV SS,AX ; bootpack传递 MOV ESI,bootpack ; 转送源 MOV EDI,BOTPAK ; 转送目标 MOV ECX,512*1024/4 CALL memcpy ; 磁盘数据最终转送到它本来的位置去 ; 首先从启动扇区开始 MOV ESI,0x7c00 ; 转送源 MOV EDI,DSKCAC ; 转送目标 MOV ECX,512/4 CALL memcpy ; 剩余的全部 MOV ESI,DSKCAC0+512 ; 转送源 MOV EDI,DSKCAC+512 ; 转送源目标 MOV ECX,0 MOV CL,BYTE [CYLS] IMUL ECX,512*18*2/4 ; 从柱面数变换为字节数/4 SUB ECX,512/4 ; 减去 IPL 偏移量 CALL memcpy ; 必须由asmhead来完成的工作,至此全部完毕 ; 以后就交由bootpack来完成 ; bootpack启动 MOV EBX,BOTPAK MOV ECX,[EBX+16] ADD ECX,3 ; ECX += 3; SHR ECX,2 ; ECX /= 4; JZ skip ; 没有要转送的东西时 MOV ESI,[EBX+20] ; 转送源 ADD ESI,EBX MOV EDI,[EBX+12] ; 转送目标 CALL memcpy skip: MOV ESP,[EBX+12] ; 堆栈的初始化 JMP DWORD 2*8:0x0000001b waitkbdout: IN AL,0x64 AND AL,0x02 IN AL,0x60 ; 空读(为了清空数据接收缓冲区中的垃圾数据) JNZ waitkbdout ; AND的结果如果不是0,就跳到waitkbdout RET memcpy: MOV EAX,[ESI] ADD ESI,4 MOV [EDI],EAX ADD EDI,4 SUB ECX,1 JNZ memcpy ; 减法运算的结果如果不是0,就跳转到memcpy RET ; memcpy地址前缀大小 ALIGNB 16 GDT0: RESB 8 ; 初始值 DW 0xffff,0x0000,0x9200,0x00cf ; 可以读写的段(segment)32bit DW 0xffff,0x0000,0x9a28,0x0047 ; 可执行的文件的32bit寄存器(bootpack用) DW 0 GDTR0: DW 8*3-1 DD GDT0 ALIGNB 16 bootpack: