05 印出在 memory 中的 character
程式要在 memory 裡才能執行,那麼我們寫在 boot sector 裡的程式,也是被 BIOS load 到 memory 中的某個地方才得以執行的。
這個位置在 0x7c00
,也就是 BIOS 會將 boot sector 的內容 load 到 memory 0x7c00
位置的地方。
以下是開機後的 memory layout:
接下來希望可以印出放在 memory 內的資料。
我們用些方式來嘗試印印看:
1 | mov ah, 0x0e |
label 表示從 code 一開始到該位置的 offset,the_secret
的值即是從 code 最開始到該位置的 offset。
[bx]
是是去 bx
register 內容所代表的的 memory address 拿資料,例如 bx
的值是 0x1e
,則 [bx]
就會是 memory address 0x1e
位置上的值,而非這段 code 被 load 到的 memory address 再加上 offset。
最後只有第三種方式可以成功印出 X
,這印證了 boot sector 確實被 load 到 memory 0x7c00
的位置。
既然 BIOS 會把 boot sector load 到 0x7c00
,這表示對每個 label 我們都要自己加上 0x7c00
才能得到正確的 address。每次要在 offset 加上 0x7c00
也太麻煩,所以可以在最開頭加上以下指令,就能表示「這段 code 預期會被 load 到 memory 哪個位置」,也就不用自己手動加:
1 | [org 0x7c00] |
加上這行後,就會是第二種方式印出 X
了。
Define strings
定義 string 需要知道關於 string 的兩件事:
- string 所在 memory address
- string 長度
前者可以用 label,如下所示:
1 | my_string: |
my_string
就是 string Hello World
的 memory address。指令 db
是 declare byte(s) of data 的意思,也就是直接將這幾個 byte 寫進 binary output file,而不要把它們當作 instruction。
那麼如何知道 string 的長度呢?
一種 convention 是定義 null-terminating string,也就是在 string 結尾加上一個 byte,其值為 0,像這樣:
1 | my_string: |
這樣在處理 string 時,只要遇到值為 0 的 byte 就知道 string 結束了。