您的位置:首页 > 运维架构 > Linux

Linux0.11版源代码分析——boot/setup.s

2012-09-01 14:26 288 查看
Linux0.11版源码分析第二篇,setup.s注释分析。

!
! setup.s  (C) 1991 Linus Torvalds
!
! setup.s is responsible for getting the system data from the BIOS,
! and putting them into the appropriate places in system memory.
! both setup.s and system has been loaded by the bootblock.
!
! This code asks the bios for memory/disk/other parameters, and
! puts them in a "safe" place: 0x90000-0x901FF, ie where the
! boot-block used to be. It is then up to the protected mode
! system to read them from there before the area is overwritten
! for buffer-blocks.
!
!
! setup.s  (C) 1991 Linus Torvalds版权所有
!
! setup负责从BIOS获取系统数据,并存储在适当的内存位置,
! setup和system都已经被引导程序bootsect加载到内存了
!
!
! 这个代码向bios询问内存/硬盘和其它参数,然后将这些参数放置到安全的地方: 0x90000-0x901FF
! 也就是原来bootsect呆的地方。在该缓冲区被覆盖前,由保护模式的system读取
!
!注意!以下参数最好和bootsect中的相同
!

INITSEG  = 0x9000 ! we move boot here - out of the way                                       !boots所在位置
SYSSEG   = 0x1000 ! system loaded at 0x10000 (65536).                                        !system所在位置
SETUPSEG = 0x9020 ! this is the current segment                                              !setup所在位置

.globl begtext, begdata, begbss, endtext, enddata, endbss                                    !定义全局标识符
.text
begtext:
.data
begdata:
.bss
begbss:
.text

entry start                                                                                   !入口地址,跳转至标号start处
start:                                                                                        ! start标号

! ok, the read went well so we get current cursor position and save it for                    !ok,读取磁盘过程很成功,我们获取当前光标位置并保存
! posterity.                                                                                  !

mov ax,#INITSEG ! this is done in bootsect already, but...                                  !ds指向0x9000位置
mov ds,ax                                                                                   !
mov ah,#0x03 ! read cursor pos                                                             !利用中断0x10读取光标位置
xor bh,bh                                                                                   !
int 0x10  ! save it in known place, con_init fetches                                      !执行中断
mov [0],dx  ! it from 0x90000.                                                            !将该位置保存到ds:[0]处即0x90000

! Get memory size (extended mem, kB)                                                          !获取内存大小

mov ah,#0x88                                                                                !功能号
int 0x15                                                                                    !执行中断0x15
mov [2],ax                                                                                  !将内存大小保存到0x90002处

! Get video-card data:                                                                        !获取显卡数据

mov ah,#0x0f                                                                                !中断功能号
int 0x10                                                                                    !执行中断0x10
mov [4],bx  ! bh = display page                                                           !保存显示页
mov [6],ax  ! al = video mode, ah = window width                                          !保存显示模式、字符列数

! check for EGA/VGA and some config parameters                                                !检测EGA/VGA和一些配置参数

mov ah,#0x12                                                                                !功能号
mov bl,#0x10                                                                                !功能号
int 0x10                                                                                    !执行中断
mov [8],ax                                                                                  !保存不知道放了什么东西???
mov [10],bx                                                                                 !保存显存和显示模式
mov [12],cx                                                                                 !保存显卡特性参数

! Get hd0 data                                                                    !获取hd0的参数,第一个硬盘参数表的首地址是向量0x41的向量值
!为加载该向量
mov ax,#0x0000
mov ds,ax
lds si,[4*0x41]                                                                 !取出参数
mov ax,#INITSEG
mov es,ax
mov di,#0x0080
mov cx,#0x10
rep
movsb                                                                           !放置到指定位置

! Get hd1 data                                                                    !获取hd1参数,同上,只是放置的位置不同

mov ax,#0x0000
mov ds,ax
lds si,[4*0x46]
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
rep
movsb

! Check that there IS a hd1 :-)                                                  !检测是否有第二块硬盘

mov ax,#0x01500                                                              !驱动器号
mov dl,#0x81                                                                 !功能号
int 0x13                                                                     !执行中断查询
jc no_disk1                                                                 !flags中标记,判断是否存在第二个硬盘
cmp ah,#3                                                                    !比较ah中的返回值
je is_disk1                                                                 !有第二个硬盘
no_disk1:                                                                      !没有第二个硬盘,参数清零,就是前面保存的值清零
mov ax,#INITSEG
mov es,ax
mov di,#0x0090
mov cx,#0x10
mov ax,#0x00
rep
stosb
is_disk1:                                                                       !如果有第二个硬盘,准备进入保护模式

! 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:                                                                  !移动system
mov es,ax  ! destination segment
add ax,#0x1000
cmp ax,#0x9000
jz end_move
mov ds,ax  ! source segment
sub di,di
sub si,si
mov  cx,#0x8000
rep
movsw
jmp do_move

! then we load the segment descriptors                                     !加载描述符表

