diff --git a/1kos/1.md b/1kos/1.md index ed11a26..f49202b 100644 --- a/1kos/1.md +++ b/1kos/1.md @@ -2,6 +2,17 @@ 显存地址是 0xb8000,屏幕是80*25,每个位置由两个字节决定。第一个字节决定所显示的字符,如0xb8000。第二个字节决定怎么显示字符(背景颜色,前景颜色),如0xb8001。 +Number Colour Name Number + bright bit bright Colour Name +0 Black 0+8=8 Dark Gray +1 Blue 1+8=9 Light Blue +2 Green 2+8=A Light Green +3 Cyan 3+8=B Light Cyan +4 Red 4+8=C Light Red +5 Magenta 5+8=D Light Magenta +6 Brown 6+8=E Yellow +7 Light Gray 7+8=F White + + **汇编命令知识**: cld: 方向标志置0,si和di 增1或增2; @@ -17,8 +28,8 @@ **串存储指令(数据从寄存器到内存)** cld - stosb # al -> es:[di], ++si - stosw # ax ->es:[di], si+=2 + stosb # al -> es:[di], ++di + stosw # ax ->es:[di], di+=2 **串读取指令(数据从内存到寄存器)** @@ -35,32 +46,31 @@
-    .text
-    .global start
-    .code16
+    .text                      #代码段
+    .global start              #start标识符可被外部引用
+    .code16                    #16位代码
 start:
-    jmp $0x0, $code
+    jmp $0x0, $code            #长跳转
 msg:
-    .string "1kos booting......\x0"
+    .string "1kos booting......\x0"   #字符串存储在msg标识符表示的地址
 code:
     movw    $0xb800,%ax        #显存地址在0xb8000
-    movw    %ax,    %es        
-    xorw    %di,    %di        #es:di = 0xb8000
-    xorw    %ax,    %ax
-    movw    %ax,    %ds        #ds:si = msg
-    movw    $msg,   %si
-    cld                #si和di自增
-    movb    $0x07,  %ah        #字符属性:黑底白字
-
-loop:
-    cmp        $0x0,   (%si)
-    je        end
-    lodsb            #ds:[si] -> al, ++si
-    stosw            #ax -> es:[di], di += 2  #al=字符 ah=属性
-    jmp        loop
-
+    movw    %ax,    %es        #es寄存器设置为0xb8000
+    xorw    %di,    %di        #es:di = 0xb8000
+    xorw    %ax,    %ax        #ax寄存器设置为0
+    movw    %ax,    %ds        #ds:si = msg
+    movw    $msg,   %si        #si指向msg字符串
+    cld                        #si和di自增(Clear Director)
+    movb    $0x07,  %ah        #字符属性:黑底白字
+
+loop:                          #循环体
+    cmp        $0x0,   (%si)   #判断是否到达msg的结尾0,等价于c代码:if(msg[n]=='0')
+    je        end              #Jump if equal
+    lodsb            #ds:[si] -> al, ++si ,从内存读取一个字节到al, si自增1
+    stosw            #ax -> es:[di], di += 2  #al=字符 ah=属性, 保存一个字节, di自增1
+    jmp        loop  #跳转到loop
 end:
-    jmp        end
+    jmp        end   #结束
 
diff --git a/1kos/2.md b/1kos/2.md index 5be2a5b..aeb7e76 100644 --- a/1kos/2.md +++ b/1kos/2.md @@ -58,6 +58,28 @@ BIOS磁盘存取功能 《IBM-PC汇编语言程序设计 第2版》p479 《IBM-P > EX:BX 数据缓冲区地址 +# 软盘L-CHS和P-CHS的转换 +物理扇区 +一个1.44MB软盘包含80个磁道. 磁道编号范围是0\~79. + +磁盘有上表面和下表面,当磁头定位到一个磁道的时候,上/下磁头都可以对这个位置的磁道进行读写. 编号(0,1). 每个表面上的某个磁道都被分为18个扇区,编号范围是1~18. 于是,一个磁盘包含80*18*2=2880个扇区. +逻辑扇区 +将磁盘的2880个扇区,从0开始编号,就得到0~2879编号的逻辑扇区. +我们定义,逻辑扇区从0磁道开始,先编码0磁头,再编码1磁头;然后开始编码1磁道… 于是,每个磁道就包含了0/1两个磁头,共36个扇区. +物理扇区转化为逻辑扇区 +对于x磁道,y磁头,z扇区,其逻辑扇区号码 +N = 2*18*x + 18*y + z -1 + 这里x取值范围(0,79).第0磁道表示其前面有0个磁道;第1磁道表示前面有1个磁道.第x磁道表示其前 +面有x磁道,因此有2*18*x. + 这里y从(0,1)取值,如果y=1就表示其前面还有18个磁道.  这里z取值范围是(1,18).最后z-1是因为逻辑扇区从0开始. +逻辑扇区转化为物理扇区 +下面根据上面的公式,计算对于给定的逻辑扇区N, 如何计算得出x,y,z + 对公式两侧同时除以2*18,就得到 N/(2*18) = x + y/2 + (z-1)/(2*18) +因为y/2肯定为0, (z-1)/(2*18)也是0,所以就得到x的值.  对公式两侧同时除以18,就得到 N/18 = (2*x) + y + (z-1)/18 = (2*x + y) + (z-1)/18 +我们已经知道(z-1)/18肯定为0. 对于(2*x + y),当y=1时是奇数,y=0时是偶数。对于这样一个数,我们计算(2*x + y) & 0x1,则这个计算式的值和y的取值一致。所以我们得到了y的计算方式。  对公式两侧同时对18取模,就得到 +N%18 = (2*18*x)%18 + (18*y)%18 + (z-1)%18 = 0 + 0 + (z-1)%18 =(z-1) + 因为(z-1)一定小于18,所以(z-1)%18=(z-1).于是我们得到z = 1 + N%18 + # 读取软驱的函数 在我的虚拟机中,软驱A是1.44MB格式的软驱,一共1440KB字节,共2880个扇区。地址表示为 T/H/S @@ -86,20 +108,21 @@ rd_sect: movw %si, %ax movb $18, %bl - divb %bl # al <-- (ax)/(bl) 的商 - # ah <-- (ax)/(bl)的余数 - incb %ah # 因为软驱的物理起始扇区号从1开始,而逻辑扇区号从0开始,所以要增1 + divb %bl # al <-- (ax)/(bl) 的商 + # ah <-- (ax)/(bl)的余数 + incb %ah # 因为软驱的物理起始扇区号从1开始,而逻辑扇区号从0开始,所以要增1 movb %ah, %cl # 起始扇区号,(int 13H ah=02h 中断的参数) - xorb %ah, %ah - movb $2, %bl - divb %bl +   xorb   %ah,   %ah        #ah=0 +   movb   $2,     %bl #bl=2 + divb %bl #al <-- (ax)/(bl) + #ah <-- (ax)/(bl)的余数 movb %ah, %dh # 磁头号,(int 13H ah=02h 中断的参数) movb %al, %ch # 磁道号,(int 13H ah=02h 中断的参数) popw %bx re_rd: movb $0x2, %ah # 读磁盘中断 - movb $1, %al # 读取1个扇区 + movb $1, %al # 读取1个扇区 movb $0x0, %dl # 读取软驱A int $0x13 jc re_rd