前面提到可以將所有存儲器看成一個單一的邏輯空間,物理地址就是這邏輯空間上的真實地址,CPU 透過物理地址才能定位其上的單元空間。
8086 CPU 的地址總線有 20 條,但 CPU 的暫存器卻只有 16 位,那 CPU 該如何產生 20 位的物理地址呢?
答案是一個不夠就用兩個,CPU 內部會使用兩個 16 位的地址來表示一個 20 位的地址空間,這兩個地址分別是 段地址
和 偏移地址
,CPU 內部會將這兩個地址送到 地址加法器
經過運算後得到一個 20 位的 物理地址
,再由地址總線傳給外部設備。
物理地址計算方式:
物理地址 = 段地址 x 16 + 偏移地址
組合語言程式使用 H
表示 16 進制,假設段地址為 1000H 偏移地址為 500H,那計算後的物理地址等於多少呢?
物理地址
= 1000H x 16 + 500H
= 10000H + 500H
= 10500H
答案是 10500H,16進制的數值 x 16 等於將該數值左移一位。
物理地址由段地址和偏移地址計算得到,寫程式時可以利用段地址將程式分成不同的段管理,類似高階語言模組化的概念較好維護程式,不過因為偏移地址只有 16 位,所以每個段不能放太多東西,只有 64 KB 的大小。
來看一個例子:
段地址 偏移地址 物理地址
-------|--------|---------
3336 + 6510 = 39870
32F2 + 6950 = 39870
3116 + 8710 = 39870
這三個組合計算後得到的物理地址都是 39870,說明不同的段地址加偏移地址可以得到 相同的物理地址
,寫程式時要小心段重疊的問題。
之前介紹了四個通用暫存器,接下來介紹四個段暫存器 CS、DS、SS、ES,上面提到物理地址必需由段地址加偏移地址產生,其中的段地址就是由這四個暫存器提供。
段暫存器用途:
段暫存器出現了,那是不是有偏移地址暫存器呢,沒錯 IP 指令指標暫存器
就是用於存放偏移地址,通常會搭配 CS 一起使用。
看到下方的示意圖。
以上為指令執行的步驟,CPU 透過 CS 和 IP 指向要執行的指令,並在結束後更改偏移地址,指向下一條指令,不停的重複這五個步驟。
回憶之前改變暫存器的值,可以利用 mov
指令,例如 mov ax, 0010H,那可以用 mov 改變 CS 和 IP 的值嗎?
答案是不可以的,8086 CPU 不能用 mov 指令修改 CS 和 IP,不過提供了另一個更方便的 jmp
轉移指令。
jmp 用法:
jmp 段地址:偏移地址
jmp 1000:3 ; 等於物理地址 10003
jmp 某一個暫存器
mov ax, 1000
jmp ax ; 等於修改 IP 為 1000
jmp 有點像 C 語言的 goto
,在高階語言中大家應該都有默契不使用,但類似的寫法在組合語言卻是處處可見,難怪大家覺得組合語言難學。
今天介紹了物理地址和段暫存器,這兩個都是非常重要的概念,看完示意圖有沒有恍然大悟的感覺,哦~原來程式是這樣執行的~,這是以前學習高階語言時無法體會的,高階語言的最底層只接觸到記憶體也就是變數,再往下的 CPU 運作,就像隔了一層紗,朦朧一片,完全無法像組合語言可以看的這麼清楚。
明天要介紹 Debug 工具,今天就到這裡摟,感謝大家觀看。