学习资料:

  1. Linux内核完全注释

  1. 操作系统真像还原

  1. 极客时间-Linux内核源码趣读

  1. Linux0.11内核源码

->上电

->80x86架构CPU会自动进入实模式

->从地址0xffff0自动执行程序代码

->bios执行系统检测,从物理地址0初始化中断向量,将第一个引导扇区512字节读入内存绝对地址0x7c00(BIOS把512字节的二进制数据从硬盘搬到内存中,作为操作系统的开发人员,我们只需要把代码放到0盘0磁道1扇区即可,对应的代码是bootsect.s)

->跳转到0x7c00(31KB)

->0x7c00当被执行的时候会把自己搬到0x90000(576KB)处,并把启动设备中后2KB代码(setup.s)读到0x90200处

# ROOT_DEV:    0x000 - same type of floppy as boot. 根文件系统设备使用与引导同样的软驱设备
#        0x301 - first partition on first drive etc 根文件系统设备在第一个硬盘的第一个分区上
#        0x300  /dev/hd0
#        0x301 /dev/hd1
#        ...
#        0x304 /dev/hd4
#        0x305 /dev/hd5 第二个硬盘
#        0x306 /dev/hd6 第二个硬盘第一个分区.equ ROOT_DEV, 0x301  ljmp    $BOOTSEG, $_start_start:   # ds = 0x07c0mov    $BOOTSEG, %axmov    %ax, %ds# es = 0x9000mov    $INITSEG, %axmov    %ax, %es# move 256 word from 0x7c00(DS:SI) to 0x9000(ES:DI)#ds:si=0x07c0:0x0000#es:di=0x9000:0x0000mov    $256, %cxsub    %si, %sisub    %di, %direp    movsw#间接跳转0x9000ljmp    $INITSEG, $go# 代码段移动后,重新设置堆栈段
go:    mov    %cs, %axmov    %ax, %dsmov    %ax, %es
# put stack at 0x9ff00.# cs=0x9000 ss=0x9000 sp=0xff00mov    %ax, %ssmov    $0xFF00, %sp        # arbitrary value >>512

int 0x13

功能02H

功能描述:读扇区

入口参数:AH=02H

AL=扇区数

CH=柱面

CL=扇区

DH=磁头

DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘

ES:BX=缓冲区的地址

功能00H

功能描述:磁盘系统复位

入口参数:AH=00H

DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘

出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明

load_setup:mov    $0x0000, %dx        # drive 0, head 0mov    $0x0002, %cx        # from sector 2, track 0mov    $0x0200, %bx        # address = 512, in INITSEG.equ    AX, 0x0200+4        # read 4 sector mov     $AX, %ax        # service 2, nr of sectorsint    $0x13            # read itjnc    ok_load_setup        # ok - continuemov    $0x0000, %dxmov    $0x0000, %ax        # reset the disketteint    $0x13jmp    load_setup

功能08H

功能描述:读取驱动器参数

入口参数:AH=08H

DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘

出口参数:CF=1——操作失败,AH=状态代码,参见功能号01H中的说明,否则, BL=01H — 360K

=02H — 1.2M

=03H — 720K

=04H — 1.44M

CH=柱面数的低8位

CL的位7-6=柱面数的该2位

CL的位5-0=扇区数

DH=磁头数

DL=驱动器数

ES:DI=磁盘驱动器参数表地址

ok_load_setup:# Get disk drive parameters, specifically nr of sectors/trackmov    $0x00, %dlmov    $0x0800, %ax        # AH=8 is get drive parametersint    $0x13mov    $0x00, %ch#seg csmov    %cx, %cs:sectors+0    # %cs means sectors is in %cs   保存磁道扇区数mov    $INITSEG, %axmov    %ax, %es #磁盘参数中断改掉了es的值,恢复es寄存器

# 后续装载系统模块需要装载240个扇区,是之前装载扇区数量的60倍,在此处显示一条信息提示用户等待

