(如有错误请立即指正,么么哒!)

!    boot.s
!
! It then loads the system at 0x10000, using BIOS interrupts. Thereafter
! it disables all interrupts, changes to protected mode, and calls the
! 从0X10000开始,使用BIOS中断加载系统。
! 使所有的中断失灵,转入保护模式……

BOOTSEG = 0x07c0            
! boot段,BIOS会自动将操作系统的程序加载到这一段中开始执行,这时连操作系统都不会存在。

SYSSEG  = 0x1000            ! system loaded at 0x10000 (65536).
! Linus注释说系统加载到0x10000,我们一会回来看这个SYSSEG是做什么用的……(算作遗留问题①)

SYSLEN  = 17                ! sectors occupied.
! sectors的意思是扇区,这里指占用了17个扇区。
! bochs中模拟的加载器是一个1.2MB的软盘,软盘这里一个扇区的大小是512B

entry start
start:
    jmpi    go,#BOOTSEG
    ! jmpi 是段内跳转,由于是在实模式下,后面的操作数是段的基地址。
    ! 这句的意思就是说跳到以#BOOTSEG为基址的段的偏移为go的地方,go在哪里?往下看:
go:    mov    ax,cs
    mov    ds,ax
    mov    ss,ax
    ! 上面的jmpi的意思就是从这个go开始的,接着是3条mov指令,把cs置给ds和ss
    ! 表示在这段代码中,代码段,数据段和堆栈段是重叠的
    mov    sp,#0x400        ! arbitrary value >>512
    ! arbitrary value:猜猜它是啥意思?(遗留问题②)">>"是远大于。
! ok, we've written the message, now
! 好的,我们已经写好了message(这个message在哪里?遗留问题③)
load_system:
! 开始加载系统啦!
! int 0x13是BIOS自留的中断指令,显然在这里要读取磁盘的内容,并且装载到某一个地方,
! 这个地方是哪里呢?(遗留问题④)
    mov    dx,#0x0000    ! 32-bit下立即数都要以#开头
    mov    cx,#0x0002    ! 置dx和cx,为 int 0x13做准备
    mov    ax,#SYSSEG   
    mov    es,ax        ! 把#SYSSEG装载到了es中
    xor    bx,bx        ! 清空bx
    mov    ax,#0x200+SYSLEN ! ah置为0x02,al置为0x11(十进制就是17)
    int     0x13
    ! AH=02H 指明要读扇区
    ! AL:要读的扇区数
    ! DL:驱动器号
    ! DH:所读磁盘的磁头号(系统在0号驱动器的第0磁头所指位置)
    ! CH 磁道号的低8位数
    ! CL 低5位放入所读起始扇区号,位7-6表示磁道号的高2位
    ! ES:BX 读出数据的缓冲区地址。
    ! 返回参数:
    ! 如果CF=1,AX中存放出错状态。读出后的数据在ES:BX区域依次排列。
    jnc    ok_load
    ! 表示CF没有被置位,即没有出错,跳转到 ok_load 这里去执行,否则就die,死循环在这里
    ! 下面解决一下遗留问题④,系统代码被读到那里去了?ES:BX在调用int 0x13前是0x1000:0x0000,
    ! 请看文档开头,这确实也是作者希望系统被加载到的位置。同时解决了遗留问题①
die:    jmp    die