end_move:
mov ax,#SETUPSEG ! right, forgot this at first. didn't work :-)         !设置ds指向
mov ds,ax
lidt idt_48  ! load idt with 0,0                                    !加载中断描述符寄存器
lgdt gdt_48  ! load gdt with whatever appropriate                   !加载全局描述符寄存器

! that was painless, now we enable A20                                         !打开A20地址

call empty_8042                                                         !检测是否为空可写
mov al,#0xD1  ! command write                                        !命令字
out #0x64,al                                                               !写命令
call empty_8042                                                         !检测是否为空可写
mov al,#0xDF  ! A20 on                                               !命令字
out #0x60,al                                                               !写命令,使A20打开
call empty_8042                                                         !检查是否为空,如果为空,则可打开a20
! well, that went ok, I hope. Now we have to reprogram the interrupts :-(      !希望可以很好的运行,现在我们不得不去进行中断编程设置
! we put them right after the intel-reserved hardware interrupts, at           !我们将它放置在intel保留中断的后面,即int 0x20-0x2F
! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really           !在那里放置不会引起混乱,很不幸的是ibm在原来的pc机中
! messed this up with the original PC, and they haven't been able to           !搞混乱了再也没有改过来。bios设置中断在0x08-0x0f,所以我们
! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,           !需要重新对8259A重新编程控制,这一点也不好玩。
! which is used for the internal hardware interrupts as well. We just          !
! have to reprogram the 8259's, and it isn't fun.                              !

mov al,#0x11  ! initialization sequence                              !初始化
out #0x20,al  ! send it to 8259A-1                                   !
.word 0x00eb,0x00eb  ! jmp $+2, jmp $+2                             !
out #0xA0,al  ! and to 8259A-2                                       !
.word 0x00eb,0x00eb                                                      !
mov al,#0x20  ! start of hardware int's (0x20)                       !开始中断port
out #0x21,al                                                               !
.word 0x00eb,0x00eb                                                      !
mov al,#0x28  ! start of hardware int's 2 (0x28)                     !开始中断port
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0x04  ! 8259-1 is master                                    !设置为主芯片
out #0x21,al
.word 0x00eb,0x00eb
mov al,#0x02  ! 8259-2 is slave                                     !设置为从芯片
out #0xA1,al
.word 0x00eb,0x00eb
mov al,#0x01  ! 8086 mode for both                                  !设置主从芯片8086模式
out #0x21,al
.word 0x00eb,0x00eb                                                     !延时
out #0xA1,al
.word 0x00eb,0x00eb                                                     !跳转延时
mov al,#0xFF  ! mask off all interrupts for now                     !屏蔽主从芯片中断请求
out #0x21,al
.word 0x00eb,0x00eb                                                     !延时
out #0xA1,al

! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
! need no steenking BIOS anyway (except for the initial loading :-).
! The BIOS-routine wants lots of unnecessary data, and it's less
! "interesting" anyway. This is how REAL programmers do it.
!
! Well, now's the time to actually move into protected mode. To make
! things as simple as possible, we do no register set-up or anything,
! we let the gnu-compiled 32-bit programs do that. We just jump to
! absolute address 0x00000, in 32-bit protected mode.

mov ax,#0x0001 ! protected mode (PE) bit                                  !保护模式
lmsw ax  ! This is it!                                              !加载状态字
jmpi 0,8  ! jmp offset 0 of segment 8 (cs)                           !跳转到system处执行,8是段选择子

! This routine checks that the keyboard command queue is empty                 !这个程序检测键盘命令队列是否为空。这里不是用超时检测方法,
! No timeout is used - if this hangs there is something wrong with             !(.word 0x00eb,0x00eb跳转)是因为如果出问题,就是pc机问题
! the machine, and we probably couldn't proceed anyway.                        !我们没办法再进行下去了
empty_8042:                                                                    !检测8042控制器
.word 0x00eb,0x00eb                                                      !不用超时的方法,而是采用跳转的方法延时0x00eb其实就是jump
in al,#0x64 ! 8042 status port                                         !读控制器的的状态控制器
test al,#2  ! is input buffer full?                                !通过返回值检测输入控制器是否已满
jnz empty_8042 ! yes - loop                                               !如果满,则继续检测,直至该缓冲器为空,为写命令字提供条件
ret

gdt:
.word 0,0,0,0  ! dummy

.word 0x07FF  ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000  ! base address=0
.word 0x9A00  ! code read/exec
.word 0x00C0  ! granularity=4096, 386

.word 0x07FF  ! 8Mb - limit=2047 (2048*4096=8Mb)
.word 0x0000  ! base address=0
.word 0x9200  ! data read/write
.word 0x00C0  ! granularity=4096, 386

idt_48:
.word 0   ! idt limit=0
.word 0,0   ! idt base=0L

gdt_48:
.word 0x800  ! gdt limit=2048, 256 GDT entries
.word 512+gdt,0x9 ! gdt base = 0X9xxxx

.text
endtext:
.data
enddata:
.bss
endbss:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: