Browse Source

完善 MBR 部分

runningwater 1 year ago
parent
commit
cba2768934
7 changed files with 204 additions and 50 deletions
  1. 25 27
      .gitignore
  2. 7 3
      bochsrc
  3. 4 0
      boot/include/boot.inc
  4. 32 0
      boot/loader.S
  5. 110 20
      boot/mbr.s
  6. 26 0
      boot/readme.md
  7. BIN
      hd30M.img

+ 25 - 27
.gitignore

@@ -43,33 +43,31 @@ install_manifest.txt
 # ---> VisualStudioCode
 # ---> VisualStudioCode
 .settings
 .settings
 
 
-
 # ---> macOS
 # ---> macOS
-.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
-.DocumentRevisions-V100
-.fseventsd
-.Spotlight-V100
-.TemporaryItems
-.Trashes
-.VolumeIcon.icns
-
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon
+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk
 bochsout.txt
 bochsout.txt
 a.img
 a.img
-boot.bin
+*.bin

+ 7 - 3
bochsrc

@@ -6,12 +6,16 @@ vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest
 
 
 mouse: enabled=0
 mouse: enabled=0
 
 
-floppya: 1_44=a.img, status=inserted
+# floppya: 1_44=a.img, status=inserted
 
 
-boot: floppy
+# disk
+ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
+ata0-master: type=disk, mode=flat, path="hd30M.img", cylinders=60, heads=16, spt=63
+
+boot: disk
 
 
 log: bochsout.txt
 log: bochsout.txt
 
 
-logprefix: %t%e%d
+# logprefix: %t%e%d
 
 
 # memory: guest=512, host=256, block_size=512
 # memory: guest=512, host=256, block_size=512

+ 4 - 0
boot/include/boot.inc

@@ -0,0 +1,4 @@
+;---------------------------loader和kernel-------------------------------------
+MBR_BASE_ADDR equ 0x7c00   ; mbr 在内存中的位置
+LOADER_BASE_ADDR equ 0x900 ; loader 在内存中的位置 
+LOADER_START_SECTOR equ 0x2 ; loader 在硬盘上的逻辑扇区地址,即 LBA 地址 

+ 32 - 0
boot/loader.S

@@ -0,0 +1,32 @@
+; loader
+; 位于硬盘第 2 扇区(LBA 地址)
+; ----------------------------------------------------------------
+%include "boot.inc"
+SECTION LOADER vstart=LOADER_BASE_ADDR
+
+; 输出背景绿色,前景红色,并且跳动的字符串 "2 LOADER"
+    mov byte [gs:0x00], '2'
+    mov byte [gs:0x01], 0xA4
+
+    mov byte [gs:0x02], ' '
+    mov byte [gs:0x03], 0xA4
+
+    mov byte [gs:0x04], 'L'
+    mov byte [gs:0x05], 0xA4
+
+    mov byte [gs:0x06], 'O'
+    mov byte [gs:0x07], 0xA4
+
+    mov byte [gs:0x08], 'A'
+    mov byte [gs:0x09], 0xA4
+
+    mov byte [gs:0x0A], 'D'
+    mov byte [gs:0x0B], 0xA4
+
+    mov byte [gs:0x0C], 'E'
+    mov byte [gs:0x0D], 0xA4
+
+    mov byte [gs:0x0E], 'R'
+    mov byte [gs:0x0F], 0xA4
+
+    jmp $  ; 通过死循环使程序悬停在此

+ 110 - 20
boot/mbr.s

@@ -1,17 +1,26 @@
 ; 主引导程序
 ; 主引导程序
 ; ----------------------------------------------------------------
 ; ----------------------------------------------------------------
-SECTION MBR vstart=0x7c00
+%include "boot.inc"
+SECTION MBR vstart=MBR_BASE_ADDR
     mov ax, cs ; 0x00000000
     mov ax, cs ; 0x00000000
     mov ds, ax
     mov ds, ax
     mov es, ax
     mov es, ax
     mov ss, ax
     mov ss, ax
     mov fs, ax 
     mov fs, ax 
     mov sp, 0x7c00
     mov sp, 0x7c00
+    mov ax, 0xb800 ;文本模式显示
+    mov gs, ax
 
 
-    call CleanDisply
-    call GetCursorPosition
-    call DispStr
-	jmp $
+    ; call clean_display
+    ; call get_cursor_position
+    call disp_string
+	
+    mov eax, LOADER_START_SECTOR ; 起始扇区地址: LBA 地址
+    mov bx, LOADER_BASE_ADDR ; 写入的地址
+    mov cx, 1 ; 待写入的扇区数(1 个扇区)
+    call rd_disk_m_16  ; 读取硬盘数据
+
+    jmp LOADER_BASE_ADDR
 
 
 
 
 ;清屏,利用 0x06 号功能,上巻全部行,则可清屏
 ;清屏,利用 0x06 号功能,上巻全部行,则可清屏
