Tag Archives: Tutorial

写你自己的操作系统

这是转载的,原文可以在http://www.xemean.net的文档中心里找到.

因为原文中的代码编译后运行有错误,这里我把改过后能正确运行的代码讲一下

org 0x07c00     ; 起始地址是0000:7c00

jmp begin_boot ; 跳过其它的数据,跳转到引导程序的开始处

OEM_ID                db ”OSeg    ”   ;软盘信息,具体请参考”FAT格式”

BytesPerSector        dw 0×0200

SectorsPerCluster     db 0×01

ReservedSectors       dw 0×0001

TotalFATs             db 0×02

MaxRootEntries        dw 0x00E0

TotalSectorsSmall     dw 0x0B40

MediaDescriptor       db 0xF0

SectorsPerFAT         dw 0×0009

SectorsPerTrack       dw 0×0012

NumHeads              dw 0×0002

HiddenSectors         dd 0×00000000

TotalSectorsLarge     dd 0×00000000

DriveNumber           db 0×00

Flags                 db 0×00

Signature             db 0×29

VolumeID              dd 0xFFFFFFFF

VolumeLabel           db ”OSexample  ”

SystemID              db ”FAT12   ”

print_mesg:  ;打印信息调用

mov ah,0×13 ; 使用中断10h的功能13,在屏幕上写一个字符串

mov al,0×00 ; 决定调用函数后光标所处的位置

mov bx,0×0007 ; 设置显示属性

mov cx,0×20 ; 在此字符串长度为32

mov dx,0×0000 ; 光标的起始行和列

int 0×10 ; 调用BIOS的中断10h

ret ; 返回调用程序

get_key:  ;等待按键

mov ah,0×00

int 0×16 ; Get_key使用中断16h的功能0,读取下一个字符

ret

clrscr:   ;清屏

mov ax,0×0600 ; 使用中断10h的功能6,实现卷屏,如果al=0则清屏

mov cx,0×0000 ; 清屏

mov dx,0x174f ; 卷屏至23,79

mov bh,0 ; 使用颜色0来填充

int 0×10 ; 调用10h中断

ret  ;返回

begin_boot:  ;;引导程序开始

mov  ax,cs    ;设置段寄存器

mov  ds,ax

mov  es,ax

call clrscr ; 先清屏

mov bp,bootmesg ; 提供串地址

call print_mesg ; 输出信息

call get_key ; 等待用户按下任一键

bits 16   ;以16位方式编译

call clrscr ; 清屏

mov ax,0xb800 ; 使gs指向显示内存

mov gs,ax ; 在实模式下显示一个棕色的A

mov word [gs:0],0×641 ; 显示

call get_key ; 调用Get_key等待用户按下任一键

mov bp,pm_mesg ; 设置串指针

call print_mesg ; 调用print_mesg子程序

call get_key ; 等待按键

call clrscr ; 清屏

cli ; 关中断

mov  eax,ds   ;设置GDT物理地址

shl  eax,4

add  [gdtr+2],eax

lgdt [gdtr] ; 加载GDT

mov eax,cr0 ;进入保护模式

or  al,0×01 ; 设置保护模式位

mov cr0,eax ; 将更改后的字送至控制寄存器中

jmp codesel:go_pm  ;跳至32位代码

bits 32  ;以32位方式编译

go_pm:

mov ax,datasel  ;设置段寄存器

mov ds,ax ; 初始化ds和es,使其指向数据段

mov es,ax

mov ax,videosel  ;使gs指向显存

mov gs,ax

mov word [gs:0],0×0400+’B' ; 在保护模式下显示一个红色的字符B

jmp $ ; 无限循环

bits 16

gdtr:

dw gdt_end-gdt-1 ; gdt的长度

dd gdt ; gdt的物理地址

gdt:   ;具体GDT信息请参考GDT格式

nullsel equ $-gdt ; $指向当前位置,所以nullsel = 0h

dd 0

dd 0 ; 所有的段描述符都是64位的

codesel equ $-gdt ; 这是8h也就是gdt的第二个描述符

code_gdt:

dw 0x0ffff ; 段描述符的界限是4Gb

dw 0×0000

db 0×00

db 0x09a

db 0x0cf

db 0×00

datasel equ $-gdt

data_gdt:

dw 0x0ffff

dw 0×0000

db 0×00

db 0×092

db 0x0cf

db 0×00

videosel equ $-gdt

dw 3999

dw 0×8000 ; 基址是0xb8000

db 0x0b

db 0×92

db 0xcf

db 0×00

gdt_end:

bootmesg db ”Our OS boot sector loading…   ”   ;信息数据

pm_mesg  db ”Switching to protected mode…  ”

times 510-($-$$) db 0  ;填满512个字节

dw 0x0AA55  ;引导扇区标志

.