Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 33 additions & 23 deletions 1kos/1.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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

**串读取指令(数据从内存到寄存器)**

Expand All @@ -35,32 +46,31 @@


<pre name="code" class="asm">
.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   #结束
</pre>


37 changes: 30 additions & 7 deletions 1kos/2.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down