# Print some inane messagemov    $0x03, %ah        # read cursor posxor    %bh, %bhint    $0x10mov    $24, %cxmov    $0x0007, %bx        # page 0, attribute 7 (normal)#lea    msg1, %bpmov     $msg1, %bpmov    $0x1301, %ax        # write string, move cursorint    $0x10

把system 240个扇区拷贝到0x10000,关闭软驱电机

# ok, we've written the message, now
# we want to load the system (at 0x10000)mov    $SYSSEG, %axmov    %ax, %es        # segment of 0x010000call    read_itcall    kill_motor

检查要使用哪个根文件系统设备,如果指定了设备!=0,就直接使用指定设备,否则根据BIOS报告的磁道扇区数来确定是用那个设备

跳转setup.s 0x90200

# After that we check which root-device to use. If the device is
# defined (#= 0), nothing is done and the given device is used.
# Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
# on the number of sectors that the BIOS reports currently.#seg csmov    %cs:root_dev+0, %ax  # Root Device根文件系统设备cmp    $0, %ax  # 判断根设备号是否为0jne    root_defined # ZF = 0时跳转,即ax不为0时,即根设备已设置#seg cs
# 根设备未设置mov    %cs:sectors+0, %bx mov    $0x0208, %ax        # /dev/ps0 - 1.2Mbcmp    $15, %bx  # 取上面获取到每磁道扇区数,如果sectors=15则说明是1.2Mb的驱动器je    root_definedmov    $0x021c, %ax        # /dev/PS0 - 1.44Mbcmp    $18, %bx # 取上面获取到每磁道扇区数,如果sectors=18则说明是1.44Mb的软驱je    root_defined
undef_root:  # down机jmp undef_root
root_defined:#seg csmov    %ax, %cs:root_dev+0# after that (everyting loaded), we jump to
# the setup-routine loaded directly after
# the bootblock:ljmp    $SETUPSEG, $0

如果ES在64k,0x1000边界上,就立刻停止

