这是转载的,原文可以在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 条评论。