Chapter 2:撰寫MBR主啟動紀錄
===
:::info
這是讀書筆記

作者:鄭鋼
出版社:佳魁資訊股份有限公司
出版日期:2017/05/31
:::
---
# Intel x86 Memory Map
>參考資料:[Memory Map (x86)](https://wiki.osdev.org/Memory_Map_(x86))

:::warning
可以和 ARM 架構的 memory map 作比較:
[ARMv8-A Foundation Platform memory ma](https://developer.arm.com/documentation/100961/1100-00/Programming-Reference/ARMv8-A-Foundation-Platform-memory-map)
:::
## 0x7c00 的故事
Intel 最一開始的 BIOS 是按照最小記憶體 32KB 去設計的:==0x0 - 0x7FFF==
由於最前要儲存 IVT(interrupt vector table):==0x0 - 0x3FF==
所以最初設計 BIOS 將 MBR 載入到記憶體最尾端,並且保留 1KB:==0x7c00 - 0x7FFF==
>相關參考資料:[[筆記] 為什麼在 x86,MBR 會被載入到 0x7C00?(完全版)](https://gist.github.com/snyiu100/b147b3175315b9e959e3a7a6281a82c1)
# MBR 的撰寫
## Intel x86 Instruction Set
[x86 instruction listings](https://en.wikipedia.org/wiki/X86_instruction_listings)
[x86 and amd64 instruction reference](https://www.felixcloutier.com/x86/)
## Intel x86 BIOS Interrupt
>參考資料:[BIOS中斷呼叫](https://zh.wikipedia.org/zh-tw/BIOS%E4%B8%AD%E6%96%B7%E5%91%BC%E5%8F%AB)

詳細的 int 0x10h:[INT 10H](https://zh.wikipedia.org/wiki/INT_10H)
## Intel x86 CPU Registers
>參考資料:[X86 CPU 暫存器 Register 大全](https://finalfrank.pixnet.net/blog/post/22992166)
https://wiki.osdev.org/CPU_Registers_x86


## 字元顯示
通常一頁的字元可以顯示 25\*80=2000,每個字元 2 bytes,總共 4000 bytes=4KB。
>[!Tip]這也是為何 Coding style 常常限制每行最多 80 個字元。
## Source Code
```asm
;主引導程序
;------------------------------------------------------------
SECTION MBR vstart=0x7c00
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00
; 清屏 利用0x06號功能,上卷全部行,則可清屏。
; -----------------------------------------------------------
;INT 0x10 功能號:0x06 功能描述:上卷窗口
;------------------------------------------------------
;輸入:
;AH 功能號= 0x06
;AL = 上卷的行數(如果為0,表示全部)
;BH = 上卷行屬性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;無返回值:
mov ax, 0x600
mov bx, 0x700
mov cx, 0 ; 左上角: (0, 0)
mov dx, 0x184f ; 右下角: (80,25),
; VGA文本模式中,一行只能容納80個字符,共25行。
; 下標從0開始,所以0x18=24,0x4f=79
int 0x10 ; int 0x10
;;;;;;;;; 下面這三行代碼是獲取光標位置 ;;;;;;;;;
;.get_cursor獲取當前光標位置,在光標位置處打印字符.
mov ah, 3 ; 輸入: 3號子功能是獲取光標位置,需要存入ah寄存器
mov bh, 0 ; bh寄存器存儲的是待獲取光標的頁號
int 0x10 ; 輸出: ch=光標開始行,cl=光標結束行
; dh=光標所在行號,dl=光標所在列號
;;;;;;;;; 獲取光標位置結束 ;;;;;;;;;;;;;;;;
;;;;;;;;; 打印字符串 ;;;;;;;;;;;
;還是用10h中斷,不過這次是調用13號子功能打印字符串
mov ax, message
mov bp, ax ; es:bp 為串首地址, es此時同cs一致,
; 開頭時已經為sreg初始化
; 光標位置要用到dx寄存器中內容,cx中的光標位置可忽略
mov cx, 5 ; cx 為串長度,不包括結束符0的字符個數
mov ax, 0x1301 ; 子功能號13是顯示字符及屬性,要存入ah寄存器,
; al設置寫字符方式 ah=01: 顯示字符串,光標跟隨移動
mov bx, 0x2 ; bh存儲要顯示的頁號,此處是第0頁,
; bl中是字符屬性, 屬性黑底綠字(bl = 02h)
int 0x10 ; 執行BIOS 0x10 號中斷
;;;;;;;;; 打字字符串結束 ;;;;;;;;;;;;;;;
jmp $ ; 使程序懸停在此
message db "1 MBR"
times 510-($-$$) db 0
db 0x55,0xaa
```
## Compile
```
nasm -o mbr.bin mbr.S
```
## Hard Disk Image
```
dd if=../code/mbr.bin of=./sr_hd60m.img bs=512 count=1 conv=notrunc
```

## Result

# MBR 大哉問
## 是否一定存在 MBR?
>參考資料:[Does every storage device have MBR?](https://superuser.com/questions/1649454/does-every-storage-device-have-mbr)