编写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 + 0x300
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
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
;用于保存内存容量,以字节为单位,此位置好记
; 0x900 + 32 + 480 = 0xb00
total_mem_bytes dd 0
gdt_ptr dw GDT_LIMIT
dd GDT_BASE
; 人工对齐
ards_buf times 244 db 0
ards_nr dw 0
loader_start:
;------- int 15h eax = 0000E820h ,edx = 534D4150h ('SMAP') 获取内存布局 -------
xor ebx,ebx
mov edx,0x534d4150
mov di,ards_buf
.e820_mem_get_loop:
mov eax, 0x0000e820
mov ecx,20
int 0x15
jc .e820_failed_so_try_e801
add di,cx
inc word[ards_nr]
cmp ebx,0
jnz .e820_mem_get_loop
mov cx,[ards_nr]
mov ebx,ards_buf
xor edx,edx
.find_max_mem_area:
mov eax,[ebx]
add eax,[ebx+8]
add ebx,20
cmp edx,eax
jge .next_ards
mov edx,eax
.next_ards:
loop .find_max_mem_area
jmp .mem_get_ok
;------ int 15h ax = E801h 获取内存大小,最大支持4G ------
.e820_failed_so_try_e801:
mov ax,0xe801
int 0x15
jc .e801_failed_so_try88
; 先算出低15M的内存
mov cx,0x400
mul cx
shl edx,16 ; 左移16位
and eax,0x0000FFFF
or edx,eax
add edx,0x100000
mov esi,edx
; 再将16M以上的内存
xor eax,eax
mov ax,bx
mov ecx,0x10000
mul ecx
add esi,eax
mov edx,esi
jmp .mem_get_ok
;----------------- int 15h ah = 0x88 获取内存大小,只能获取64M之内 ----------
.e801_failed_so_try88:
mov ah,0x88
int 0x15
jc .error_hlt
and eax,0x0000FFFF
mov cx,0x400
mul cx,
shl edx,16
or edx,eax
add edx,0x100000
.mem_get_ok:
mov [total_mem_bytes], edx
;----------------- 准备进入保护模式 -------------------
;1 打开A20
;2 加载gdt
;3 将cr0的pe位置1
;准备进入保护模式
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
.error_hlt: ;出错则挂起
hlt
[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和读书笔记七中一致。
编译代码
nasm -I include/ -o mbr.bin mbr.S
nasm -I include/ -o loader.bin loader.S
dd if=/home/truthos/oscode/c5/a/boot/mbr.bin of=/home/truthos/bochs/hd60M.img bs=512 count=1 conv=notrunc
dd if=/home/truthos/oscode/c5/a/boot/loader.bin of=/home/truthos/bochs/hd60M.img count=4 seek=2 conv=notrunc
xp 0xb00 查看物理内存0xb00出的内容
程序正常运行