@@ -25,7 +34,7 @@ SECTION MBR vstart=0x7c00
 ; DH=右下角行号 (DH、DL)=窗口的右下角位置(Y坐标,X坐标)
 ; DH=右下角行号 (DH、DL)=窗口的右下角位置(Y坐标,X坐标)
 ; DL=右下角列号
 ; DL=右下角列号
 ; ----------------------------------------------------------------
 ; ----------------------------------------------------------------
-CleanDisply:
+clean_display:
     mov ah, 0x06 ; 功能号
     mov ah, 0x06 ; 功能号
     mov al, 0x00 ; 上巻的行数(如果为 0,表示全部)
     mov al, 0x00 ; 上巻的行数(如果为 0,表示全部)
     mov bx, 0x700 
     mov bx, 0x700 
@@ -33,13 +42,13 @@ CleanDisply:
     mov dx, 0x184f ; 右下角: (80, 25)
     mov dx, 0x184f ; 右下角: (80, 25)
                 ; VGA 文本模式中,一行只能容纳 80 个字符,共 25 行. 
                 ; VGA 文本模式中,一行只能容纳 80 个字符,共 25 行. 
                 ;下标、从 0 开始,所以 Ox18=24, 0x4f=79
                 ;下标、从 0 开始,所以 Ox18=24, 0x4f=79
-    int 0x10      ; 调用 INT 0x10 功能
+    int 10h      ; 调用 INT 0x10 功能
     ret
     ret
 
 
 
 
 ;;;;;;;;;;;; 获取光标位置 ;;;;;;;;;;;;;
 ;;;;;;;;;;;; 获取光标位置 ;;;;;;;;;;;;;
 ; .get_cursor_position, 在光标位置打印字符
 ; .get_cursor_position, 在光标位置打印字符
-GetCursorPosition:
+get_cursor_position:
     mov ah, 0x3  ; 3 号功能是获取光标位置,需要
     mov ah, 0x3  ; 3 号功能是获取光标位置,需要
     mov bh, 0    ; 待获取光标的页号
     mov bh, 0    ; 待获取光标的页号
 
 
@@ -47,20 +56,101 @@ GetCursorPosition:
     ret 
     ret 
 ;;;;;;;;;;;; 获取光标位置结束 ;;;;;;;;;
 ;;;;;;;;;;;; 获取光标位置结束 ;;;;;;;;;
 
 
-; 13 号子功能打印字符串
+; 直接操作显卡显示
 ;--------------------------------------------------------
 ;--------------------------------------------------------
+; 输出背景色绿色,前景色红色, 并且跳动的字符串 "1 MBR"
 ;--------------------------------------------------------
 ;--------------------------------------------------------
-DispStr:
-	mov ax, BootMessage
-	mov bp, ax         ; ss:bp 为串首地址  
-
-	mov cx, 16         ; 串长度,不包括结束符个数
-	mov ax, 0x01301    ; 子功能号 13 显示字符及属性
-                ; al 设置写字符方式 al=01: 显示字符串,光标跟随移动
-	mov bx, 0x2  ; bh 显示的页号 bl 是字符属性,黑底绿字(bl=02h)
-	mov dl, 0
-	int 0x10
+disp_string:
+    mov byte [gs:0x00], '1'
+    mov byte [gs:0x01], 0xA4 ; A(K:1 R:0 G:1 B:0) 绿色背景闪烁, 4(K:0 R:1 G:0 B:0)前景红色
+
+    mov byte [gs:0x02], ' '
+    mov byte [gs:0x03], 0xA4
+    
+    mov byte [gs:0x04], 'M'
+    mov byte [gs:0x05], 0xA4
+
+    mov byte [gs:0x06], 'B'
+    mov byte [gs:0x07], 0xA4
+
+    mov byte [gs:0x08], 'R'
+    mov byte [gs:0x09], 0xA4
+
+    mov byte [gs:0x0A], '.'
+    mov byte [gs:0x0B], 0xA4
+
+    mov byte [gs:0x0C], '.'
+    mov byte [gs:0x0D], 0xA4
+
+    mov byte [gs:0x0E], '.'
+    mov byte [gs:0x0F], 0xA4
 	ret
 	ret
