进入保护模式,物理内存地址不能直接被程序访问,程序内部的地址(虚拟地址)需要被转化为物理地址后再去访问,程序对此一无所知。地址转换是由处理器和操作系统共同协作完成的,处理器在硬件上提供地址转换部件,操作系统提供转换工程中所需要的页表。
编写mbr.S主引导扇区代码
;LOADER_BASE_ADDR equ 0x900
;LOADER_START_SECTOR equ 0x2
%include "boot.inc"
SECTION MBR vstart=0x7c00
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00
mov ax,0xb800
mov gs,ax
mov ax,0x0600
mov bx,0x0700
mov cx,0
mov dx, 184fh
int 10h
mov byte [gs:0x00], '1'
mov byte [gs:0x01], 0xA4
mov byte [gs:0x02], ' '
mov byte [gs:0x03], 0xA4
mov byte [gs:0x04], 'M'
mov byte [gs:0x05], 0xA4
mov byte [gs:0x06], 'B'
mov byte [gs:0x07], 0xA4
mov byte [gs:0x08], 'R'
mov byte [gs:0x09], 0xA4
mov eax,LOADER_START_SECTOR
mov bx, LOADER_BASE_ADDR
mov cx,4 ; 读取的扇区数,读取4个扇区
call rd_disk_m_16
jmp LOADER_BASE_ADDR
rd_disk_m_16:
mov esi,eax
mov di,cx
mov dx,0x1f2
mov al,cl
out dx,al
mov eax,esi
mov dx,0x1f3
out dx,al
mov cl,8
shr eax,cl
mov dx,0x1f4
out dx,al
shr eax,cl
mov dx,0x1f5
out dx,al
shr eax,cl
and al,0x0f
or al,0xe0
mov dx,0x1f6
out dx,al
mov dx,0x1f7
mov al,0x20
out dx,al
.not_ready:
nop
in al,dx
and al,0x88
cmp al,0x08
jnz .not_ready
mov ax,di
mov dx,256
mul dx
mov cx,ax
mov dx,0x1f0
.go_on_ready:
in ax,dx
mov [bx],ax
add bx,2
loop .go_on_ready
ret
times 510-($-$$) db 0
db 0x55,0xaa
编写loader.S 加载器代码
;LOADER_BASE_ADDR equ 0x900
;LOADER_START_SECTOR equ 0x2
%include "boot.inc"
SECTION LOADER vstart=LOADER_BASE_ADDR
LOADER_STACK_TOP equ LOADER_BASE_ADDR
jmp loader_start
GDT_BASE: dd 0x00000000
dd 0x00000000
CODE_DESC: dd 0x0000FFFF
dd DESC_CODE_HIGH4
DATA_STACK_DESC: dd 0x0000FFFF
dd DESC_DATA_HIGH4
VIDEO_DESC: dd 0x80000007
dd DESC_VIDEO_HIGH4
GDT_SIZE equ $-GDT_BASE
GDT_LIMIT equ GDT_SIZE-1
times 60 dq 0
SELECTOR_CODE equ (0x0001 << 3) + TI_GDT + RPL0
SELECTOR_DATA equ (0x0002 << 3) + TI_GDT + RPL0
SELECTOR_VIDEO equ (0x0003 << 3) + TI_GDT + RPL0
gdt_ptr dw GDT_LIMIT
dd GDT_BASE
loadermsg db '2 loader in real.'
loader_start:
mov sp,LOADER_BASE_ADDR
mov bp, loadermsg
mov cx,17
mov ax, 0x1301
mov bx, 0x001f
mov dx, 0x1800
int 0x10
;准备进入保护模式
in al,0x92
or al,0000_0010b
out 0x92,al
lgdt [gdt_ptr]
mov eax,cr0
or eax,0x00000001
mov cr0,eax
jmp dword SELECTOR_CODE:p_mode_start
[bits 32]
p_mode_start:
mov ax,SELECTOR_DATA
mov ds,ax
mov es,ax
mov ss,ax
mov esp,LOADER_STACK_TOP
mov ax,SELECTOR_VIDEO
mov gs,ax
mov byte[gs:160],'p'
jmp $
编写boot.inc 宏定义代码文件
LOADER_BASE_ADDR equ 0x900
LOADER_START_SECTOR equ 0x2
DESC_G_4K equ 1_00000000000000000000000b
DESC_D_32 equ 1_0000000000000000000000b
DESC_L equ 0_000000000000000000000b
DESC_AVL equ 0_00000000000000000000b
DESC_LIMIT_CODE2 equ 1111_0000000000000000b
DESC_LIMIT_DATA2 equ DESC_LIMIT_CODE2
DESC_LIMIT_VIDEO2 equ 0000_000000000000000b
DESC_P equ 1_000_0000_0000_0000b
DESC_DPL_0 equ 00_0000000000000b
DESC_DPL_1 equ 01_0_0000_0000_0000b
DESC_DPL_2 equ 10_0000000000000b
DESC_DPL_3 equ 11_0000000000000b
DESC_S_CODE equ 1_0000_0000_0000b
DESC_S_DATA equ DESC_S_CODE
DESC_S_sys equ 0_000000000000b
DESC_TYPE_CODE equ 1000_0000_0000b
DESC_TYPE_DATA equ 0010_00000000b
DESC_CODE_HIGH4 equ (0x00<<24) + DESC_G_4K + DESC_D_32 + \
DESC_L + DESC_AVL + DESC_LIMIT_CODE2 + \
DESC_P + DESC_DPL_0 + DESC_S_CODE + \
DESC_TYPE_CODE + 0x00
DESC_DATA_HIGH4 equ (0x00<<24) + DESC_G_4K + DESC_D_32 + \
DESC_L + DESC_AVL + DESC_LIMIT_DATA2 + \
DESC_P + DESC_DPL_0 + DESC_S_DATA + \
DESC_TYPE_DATA + 0x00
DESC_VIDEO_HIGH4 equ (0x00<<24) + DESC_G_4K + DESC_D_32 + \
DESC_L + DESC_AVL + DESC_LIMIT_VIDEO2 + \
DESC_P + DESC_DPL_0 + DESC_S_DATA + \
DESC_TYPE_DATA + 0x0b
RPL0 equ 00b
RPL1 equ 01b
RPL2 equ 10b
RPL3 equ 11b
TI_GDT equ 000b
TI_LDT equ 100b
nasm -I include/ -o mbr.bin mbr.S
nasm -I include/ -o loader.bin loader.S
dd if=/home/truthos/oscode/c4/a/boot/mbr.bin of=/home/truthos/bochs/hd60M.img bs=512 count=1 conv=notrunc
;loader.bin大于512byte,同时mbr从第2个扇区开始加载4个扇区,因此seek=2, count=4
dd if=/home/truthos/oscode/c4/a/boot/loader.bin of=/home/truthos/bochs/hd60M.img count=4 seek=2 conv=notrunc
运行bochs. (bin/bochs -f bochsrc.disk). 正常进入保护模式