当前位置:Linux教程 - Linux综合 - Linux 内核原代码 boot.s 部分的注释

Linux 内核原代码 boot.s 部分的注释

  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,所有数据都以
[1] [2] [3] 下一页 

   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
上一页 [1] [2] [3] 下一页 

   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对应    级联处理器.

(出处:http://www.sheup.com)


上一页 [1] [2] [3] 

   out #0xA1,al 于上面对应,告诉大家我就是IR2对应    级联处理器.

(出处:http://www.sheup.com)


上一页 [1] [2] [3] [4]