Notes on A x64 OS ================= 一个64位操作系统的设计与实现(田宇著)。一年前,读过一本32位操作系统实现的书,好像叫 Orange’s ,大概看到保护模式那里就没法再看下去了(读不懂),现在出了新书,讲64位OS的实现,不管怎么样先读起来,然后慢慢记录叭~ **notes INT 10h** chapter3的第一个boot.asm里面有个清屏的操作,按照书上的代码: :: mov ax, 0600h mov bx, 0700h mov cx, 0 mov dx, 0184h int 10h 实现不了鸭(指如果运行在bochs里的话)。``int 10h`` 主要是实现屏幕指定矩形区域的文字向上滚动的功能。若 ``al`` 设置成 ``00h`` 的话,是整个矩形区域的全体文字全部上移,所以书上说的若 ``al`` 设置成 ``00h`` 后面的几个参数都不需要管应该是不对的?(我的理解是至少要设置矩形区域的大小能够超过bochs显示的大小,然后把文字都向上移走,这样就实现了清屏的效果),我的代码如下所示: :: mov ax, 0600h mov bx, 0700h mov cx, 0000h mov dx, 0ffffh int 10h 这里 ``bx`` 设置区域属性的背景都是黑色的,``cx`` 设置矩形左上角坐标,``dx`` 设置矩形右下角坐标,我给设置成了最大的 ``0ffffh`` ,因为我也不知道这个bochs的窗口到底是多大,先放最大的可以偷懒。 T^T **mistake?** p45求根目录占用的扇区数,根据书中所给数据所列出来的式子是算不到14个扇区这个结果的,但是按照 .. math:: 根目录扇区数 = (根目录中的表项数 * 表项所占字节数) / 512 这个公式算出来确实是14(怀疑是公式列错了)。 **notes LBA and CHS** LBA - Logical Block Addressing,CHS - Cylinder-Head-Sector。逻辑块寻址和柱面/磁头/扇区格式的磁盘扇区号之间的转换。LBA格式的很好理解应该,逻辑寻址,所以扇区号就从0开始递增就可以了。关键是柱面/磁头/扇区格式的扇区号是怎么排的。首先,磁盘会有好多个盘面,每个盘面就有点像一张光盘,然后有很多张“光盘”叠起来,每个盘面分成很多个同心圆,每个圆就叫一个 **磁道** ,那因为有很多个盘面叠加,所以每个盘面上同样位置的磁道,在空间上面就好像组成了一个圆柱,每个盘面的相同位置的同心圆叠加一起形成的面叫做 **柱面** ,每一个磁道会分成很多个段,每个段就叫一个 **扇区** (老式的磁盘,每一个磁道所存储的数据量是一致的,这样的话越是外围的磁道密度就会越小,因为它的周长长,相反越是内部的磁道密度就会越大)。最后还有一个磁头的概念,假设我现在要开始读取一个磁道上面的内容,那就是有一个磁头,转过这个磁道的一圈,就算读取了一个磁道,那从哪个地方开始读,就是 **磁头** 的位置。 每个盘面都有两个面,每个面都可以存储数据,所以一个盘面应该有两个 **磁头** (上下两个)。一个盘面有多少个磁道整个磁盘就有多少个 **柱面** (这个应该也很好理解)。假设盘面的计数是从底下向上的,那最底下的盘,就有0号(在下面)和1号(在上面)两个盘面,这样的话,其实就是有0号和1号这两个磁头。柱面的计数是从外部向内部计数,最外面的柱面记为0,然后向里面递增。最后就是从磁头开始,转过一圈磁道,那从磁头开始,就是1号扇区,然后递增转完一圈(CHS计数里面柱面和磁头都是从0开始,好像唯独每个磁道的扇区是从1开始算的)。以书上那个1.44M的软盘算的话,设置一个磁道有18个扇区。举例:按照CHS如果是 0/0/12 这个扇区那就是,0号柱面,也就是最外面那个柱面的,0号磁头,那就是最下面那个盘面的下面的12号扇区,那就是从磁头开始转到第12个扇区。这个扇区对应的LBA扇区号就应该是11号(LBA是从0开始计数的)。如果是0/0/18,这个扇区表示的是0号柱面的0号磁头的最后一个扇区,对应LBA应该为17。0/1/1表示是还是0号柱面,但是是1号磁头,也就是变成了最底下那个盘的上面那个面, (括号内废弃,因为我rst没找到删除线标记哎quq。然后是那个面的最外面那个磁道(因为柱面是0)的第一个扇区,对应的LBA应该为18这里是划掉的是我自己理解上面出错了,所谓的柱面号,理解成磁道号或许好一点,这一个代表的是CHS里面的那个H的数值,所谓的磁头号,反而是代表了是哪一个盘面,我感觉下面那个我自己写的公式里的字母的表述好像有点倒了...)所以这样的话CHS的变化就是,先把0号整个柱面都用完,那这个柱面会有很多个盘面组成,其中每个盘面都会提供两个面,也就是两个磁头。接着就从最下面的那个磁头开始,转一圈就算用完了这个面。然后换上面那个面(也就是上面那个磁头),再继续...这样的话,第一个柱面用完了,之后就有点像整个磁头都向里面缩进一个磁道,然后再开始...,再开始的时候就是1号柱面了,得到了这样的关系就能得出LBA和CHS之间的换算关系。 .. math:: LBA = ((c * hpc) + h) * sph + (s - 1) c = LBA / (hpc * spt) h = (LBA / spt) mod hpc s = (LBA mod spt) + 1 其中 `c` , `h` 和 `s` 分别代表柱面号,磁头号和扇区号, `hpc` 和 `sph` 分别代表每柱面拥有的磁头数和每磁头(或者说每磁道)拥有的扇区数。 `sph` 写作 `spt` 或许更好(wiki上是 `spt` )。 **mistake?** 555我感觉书上的46页3-1的LBA转换为CHS的公式好像也没有写对。QuQ 噢,对不起,没有错,好像是一种不同的计算方法,我仔细看看先。**Here!** 在这里解释上面划掉的和书上的那个公式。(括号内废弃。书上的公式表示的 x面/x道/x扇区指的是第x个盘面的第x个磁道上的第x个扇区。这个和我上面写的区别在哪里呢,我上面的那个CHS是指第 `c` 个柱面(也就是第 `c` 个磁道)的第 `h` 个磁头(也就是哪个盘面)的第 `s` 个扇区。如果写的通顺一点那就是,第 `h` 个磁头(哪个盘面)上的第 `c` 个磁道(柱面)上的第 `s` 个扇区。如果我的理解正确的话,那么书上的那个x面/x道/x扇区是不符合CHS的原本的意思的。但是这两种意思都遵循同样的计算规则,也就是我上面最后说的:一定是先把一个柱面的磁道全部用完,然后再去用里面的磁道。最后,哎等等?那按照书上的写法写到INT 13h里面去是能找到的,岂不是我看的CHS的计算规则不是INT 13h采用的???)好了好了,都是一样的,(我大概是受到了一篇CSDN博客的影响,`链接 `_)来梳理一下书上的公式。首先用LBA除以每磁道扇区数(即spt),得到商Q和余数R,将商Q右移1位得到 `c` 的值(也就是说,把Q除以2,因为1.44的软盘hpc就是2,所以得到的 `c` 就是通过我们的公式算出来的,只是说计算的顺序不太一样),然后这里需要贴一下书上写的一个代码,是读取一个扇区的函数 ``Func_ReadOneSector`` 的片段: :: div bl inc ah mov cl, ah mov dh, al shr al, 1 mov ch, al and dh, 1 先说#s,#s的值就是R+1,这个应该没什么好说的,根据上面写的公式还有书上的计算顺序就很容易看出来了。重点是在1.44M下这个#h也就是磁头号的求法。下班了也没搞懂为什么#h就是Q... 啊啊啊啊啊,这个我感觉是书上真的写错了,书上写的商Q就是磁头号喔,但是代码上面却有这一句 ``and dh, 1`` , ``dh`` 在INT 13h里面就是代表的磁头号,说明要将商Q和1做与,结果就是磁头号。**敲黑板!** 和1做与,是和0001与,不是1111,5555... (讲道理按照公式应该是要mod 2,mod 2和 和1做与 是一样的结果鸭,神奇的数学...) ???后面这个Loader是认真的?这是人能看懂的吗?