📄 bootsect.s
字号:
!! SYS_SIZE is the number of clicks (16 bytes) to be loaded.! 0x3000 is 0x30000 bytes = 196kB, more than enough for current! versions of linux ! SYS_SIZE 是要加载的节数(16 字节为1 节)。0x3000 共为1 2 3 4 5 60x7c000x00000x900000x100000xA0000system 模块代码执行位置线路0x90200! 0x30000 字节=192 kB(上面Linus 估算错了),对于当前的版本空间已足够了。!SYSSIZE = 0x3000 ! 指编译连接后system 模块的大小。参见列表1.2 中第92 的说明。! 这里给出了一个最大默认值。!! bootsect.s (C) 1991 Linus Torvalds!! bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves! iself out of the way to address 0x90000, and jumps there.!! It then loads 'setup' directly after itself (0x90200), and the system! at 0x10000, using BIOS interrupts.!! 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, especially as this doesn't contain the! buffer cache as in minix!! The loader has been made as simple as possible, 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.!! 以下是前面这些文字的翻译:! bootsect.s (C) 1991 Linus Torvalds 版权所有!! bootsect.s 被bios-启动子程序加载至0x7c00 (31k)处,并将自己! 移到了地址0x90000 (576k)处,并跳转至那里。!! 它然后使用BIOS 中断将'setup'直接加载到自己的后面(0x90200)(576.5k),! 并将system 加载到地址0x10000 处。!! 注意! 目前的内核系统最大长度限制为(8*65536)(512k)字节,即使是在! 将来这也应该没有问题的。我想让它保持简单明了。这样512k 的最大内核长度应该! 足够了,尤其是这里没有象minix 中一样包含缓冲区高速缓冲。!! 加载程序已经做的够简单了,所以持续的读出错将导致死循环。只能手工重启。! 只要可能,通过一次取取所有的扇区,加载过程可以做的很快的。.globl begtext, begdata, begbss, endtext, enddata, endbss ! 定义了6 个全局标识符;.text ! 文本段;begtext:.data ! 数据段;begdata:.bss ! 堆栈段;begbss:.text ! 文本段;SETUPLEN = 4 ! nr of setup-sectors! setup 程序的扇区数(setup-sectors)值;BOOTSEG = 0x07c0 ! original address of boot-sector! bootsect 的原始地址(是段地址,以下同);INITSEG = 0x9000 ! we move boot here - out of the way! 将bootsect 移到这里 -- 避开;SETUPSEG = 0x9020 ! setup starts here! setup 程序从这里开始;SYSSEG = 0x1000 ! system loaded at 0x10000 (65536).! system 模块加载到0x10000(64 kB)处;ENDSEG = SYSSEG + SYSSIZE ! where to stop loading! 停止加载的段地址;! ROOT_DEV: 0x000 - same type of floppy as boot.! 根文件系统设备使用与引导时同样的软驱设备;! 0x301 - first partition on first drive etc! 根文件系统设备在第一个硬盘的第一个分区上,等等;ROOT_DEV = 0x306 ! 指定根文件系统设备是第2 个硬盘的第1 个分区。这是Linux 老式的硬盘命名! 方式,具体值的含义如下:! 设备号=主设备号*256 + 次设备号(也即dev_no = (major<<8) + minor )! (主设备号:1-内存,2-磁盘,3-硬盘,4-ttyx,5-tty,6-并行口,7-非命名管道)! 0x300 - /dev/hd0 - 代表整个第1 个硬盘;! 0x301 - /dev/hd1 - 第1 个盘的第1 个分区;! …! 0x304 - /dev/hd4 - 第1 个盘的第4 个分区;! 0x305 - /dev/hd5 - 代表整个第2 个硬盘盘;! 0x306 - /dev/hd6 - 第2 个盘的第1 个分区;! …! 0x309 - /dev/hd9 - 第2 个盘的第4 个分区;! 从linux 内核0.95 版后已经使用与现在相同的命名方法了。entry start ! 告知连接程序,程序从start 标号开始执行。start: ! 47--56 行作用是将自身(bootsect)从目前段位置0x07c0(31k)! 移动到0x9000(576k)处,共256 字(512 字节),然后跳转到! 移动后代码的go 标号处,也即本程序的下一语句处。mov ax,#BOOTSEG ! 将ds 段寄存器置为0x7C0;mov ds,axmov ax,#INITSEG ! 将es 段寄存器置为0x9000;mov es,axmov cx,#256 ! 移动计数值=256 字;sub si,si ! 源地址 ds:si = 0x07C0:0x0000sub di,di ! 目的地址 es:di = 0x9000:0x0000rep ! 重复执行,直到cx = 0movw ! 移动1 个字;jmpi go,INITSEG ! 间接跳转。这里INITSEG 指出跳转到的段地址。go: mov ax,cs ! 将ds、es 和ss 都置成移动后代码所在的段处(0x9000)。mov ds,ax !由于程序中有堆栈操作(push,pop,call),因此必须设置堆栈。mov es,ax! put stack at 0x9ff00. ! 将堆栈指针sp 指向0x9ff00(即0x9000:0xff00)处mov ss,axmov sp,#0xFF00 ! arbitrary value >>512! 由于代码段移动过了,所以要重新设置堆栈段的位置。! sp 只要指向远大于512 偏移(即地址0x90200)处! 都可以。因为从0x90200 地址开始处还要放置setup 程序,! 而此时setup 程序大约为4 个扇区,因此sp 要指向大! 于(0x200 + 0x200 * 4 + 堆栈大小)处。! load the setup-sectors directly after the bootblock.! Note that 'es' is already set up.! 在bootsect 程序块后紧根着加载setup 模块的代码数据。! 注意es 已经设置好了。(在移动代码时es 已经指向目的段地址处0x9000)。load_setup:! 68--77 行的用途是利用BIOS 中断INT 0x13 将setup 模块从磁盘第2 个扇区! 开始读到0x90200 开始处,共读4 个扇区。如果读出错,则复位驱动器,并! 重试,没有退路。INT 0x13 的使用方法如下:! 读扇区:! ah = 0x02 - 读磁盘扇区到内存;al = 需要读出的扇区数量;! ch = 磁道(柱面)号的低8 位; cl = 开始扇区(0-5 位),磁道号高2 位(6-7);! dh = 磁头号; dl = 驱动器号(如果是硬盘则要置位7);! es:bx ??指向数据缓冲区; 如果出错则CF 标志置位。mov dx,#0x0000 ! drive 0, head 0mov cx,#0x0002 ! sector 2, track 0mov bx,#0x0200 ! address = 512, in INITSEGmov ax,#0x0200+SETUPLEN ! service 2, nr of sectorsint 0x13 ! read itjnc ok_load_setup ! ok - continuemov dx,#0x0000mov ax,#0x0000 ! reset the disketteint 0x13j load_setupok_load_setup:! Get disk drive parameters, specifically nr of sectors/track! 取磁盘驱动器的参数,特别是每道的扇区数量。! 取磁盘驱动器参数INT 0x13 调用格式和返回信息如下:! ah = 0x08 dl = 驱动器号(如果是硬盘则要置位7 为1)。! 返回信息:! 如果出错则CF 置位,并且ah = 状态码。! ah = 0, al = 0, bl = 驱动器类型(AT/PS2)! ch = 最大磁道号的低8 位,cl = 每磁道最大扇区数(位0-5),最大磁道号高2 位(位6-7)! dh = 最大磁头数, dl = 驱动器数量,! es:di -?? 软驱磁盘参数表。mov dl,#0x00mov ax,#0x0800 ! AH=8 is get drive parametersint 0x13mov ch,#0x00seg cs ! 表示下一条语句的操作数在cs 段寄存器所指的段中。mov sectors,cx ! 保存每磁道扇区数。mov ax,#INITSEGmov es,ax ! 因为上面取磁盘参数中断改掉了es 的值,这里重新改回。! Print some inane message ! 在显示一些信息('Loading system ...'回车换行,共24 个字符)。mov ah,#0x03 ! read cursor posxor bh,bh ! 读光标位置。int 0x10mov cx,#24 ! 共24 个字符。mov bx,#0x0007 ! page 0, attribute 7 (normal)mov bp,#msg1 ! 指向要显示的字符串。mov ax,#0x1301 ! write string, move cursorint 0x10 ! 写字符串并移动光标。! ok, we've written the message, now! we want to load the system (at 0x10000) ! 现在开始将system 模块加载到0x10000(64k)处。mov ax,#SYSSEGmov es,ax ! segment of 0x010000 ! es = 存放system 的段地址。call read_it ! 读磁盘上system 模块,es 为输入参数。call kill_motor ! 关闭驱动器马达,这样就可以知道驱动器的状态了。! After that we check which root-device to use. If the device is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -