1 /*************************************************************************
  2  > File Name: boot.s
  3  > Author: Linpeng1577
  4  > Mail:linpeng1577@gmail.com or 15820224344@163.com
  5  > Created Time: Sun 02 Nov 2014 11:42:53 PM PST
  6  ************************************************************************/

  1 ! boot.s                        !代码源自赵博的《Linux内核完全剖析:基于0.12内核》,
                                    !这里注释是笔者的阅读理解
  2 BOOTSEG = 0x07c0                !这里其实是0x07c00,  在实模式下,80386为了兼容8086而定,
                                    !80386地址会自动左移动4位
  3 SYSSEG  = 0x1000                !这里其实是0x10000,道理同上
  4 SYSLEN  = 17                    !系统扇区17个
  5 entry start                     !入口标签
  6 start:                          !同上
  7         jmpi    go,#BOOTSEG     !启动,在实模式下,jmpi会将CS:EIP自动赋值,cs段指向BOOTSEG
  8 go:     mov     ax,cs           !ax起到temp作用,因为段寄存器之间无法直接赋值
  9         mov     ds,ax           !ds段指向BOOTSEG
 10         mov     ss,ax           !ss段指向BOOTSEG
 11         mov     sp,#400         !设置临时堆栈指针,其值需大于程序末端并有一定空间
 12!加载系统代码
 13 load_system:
 14         mov     dx,#0x0000
 15         mov     cx,#0x0002
 16         mov     ax,#SYSSEG
 17         mov     es,ax
 18         xor     bx,bx
 19         mov     ax,#0x200+SYSLEN
 20         int     0x13
 21         jnc     ok_load
 22 die:    jmp     die
 23!把内核代码移动到内存0开始处
 24 ok_load:
 25         cli                     !
 26         mov     ax,#SYSSEG      !
 27         mov     ds,ax           !
 28         xor     ax,ax           !
 29         mov     es,ax           !
 30         mov     cs,#0x1000      !
 31         sub     si,si           !
 32         sub     di,di           !
 33         rep     movw            !
  18        xor     bx,bx           !
 19         mov     ax,#0x200+SYSLEN!
 20         int     0x13            !
 21         jnc     ok_load         !
 22 die:    jmp     die             !
 23
 24 ok_load:
 25         cli
 26         mov     ax,#SYSSEG
 27         mov     ds,ax
 28         xor     ax,ax
 29         mov     es,ax
 30         mov     cs,#0x1000
 31         sub     si,si
 32         sub     di,di
 33         rep     movw
 34
 35         mov     ax,#BOOTSEG
 36         mov     ds,ax
 37         lidt    idt_48          !加载idt表
 38         lgdt    gdt_48          !加载gdt表
 39
 40         mov     ax,#0x0001
 41         lmsw    ax              !lmsw指令将CR0保护标志位PE设置为0X0001,即由实模式进入保护模式
 42         jmpi    0,8             !历史一跳,这里结束实模式,开启保护模式了,8是段选择符,
                                    !0是偏移地址,
                                    !8的二进制是1000,
                                    !说明是GDT第一段
 43
 44 gdt:    .word   0,0,0,0         !段描述符0不用
 45
 46         .word   0x07FF          !段描述符1,X86是小端模式CPU,第一个字是低地址,表示段限长
 47         .word   0x0000          !位0..15,16..23,24..31均为0,故段基址是0x00000
 48         .word   0x9A00          !代码段
 49         .word   0X00C0
 50
 51         .word   0x07FF          !段描述符2
 52         .word   0x0000          !段基址是0x00000,同代码段
 53         .word   0x9A00          !数据段
 54         .word   0x00C0
 55
 56 idt_48: .word   0               !idt表长度是0
 57         .word   0,0             !lidt指令会加载6字的信息,其中2字的长度值,4字的地址值
 58 gdt_48: .word   0x7ff           !gdt表长度0x7ff,十进制就是2048,每个描述符8字节,有256个描述符
 59         .word   0x7c00+gdt,0    !加载之前是实模式,所以基地址是段基址0x7c00(注意不是0x07c0,
                                    !地址和数值不要搞混)+gdt标签偏移(汇编标签其实就是段内偏移地址,
                                    !编译器自动赋值)
 60 .org 510                        !一个扇区有512字节,在最后一个字节,赋值0xAA55,表示这是一个有效扇区
 61         .word   0xAA55          !引导扇区有效标志

<linux/test_boot/boot.s [FORMAT=unix] [TYPE=ASM] [POS=18,21][30%] 07/11/14 - 22:58