# This routine loads the system at address 0x10000, making sure
# no 64kB boundaries are crossed. We try to load it as fast as
# possible, loading whole tracks whenever we can.
#
# in:    es - starting address segment (normally 0x1000)
#
sread:    .word 1+ SETUPLEN    # sectors read of current track
head:    .word 0            # current head
track:    .word 0            # current trackread_it:mov    %es, %axtest    $0x0fff, %ax #  TEST指令按位进行逻辑与运算,与AND指令的区别是两个操作数不会被改变
die:    jne     die            # es must be at 64kB boundaryxor     %bx, %bx        # bx is starting address within segmentrp_read:mov     %es, %axcmp     $ENDSEG, %ax        # have we loaded all yet?jb    ok1_readret# 计算和验证当前磁道需要读取的扇区数,放在ax寄存器中,根据当前磁道未读取的扇区数以及段内数据字节开始偏移位置,
# 计算如果全部读取这些未读扇区,所读总字节数是否超过64KB段长度的限制,若会超过,则根据此次最多读入的字节数(64KB-段内偏移位置),反算出此次需要读取的扇区数
ok1_read:#seg csmov    %cs:sectors+0, %ax # 获取磁道扇区数sub    sread, %ax # 减去当前磁道已读扇区数mov    %ax, %cx # cx = ax = 当前磁道未读扇区数shl    $9, %cx  # cx = cx * 512add    %bx, %cx # cx = cx + bx段内当前偏移值jnc     ok2_read # 没有超过64KB字节,则跳转ok2_readje     ok2_readxor     %ax, %ax #  加上此次将读磁道上所有未读扇区时会超过64KBsub     %bx, %ax # 此时最多能读入字节数(64KB-段内读偏移位置),再转换shr     $9, %ax # 读取扇区数ok2_read:call     read_trackmov     %ax, %cx # 该次操作已读扇区数add     sread, %ax # 当前磁道上已经读取的扇区数#seg cscmp     %cs:sectors+0, %ax # 如果当前磁道上的还有扇区未读,则跳转到ok3_readjne     ok3_read # 读该磁道的下一磁头面上的数据,如果已经完成,则去读下一磁道mov     $1, %axsub     head, %ax # 判断当前磁头号jne     ok4_read # 如果是0磁头号,则再去读1磁头面上的扇区数据incw    track # 否则去读下一磁道ok4_read:mov    %ax, head # 保存当前磁头号xor    %ax, %ax # 清当前磁道已读扇区数ok3_read:mov    %ax, sread # 保存当前磁道已读扇区shl    $9, %cx # 上次已读扇区数*512字节add    %cx, %bx # 调整当前段数据开始位置jnc    rp_read # 小于64KB边界值,则跳转到rp_read,继续读数据mov    %es, %ax  # 否则调整当前段,为读下一段数据作准备add    $0x1000, %ax # 将段基址指向为下一个64KB内存开始处mov    %ax, %esxor    %bx, %bx # 清段内数据开始偏移值jmp    rp_read# 读当前磁道上指定开始扇区和需读扇区数的数据到es:bx,参见第67行下对BIOS磁盘读中断
# int 0x13, ah=2
# al 需读扇区数;es:bx 缓冲区开始位置
read_track:push    %axpush    %bxpush    %cxpush    %dxmov    track, %dx # 取当前磁道mov    sread, %cx # 取当前磁道上已读扇区数inc    %cx # cl开始读扇区mov    %dl, %ch # ch当前磁道号mov    head, %dx # 取当前磁头号mov    %dl, %dh # dh 磁头号mov    $0, %dl # dl 磁动器号,0表示当前A驱动器and    $0x0100, %dx # 磁头号大于1mov    $2, %ah # ah = 2,读磁盘扇区功能号int    $0x13jc    bad_rt # 出错则跳转bad_rtpop    %dxpop    %cxpop    %bxpop    %axret# 执行驱动器复位操作,再跳转到read_track重试
bad_rt:    mov    $0, %axmov    $0, %dxint    $0x13pop    %dxpop    %cxpop    %bxpop    %axjmp    read_track#/*
# * This procedure turns off the floppy drive motor, so
# * that we enter the kernel in a known state, and
# * don't have to worry about it later.
# */
kill_motor:push    %dxmov    $0x3f2, %dxmov    $0, %aloutsbpop    %dxretsectors:.word 0msg1:.byte 13,10.ascii "Loading system ...".byte 13,10,13,10.org 508
root_dev:.word ROOT_DEV
boot_flag:.word 0xAA55

1. 把 bootsect.s 编译成 bootsect 放在硬盘的 1 扇区;2. 把 setup.s 编译成 setup 放在硬盘的 2~5 扇区;3. 把剩下的全部代码(head.s 作为开头,与各种 .c 和其他 .s 等文件一起)编译并链接成 system,放在硬盘的随后 240 个扇区

为什么不把系统模块直接加载到物理地址0x0000处运行,而要在setup中进行移动,这是因为setup程序代码开始部分需要利用BIOS的中断获取机器的一些参数,BIOS初始化的时候会在物理内存开始处放置大小为0x400字节(1kb)的中断向量表,因此需要在BIOS中断调用后才能将这个区域覆盖掉。