! now we want to move to protected mode ...
! 下面开始跳到保护模式啦!
ok_load:
    cli            ! no interrupts allowed !
    ! 关闭中断……这个时候因为要重新设置中断向量表,覆盖掉原来的中断描述符,所以要把中断关闭了
    mov    ax, #SYSSEG
    mov    ds, ax ! ds置成#SYSSEG,表示系统代码开始的地方
    xor    ax, ax ! ax清零
    mov    es, ax ! es置零
    mov    cx, #0x2000 !cx置0x2000
    sub    si,si 
    sub    di,di  ! si,di清零
    rep
    movw
    ! rep表示将movw指令重复cx寄存器中的数次,默认将DS:SI所指的数据移动到ES:DI所指的位置,ES是零,显然把0x1000位置的代码转移到0x0000

  ! 从ds:si = 0x1000:0x0000 复制到 es:di = 0x0000:0x0000为止
    mov    ax, #BOOTSEG
    mov    ds, ax
    ! 将ds段设置为0x7c00,这个位置是boot.s存储的位置,*****我认为目前boot.s不仅存在于这个0x7c00处,还存在于内存最开始处。
    ! 重新设置这个0x7c00的目的是为了从这里取数据啊!你看看这不马上就从这里取出idt_48和gdt_48了么!
    ! 17个扇区的系统有多大呢?17*512B < 9KB < 64KB(0x00000--0x10000),因此不会覆盖后面的东西
    lidt    idt_48        ! load idt with 0,0
    lgdt    gdt_48        ! load gdt with whatever appropriate
    ! 设置idtr和gdtr两个寄存器的值,具体的值参见后面idt_48和gdt_48这两个位置

! 进入保护模式之前要做三件事,或者说三个步骤:
!    1~设置好gdt
!    2~设置gdtr,因为这直接决定了进入保护模式后第一条指令的寻址方式
!    3~更改状态字
! absolute address 0x00000, in 32-bit protected mode.
    mov    ax,#0x0001    ! protected mode (PE) bit
    ! 在这里lmsw加载状态字,把PE置位后,进入保护模式……
    lmsw    ax        ! This is it!
    jmpi    0,8        ! jmp offset 0 of segment 8 (cs)
    ! 跳到cs中的0处开始执行啦,就是进入head.s了吧
    ! 为什么是8呢?在这里,系统已经进入了保护模式了。8在这里表示的是段选择符。
    ! (段选择符16位,高13位为索引,第2位用来区分gdt(0)还是ldt(1),第1,0位用来表示特权级,
    ! 因此当选定8的时候,表示0000000000001000,求出选择哪一段的方法是将段选择符右移三位,8表示选中gdt表第1项,内核代码段)

! 下文设置了gdt全局描述符表,这个gdt符表的地址有"gdt"这个标记来标定
! gdt表项有8个字节,于是在gdt_48那里说到有256个entires,也就是256项

! 后面的数值具体表示的意思都在后面由Linus自己注释清楚了。 
gdt:    .word    0,0,0,0        ! dummy

.word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb),段长8MB
    .word    0x0000        ! base address=0x00000,基地址0x00000,实模式下有20位地址码,2^20寻址空间。
    .word    0x9A00        ! code read/exec,表示代码段,可读可执行
    .word    0x00C0        ! granularity=4096, 386,颗粒度(我不懂)

.word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
    .word    0x0000        ! base address=0x00000
    .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    0x7ff        ! gdt limit=2048, 256 GDT entries
    .word    0x7c00+gdt,0    ! gdt base = 07xxx
    ! 在这个状态下的gdt是设置在这个位置的。
    ! gdtr的高32位表示gdt基地址,低16位表示gdt的长度,在这里0x7ff表示0-2047,也就是limit=2048
.org 510
    ! 最后在说一下子这个指令,这个指令是让下面一条指令开始在510这个位置的,也就是说,它规定了boot.s的长度是512B,最后还有一个2B长的数
    .word   0xAA55

