歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux資訊 >> 更多Linux >> Linux 內核原代碼 boot.s 部分的注釋

Linux 內核原代碼 boot.s 部分的注釋

日期:2017/2/27 14:15:04   编辑:更多Linux
  boot.s       boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself    out of the way to address 0x90000, and jumps there.       It then loads the system at 0x10000, using BIOS interrupts. Thereafter    it disables all interrupts, moves the system down to 0x0000, changes    to protected mode, and calls the start of system. System then must    RE-initialize the protected mode in it's own tables, and enable    interrupts as needed.       NOTE! currently system is at most 8*65536 bytes long. This should be no    problem, even in the future. I want to keep it simple. This 512 kB    kernel size should be enough - in fact more would mean we'd have to move    not just these start-up routines, but also do something about the cache-    memory (block IO devices). The area left over in the lower 640 kB is meant    for these. No other memory is assumed to be "physical", ie all memory    over 1Mb is demand-paging. All addresses under 1Mb are guaranteed to match    their physical addresses.       NOTE1 abouve is no longer valid in it's entirety. cache-memory is allocated    above the 1Mb mark as well as below. Otherwise it is mainly correct.       NOTE 2! The boot disk type must be set at compile-time, by setting    the following equ. Having the boot-up procedure hunt for the right    disk type is severe brain-damage.    The loader has been made as simple as possible (had to, to get it    in 512 bytes with the code to move to protected mode), and continuos    read errors will result in a unbreakable loop. Reboot by hand. It    loads pretty fast by getting whole sectors at a time whenever possible.    1.44Mb disks: sectors = 18    1.2Mb disks:    sectors = 15    720kB disks:    sectors = 9    .globl begtext, begdata, begbss, endtext, enddata, endbss    .text    begtext:    .data    begdata:    .bss    begbss:    .text BOOTSEG = 0x07c0    IN99vSEG = 0x9000    SYSSEG = 0x1000 system loaded at 0x10000 (65536).    ENDSEG = SYSSEG + SYSSIZE SYSSIZE在Makefile中定義的 ^_^ entry start    start:    mov ax,#BOOTSEG 現在應仍處在REAL MODE下.    mov ds,ax 移動自身從BOOTSEG:0000到IN99vSEG:0000    mov ax,#IN99vSEG 共512字節.    mov es,ax 那麼BOOT.S處在0x90000-0x90200.    mov cx,#256    sub si,si    sub di,di    rep    movw    jmpi go,IN99vSEG    go: mov ax,cs    mov ds,ax 將DS,ES,SS均設為0x9000,所有數據都以


   mov es,ax 0x9000為段偏移.    mov ss,ax 堆棧偏移0x9000    mov sp,#0x400 棧頂指針0x9000:0x0400,堆棧空間512bytes??    mov ah,#0x03 read cursor pos    xor bh,bh    int 0x10    mov cx,#24    mov bx,#0x0007 page 0, attribute 7 (normal)    mov bp,#msg1 顯示Loading System ...    mov ax,#0x1301 write string, move cursor    int 0x10 ok, we've written the message, now    we want to load the system (at 0x10000) mov ax,#SYSSEG    mov es,ax segment of 0x010000    call read_it 讀內核到0x10000    call kill_motor 殺了軟驅!? ^_^ if the read went well we get current cursor position ans save it for    posterity. mov ah,#0x03 read cursor pos    xor bh,bh    int 0x10 save it in known place, con_init fetches    mov [510],dx it from 0x90510. now we want to move to protected mode ... cli no interrupts allowed ! first we move the system to it's rightful place mov ax,#0x0000    cld 'direction'=0, movs moves forward    do_move:    mov es,ax destination segment    add ax,#0x1000    cmp ax,#0x9000    jz end_move    mov ds,ax source segment    sub di,di 置零,地址為0x1000:0000    sub si,si 置零,地址為0x9000:0000    mov cx,#0x8000 cx的作用是計數器    rep    movsw    j do_move 將位於低端0x1000:0000的內核移到內存    高端0x9000:0000,覆蓋了boot.S !? then we load the segment descriptors end_move: mov ax,cs right, forgot this at first. didn't work :-)    mov ds,ax    lidt idt_48 idt_48和gdt_48都是一個3個Word長的數據結構    lgdt gdt_48 第一個字說明(Global Interrupt) Descriptor    Table有多長,因為每個Table是四個字長,所以    可以得出整個DescriptorTable的entries.(見下)    後兩個字指出DT的具體位置.    idt_48是0,0,0;應表示沒有中斷描述符entries.    gdt_48有256個入口,第一個是個空入口,然後    定義了一個code段和一個data段.基址都是    0x00000000, !?那裡是什麼東西???    *** 0x00000000 != 0x0000:0000 *** that was painless, now we enable A20 call empty_8042    mov al,#0xD1 command write    out #0x64,al    call empty_8042    mov al,#0xDF A20 on    out #0x60,al    call empty_8042 well, that went ok, I hope. Now we have to reprogram the interrupts :-(    we put them right after the intel-reserved hardware interrupts, at    int 0x20-0x2F. There they won't mess up anything. Sadly IBM really

   messed this up with the original PC, and they haven't been able to    rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,    which is used for the internal hardware interrupts as well. We just    have to reprogram the 8259's, and it isn't fun.    初始化中斷處理器8259i    初始化順序為: 1. 向主8259A寫ICW1, 0x20    2. 向第二塊8259A寫ICW1, 0xA0    3. 向主8259A寫ICW2, 0x21    4. 向第二塊8259A寫ICW2, 0xA1    5. 如果ICW1指示有級聯中斷處理器,則初始化Master&Slave    (在下例中只有IR2有級聯8259A), 0x21, 0xA1    6. 向兩塊8259寫ICW4,指定工作模式.    輸入了適當的初始化命令之後, 8259已經准備好接收中斷請求.    現在向他輸入工作    命令字以規定其工作方式. 8259A共有三個工作命令字,但下例中只用過OCW1.    OCW1將所有的中斷都屏蔽掉, OCW2&OCW3也就沒什麼意義了.    ** ICW stands for Initialization Command Word;    OCW for Operation Command Word.    1. mov al,#0x11    out #0x20,al    .word 0x00eb,0x00eb jmp $+2, jmp $+2    2. out #0xA0,al and to 8259A-2    .word 0x00eb,0x00eb    3. mov al,#0x20 向主8259A寫入ICW2.    out #0x21,al 硬件中斷入口地址0x20, 並由ICW1 得知中斷向量長度 = 8 bytes.    .word 0x00eb,0x00eb    4. mov al,#0x28 start of hardware int's 2 (0x28)    out #0xA1,al 第二塊8259A的中斷入口是0x28.    .word 0x00eb,0x00eb    5. mov al,#0x04 8259-1 is master    out #0x21,al Interrupt Request 2有級聯處理. .word 0x00eb,0x00eb    mov al,#0x02 8259-2 is slave    out #0xA1,al 於上面對應,告訴大家我就是IR2對應    級聯處理器.



   out #0xA1,al 於上面對應,告訴大家我就是IR2對應    級聯處理器.



Copyright © Linux教程網 All Rights Reserved