Linux0.11内核源码解析-bootsect.s相关推荐

  1. Linux0.11内核源码解析-setup.s

    学习资料: Linux内核完全注释 操作系统真像还原 极客时间-Linux内核源码趣读 Linux0.11内核源码 ->setup程序将system模块从0x10000~0x8ffff整块向下移 ...

  2. Linux0.11内核源码解析01

    系统整体布局 第一部分:进入内核前的苦力活 第二部分:大战前期的初始化工作 第三部分:一个新进程的诞生 第四部分:shell 程序的到来 第五部分:从一个命令的执行看操作系统各模块的运作 第六部分:操 ...

  3. linux-0.11 内核源码学习笔记一(嵌入式汇编语法及使用)

    linux内核源码虽然是用C写的,不过其中有很多用嵌入式汇编直接操作底层硬件的"宏函数",要想顺利的理解内核理论和具体实现逻辑,学会看嵌入式汇编是必修课,下面内容是学习过程中的笔记 ...

  4. Linux0.11内核源码分析(bootsect.s)

    Intel 80x86系列的CPU可以分别在16位实模式和32位保护模式下运行.为了兼容,也为了解决最开始的启动问题,Intel将所有80x86系列的CPU,包括最新型号的CPU的硬件都设计为加电即进 ...

  5. Linux0.11内核源码分析1-main函数运行之前的准备

    在阅读该文章之前,你起码有点操作系统的知识,了解实模式与保护模式的概念,了解分段机制,如果不懂得建议去阅读<操纵系统真象还原>这本书

  6. 小米9开源linux内核,发布即开源:小米开源新机Mi 11内核源码

    小米已开源最近发布的新机小米 11 的源码,小米 11 系统内核基于 Android R,源码已更新至小米手机内核的 GitHub 仓库,代号为 venus-r-oss. 由于 Android 系统是 ...

  7. linux0.11操作系统源码剖析fork.c

    fork() 用于创建 一个新的进程,一次调用两次返回.父进程返回子进程的PID 子进程是 0. fork() 采用写时复制,也就是 创建的时候 就复制了页表,并没有实际的内存空间,子进程这个时候和父 ...

  8. 关于互斥锁,条件变量的内核源码解析

    一.解决问题和适用范围 主要是用来等待一个条件,这个条件可能需要另一个线程来满足这个条件.这个和我们平常适用的pthread_mutex_lock的最大不同在于后者保护的一般是一个代码段(也就是关键区 ...

  9. 视频教程-YOLOv3目标检测:原理与源码解析-计算机视觉

    YOLOv3目标检测:原理与源码解析 大学教授,美国归国博士.博士生导师:人工智能公司专家顾问:长期从事人工智能.物联网.大数据研究:已发表学术论文100多篇,授权发明专利10多项 白勇 ¥78.00 ...

最新文章

  1. 简单的Linux扫描仪应用:C语言实现
  2. 在线生成 CSS3 的工具
  3. oracle domnode释放,关于释放引用DOM对象内存的问题
  4. 【小松教你手游开发】【面试必读(编程基础)】几种常用的设计模式介绍
  5. Mac 效率工具必备神器 —— Alfred
  6. 剑指Offer系列刷题笔记汇总
  7. 高通QMI_WWAN驱动详解
  8. 这个编辑器居然号称快如闪电!
  9. 男主龙失忆java_男主失忆的小说推荐:我忘了全世界,却记得对你的爱,一生不变...
  10. CSS代码缩写,占用更少的带宽/字体缩写/盒模型代码简写/颜色值缩写
  11. prefetch()
  12. 计算机财务管理知识点,财务管理知识点梳理(财务基础必背知识点整理篇)
  13. 自由复制360doc个人图书馆的文档
  14. 什么是脚本语言?什么是解释性语言?什么是编译性语言?
  15. Python全国二级等级考试(2019)
  16. Spring之——c3p0配置详解
  17. java计算机毕业设计驴友社区网站录屏源程序+mysql+系统+lw文档+远程调试
  18. abaqus无法定位html文档集,Abaqus:一种定位外部节点的方法?
  19. linux指令_齐南汕
  20. project 2010

热门文章

  1. 领导的生命周期理论(转载)
  2. 究极pytorch环境搭建
  3. 电路基础(4) 电阻电路的一般分析
  4. CocoaPods 使用的简单化
  5. SEO优化(如何对网站的文件和资源进行优化)?
  6. JavaScript 面向对象游戏案例:贪吃蛇
  7. AVAudioRecorder stop崩溃 在iOS13系统上
  8. 深度残差网络:ResNet
  9. 酷派大神f2AGPS服务器修改,关于AGPS定位服务器地址的设置
  10. 奇怪问题:stray '\200' in program