写你自己的操作系统

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

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

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

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

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

BytesPerSector        dw 0x0200

SectorsPerCluster     db 0x01

ReservedSectors       dw 0x0001

TotalFATs             db 0x02

MaxRootEntries        dw 0x00E0

TotalSectorsSmall     dw 0x0B40

MediaDescriptor       db 0xF0

SectorsPerFAT         dw 0x0009

SectorsPerTrack       dw 0x0012

NumHeads              dw 0x0002

HiddenSectors         dd 0x00000000

TotalSectorsLarge     dd 0x00000000

DriveNumber           db 0x00

Flags                 db 0x00

Signature             db 0x29

VolumeID              dd 0xFFFFFFFF

VolumeLabel           db "OSexample  "

SystemID              db "FAT12   "

print_mesg:  ;打印信息调用

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

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

mov bx,0x0007 ; 设置显示属性

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

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

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

ret ; 返回调用程序

get_key:  ;等待按键

mov ah,0x00

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

ret

clrscr:   ;清屏

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

mov cx,0x0000 ; 清屏

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

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

int 0x10 ; 调用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],0x641 ; 显示

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,0x01 ; 设置保护模式位

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],0x0400+'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 0x0000

db 0x00

db 0x09a

db 0x0cf

db 0x00

datasel equ $-gdt

data_gdt:

dw 0x0ffff

dw 0x0000

db 0x00

db 0x092

db 0x0cf

db 0x00

videosel equ $-gdt

dw 3999

dw 0x8000 ; 基址是0xb8000

db 0x0b

db 0x92

db 0xcf

db 0x00

gdt_end:

bootmesg db "Our OS boot sector loading...   "   ;信息数据

pm_mesg  db "Switching to protected mode...  "

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

dw 0x0AA55  ;引导扇区标志

发表评论?

0 条评论。

发表评论


注意 - 你可以用以下 HTML tags and attributes:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>