我們可以透過https://wiki.osdev.org/來得到許許多多的資料。
要進入保護模式,首先要先關閉中斷,直到我們自己製作一個中斷描述表,才能夠再開回來。關閉中斷,利用
cli
之後,我們可以利用許多方法開啟A20。其中,我們利用最簡便的方法開啟。inb $0x92, %al
orb $2, %al
out %al, $0x92
再來就是GDT(全局描述表)了。它的功能就是描述每一段記憶體的開頭、大小、權限等等。我們的GDT有三個表項,分別是空、程式段、資料段。GDT的第一個一定要是空的。有關GDT內容的詳細敘述,可以參考Intel的手冊https://software.intel.com/sites/default/files/managed/a4/60/325384-sdm-vol-3abcd.pdf在32位元保護模式中,GDT的大小是8Bytes(可以參考手冊中Figure 3-8)。我們的程式段和資料段都是由0x0起始,大小4GB。
GDT_NUL:
.long 0
.long 0
GDT_CODE32:
.long 0x0000FFFF
.long 0x00CF9A00
GDT_DATA32:
.long 0x0000FFFF
.long 0x00CF9200
GDTR:
.word 24
.long GDT_NUL+0x7C00
我們最後的GDTR這個區段,裡面是我們要存進GDTR暫存器的資料,首先是我們GDT的大小,再來是GDT的位置。我們打完這個區段以後,就利用lgdt GDTR
將GDTR暫存器準備好。再來我們就要正式開啟保護模式了。設定CR0暫存器的最低位,就可以開啟保護模式。movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0
之後,利用一個ljmp指令,就可以改變cs暫存器,完全地進入保護模式。ljmp $0x08, $(0x7c00+OS_PMODE)
OS_PMODE:
現在整個組合語言程式如下。.code16
.section .text
# Init all the registers
xorw %ax, %ax
xorw %bx, %bx
xorw %cx, %cx
xorw %dx, %dx
movw $0x7c0, %ax
movw %ax, %es
movw %ax, %ds
movw %ax, %ss
# Reset Floppy (int 0x13, ah = 0x0, dl = 0 (first floppy))
movb $0, %ah
int $0x13
# Read Number 2 (CHS)
# (int 0x13, ah = 0x2, al = 1, ch = 0, cl = 2, dh = 0, dl = 0, ES:BX = 0x7E00)
movw $0x200, %bx
movb $0x2, %ah
movb $0x1, %al
movb $0x0, %ch
movb $0x2, %cl
movb $0x0, %dh
movb $0x0, %dl
int $0x13
jc error
jmp second_sector
error:
# Print Error
movw $ERROR_MSG, %bp
call print
jmp .
ERROR_MSG:
.asciz "READ FLOPPY ERROR"
# ====================================================================
# print function
# ====================================================================
# es:bp as Message position, zero-term string
print:
# Get cursor position (Return dh = row, dl = column ...)
movb $0x03, %ah
movb $0, %bh
int $0x10
# Count String
xorw %cx, %cx
movw %bp, %si
cnt:
movb (%si), %ah
cmpb $0, %ah
je cnt_exit
incw %si
incw %cx
jmp cnt
cnt_exit:
# Print
# (ah = 0x13, al = 0x0, bh = 0, bl = 7, cx = strlen, dh:dl=row:column, es:bp=7c0:Message)
movw $0x1300, %ax
movw $0x7, %bx
int $0x10
# Move cursor to next line
incb %dh
xorb %dl, %dl
movb $0, %bh
movb $0x02, %ah
int $0x10
ret
#=====================================================================
#=====================================================================
# int 0xE820
# (eax = 0xe820) (ebx = 0) (es:di = smap) (ecx = buffer size = 0x200) (edx = smap)
#=====================================================================
getRam:
movl $0xe820, %eax
xorl %ebx, %ebx
movw $0x400, %di
movl $32, %ecx
movl $0x534D4150, %edx
getRam_loop:
int $0x15
movl %eax, %edx
movl $0xe820, %eax
movl $32, %ecx
addw $32, %di
cmpl $0, %ebx
jne getRam_loop
ret
.org 0x1FE, 0x62
.byte 0x55
.byte 0xAA
second_sector:
# Print
movw $HELLO_MESSAGE, %bp
call print
call getRam
# Clear Interrupt Flag
cli
# A20
inb $0x92, %al
orb $2, %al
outb %al, $0x92
# LGDT
lgdt GDTR
# Enter Protected Mode
movl %cr0, %eax
orl $1, %eax
movl %eax, %cr0
ljmp $0x08, $(0x7c00+OS_PMODE)
OS_PMODE:
jmp .
HELLO_MESSAGE:
.asciz "Hello world!"
GDT_NUL:
.long 0
.long 0
GDT_CODE32:
.long 0x0000FFFF
.long 0x00CF9A00
GDT_DATA32:
.long 0x0000FFFF
.long 0x00CF9200
GDTR:
.word 23
.long GDT_NUL+0x7c00
.org 0x400, 0x62
# SuperBlock
.long 184 # s_inode_count
.long 1440 # s_blocks_count
.long 72 # s_r_blocks_count
.long 1411 # s_free_blocks_count
.long 174 # s_free_inodes_count
.long 1 # s_first_data_block
.long 0 # s_log_block_size
.long 0 # s_log_frag_size
.long 8192 # s_blocks_per_group
.long 8192 # s_frags_per_group
.long 184 # s_inodes_per_group
.long 0 # s_mtime
.long 0x5D0F7311 # s_wtime
.word 0 # s_mnt_count
.word 0x1e # s_max_mnt_count
.word 0xEF53 # s_magic
.word 1 # s_state
.word 1 # s_errors
.word 0 # s_minor_rev_level
.long 0x5D0F7311 # s_lastcheck
.long 0xed4e00 # s_checkinterval
.long 0 # s_creator_os
.long 1 # s_rev_level
.word 0 # s_def_resuid
.word 0 # s_def_resgid
.long 11
.word 128
.word 0
.long 0
.long 0
.long 0
.quad 0x52145214
.quad 0x52145214
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.long 0
.org 0x800, 0x0
# Block Group Descriptor Table
.long 3
.long 4
.long 5
.word 1411
.word 174
.word 1
.word 0
.long
.long
.long
.org 0xC00, 0x0
# BLOCK BITMAP
.long 0x0FFFFFFF
.org 0x1000, 0x0
# INODE BITMAP
.word 0b1111111111
.org 0x1480, 0x0
# INODE TABLE
# Root directory
.word 0x41ED #i_mode
.word 0
.long 1024
.long 0
.long 0x5D0F7311
.long 0
.long 0
.word 0
.word 2
.long 2
.long 0
.long 0
# 15 blocks
.long 28
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.long 0
.org 0x7000, 0x0
.long 2
.word 12
.byte 1
.byte 2
.ascii "."
.long 2
.word 12
.byte 2
.byte 2
.ascii ".."
👉【幫我們一個忙!】👈
👋如果您喜歡這篇文章,請在下方按5個Like!
❤您的支持是我們最大的動力!
您只要登入帳號(Facebook、Google),在下方按5個Like,我們就會收到來自LikeCoin基金會的贊助。
您只需要支持我們,完全不會花到錢!