-BootMessage:	db "Hello OS World"
+;----------------------------------------------------------------
+; 读取硬盘数据
+; EAX=LBA 地址(扇区号)
+; BX=将数据写入的内存地址
+; CX=读取的扇区数
+rd_disk_m_16:
+;----------------------------------------------------------------
+    mov esi, eax ; 备份 eax
+    mov di, cx   ; 备份 cx
+
+; 第 1 步:设置要读取的扇区数
+    mov dx, 0x1f2  ; Primary 通道 Sector count
+    mov al, cl 
+    out dx, al ; 读取的扇区数
+
+    mov eax, esi ; 恢复 eax 
+
+; 第 2 步:设置 LBA 地址,存入 0x1f3 - 0x1f6 端口中
+    ; LBA 地址 7 ~ 0 位写入端口 0x1f3
+    mov dx, 0x1f3  ; Primary 通道 LBA low
+    out dx, al
+
+    ; LBA 地址 15 ~ 8 位写入端口 0x1f4
+    mov cl, 8
+    shr eax, cl
+    mov dx, 0x1f4  ; Primary 通道 LBA mid
+    out dx, al
+
+    ; LBA 地址 23 ~ 16 位写入端口 0x1f5
+    shr eax, cl
+    mov dx, 0x1f5  ; Primary 通道 LBA high
+    out dx, al
+
+    shr eax, cl
+    and al, 0x0f ; LBA 第 24~27 位
+    or  al, 0xe0  ; 设置 7-4 位为 1110, 表示 LBA 模式
+    mov dx, 0x1f6  ; Device
+    out dx, al
+
+; 第 3 步:向 0x1f7 端口写入命令 0x20
+    mov dx, 0x1f7  ; Command
+    mov al, 0x20
+    out dx, al 
+
+; 第 4 步:检测硬盘状态
+.not_ready:
+    ; 同一端口,写时表示写入命令,读时表示读入硬盘状态
+    nop
+    in al, dx    ; 0x1f7  Status
+    and al, 0x88 ; 第 4 位为 1 表示硬盘控制器已准备好数据传输,第 7 位为 1 表示硬盘忙
+    cmp al, 0x08
+    jnz .not_ready
+
+; 第 5 步:从 0x1f0 端口读取数据
+    ; di 为要读取的扇区数,一个扇区 512 字节,每次读入一个字,共需要 di*512/2 次,所以 di*256
+    mov ax, di 
+    mov dx, 256
+    mul dx       ; dx:ax = dx * 256
+    mov cx, ax 
+    mov dx, 0x1f0
+.go_on_read:
+    in ax, dx
+    mov [bx], ax    ; LOADER_BASE_ADDR (0~FFFFh)
+    add bx, 2
+    loop .go_on_read
+    ret
+
 times 510 - ($-$$) db 0
 times 510 - ($-$$) db 0
 db 0x55, 0xaa
 db 0x55, 0xaa

+ 26 - 0
boot/readme.md

@@ -0,0 +1,26 @@
+1. `boot.inc` 文件放置在 `include` 目录下,所以编译的时候需要添加 `-I` 参数
+
+    ```language=sh
+       boot git:(master) ✗ nasm -I include/ -o mbr.bin mbr.s
+       boot git:(master) ✗ nasm -I include/ -o loader.bin loader.S
+    ```
+
+2. 用 `dd` 命令将 mbr.bin 写入虚拟硬盘 `dd if=./mbr.bin of=/此处替换成你的安装目录
+/bochs/hd30M.img bs=512 count=1 conv=notrunc 回车`
+
+    ```sh
+       (base) ➜  boot git:(master) ✗ dd if=mbr.bin of=../hd30M.img bs=512 count=1 conv=notrunc
+        1+0 records in
+        1+0 records out
+        512 bytes transferred in 0.000350 secs (1462864 bytes/sec) 
+    ```
+
+3. 将生成的 `loader.bin` 写入硬盘第 2 个扇区。第 0 个扇区是 MBR,第 1 个扇区是空的未使用。`dd if=./loader.bin of=/此处替换成你的安装目录
+/bochs/hd30M.img bs=512 count=1 seek=2 conv=notrunc 回车`
+
+    ```sh
+        (base) ➜  boot git:(master) ✗ dd if=loader.bin of=../hd30M.img bs=512 count=1 seek=2 conv=notrunc
+        0+1 records in
+        0+1 records out
+        103 bytes transferred in 0.000102 secs (1011741 bytes/sec)
+    ```

BIN
hd30M.img