[Operationg System Labs] 我对 Linux0.00 中 boot.s的理解和注释的更多相关文章

  1. [Operating System Labs] 我对Linux0.00中 head.s 的理解和注释

    ?21,#  head.s contains the 32-bit startup code.#  head.s 是32位的启动代码 #  Two L3 task multitasking. The ...

  2. Linux-0.00运行环境搭建【转】

    转自:http://blog.csdn.net/rosetta/article/details/8933240 这里的Linux-0.00由Linus Torvalds写的Linux最初版本,只是打印 ...

  3. 从linux0.11中起动部分代码看汇编调用c语言函数

    上一篇分析了c语言的函数调用栈情况,知道了c语言的函数调用机制后,我们来看一下,linux0.11中起动部分的代码是如何从汇编跳入c语言函数的.在LINUX 0.11中的head.s文件中会看到如下一 ...

  4. 关于导出Excel出现异常的解决办法。:System.UnauthorizedAccessException: 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} 的组件时失败

    异常信息为:System.UnauthorizedAccessException: 检索 COM 类工厂中 CLSID 为 {000209FF-0000-0000-C000-000000000046} ...

  5. 【排除解决】System.Runtime.InteropServices.ExternalException (0x80004005): GDI+ 中发生一般性错误

    前言: 今天项目发布上线,发布到正式环境验证功能的时候忽然方向之前做的一个图片合成的功能报错了提示:System.Runtime.InteropServices.ExternalException ( ...

  6. mysql数据库导出模型到powerdesigner,PDM图形窗口中显示数据列的中文注释

    1,mysql数据库导出模型到powerdesigner 2,CRL+Shift+X 3,复制以下内容,执行 '******************************************** ...

  7. C++中 类的构造函数理解(一)

    C++中 类的构造函数理解(一) 写在前面 这段时间完成三个方面的事情: 1.继续巩固基础知识(主要是C++ 方面的知识) 2.尝试实现一个iOS的app,通过完成app,学习iOS开发中要用到的知识 ...

  8. C++编程中对缓冲区的理解(OS默认4096大小的缓冲区,有例子,很形象)

    什么是缓冲区缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区.缓冲区根据其对应的是输入设备还是输出 ...

  9. 转 在PowerDesigner的PDM图形窗口中显示数据列的中文注释

    Name是名称(字段描述),Code是字段名称,Comment是注释名称,ER图中显示的是Name.一般设计时,Name跟comment都设计成描述, 而设计时候常把comment写成中文,name保 ...

随机推荐

  1. 自然数e这家伙怎么蹦跶出来的?

    自然数e这家伙怎么蹦跶出来的? 之前看过一篇中文介绍自然数e的blog,引起了我的兴趣 原文是阮一峰大牛(我认为必须很有必要尊敬的称,大牛)嚼烂了吐出来的哈哈,只是我认为还是自己去看原文比較好 感觉非 ...

  2. HDU1863 畅通project 【最小生成树Prim】

    畅通project Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. Liferay 6.1开发学习

    http://www.huqiwen.com/2013/01/10/liferay-6-1-development-study-17-springmvc-portlet/ http://www.blo ...

  4. java Serializable和Externalizable序列化反序列化详解--转

    一.什么是序列化? “对象序列化”(Object Serialization)是 Java1.1就开始有的特性. 简单地说,就是可以将一个对象(标志对象的类型)及其状态转换为字节码,保存起来(可以保存 ...

  5. C++学习笔记39:进程概念

    进程的基本概念 进程是描述程序执行过程和资源共享的基本单位 主要目的:控制和协调程序的执行 进程相关函数 用户与组ID函数 创建进程:system(),fork(),exec() 终止进程:kill( ...

  6. grunt -- javascript自动化工具

    grunt 是一个基于npm,node.js 用js编写的工具框架,可以自动完成一些重复性的任务(如合并文件,语法检查,压缩代码), grunt拥有庞大的插件库,可以满足各种自动化批处理需求,常用的插 ...

  7. GUID的广泛使用

    GUID(Global unique identifier)全局唯一标识符,它是由网卡上的标识数字(每个网卡都有唯一的标识号)以及 CPU 时钟的唯一数字生成的的一个 16 字节的二进制值. GUID ...

  8. iptables阻止服务器被攻击

    下列规则将会阻止来自某一特定IP范围内的数据包,因为该IP地址范围被管理员怀疑有大量恶意攻击者在活动:  # iptables -t filter -A INPUT -s 123.456.789.0/ ...

  9. xcode 删除 Provisioning Profile

    provisioning profile path: ~/Library/MobileDevice/Provisioning Profiles 打开并日期排序,删除老的 provisioning pr ...

  10. DirectX Graphics Infrastructure (DXGI) 全屏设置相关问题

    原文地址: https://msdn.microsoft.com/en-us/library/windows/desktop/ee417025(v=vs.85).aspx 未完待续... DXGI是在 ...