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