微機(二) 8086 寄存器 存儲器 尋址 段地址 有效地址

前言 ´・ᴗ・`

  • 本節主要以8086爲例講了CPU的一些內置寄存器及其作用 不要求記住 因爲只有用到的時候這些名稱才更加有意義
  • 筆者在玩嵌入式的時候 比如stm32 涉及深入的硬件debug 就遇到了內部寄存器級別的問題 所以這個也算是對嵌入式的鋪墊
  • 本篇內容將會幫助你學習…
    • 0 8086 CPU的基本結構
    • 1 Intel 8086 寄存器種類 作用
    • 2 寄存器之間部分相互聯繫
    • 3 存儲器 內存的CPU尋址方法

微機系統的構成

這裏我們提綱挈領的明白 接下來我們學習的部分到底是屬於哪裏
大部分簡單的單片機乃至複雜的PC 其實組成結構都是相近的 可以說都從那個簡單的8086進化而來
意味着我們掌握8086 就可以一通百通
姑且給簡單的計算機(現在就是嵌入式的單片機了)起個名字:微機

  • 微機系統
    • 硬件系統
      • 微機(可以理解爲電腦)
        • CPU
        • 存儲器 (內存)
        • IO 接口
        • 總線 Bus
      • 外設 perpherial
    • 軟件系統
      • 系統軟件(OS操作系統自帶的)
      • 應用軟件 就是我們自己安裝的

接下來的部分 聚焦 CPU以及與存儲器的聯動

外設

外設(perpherial 直譯 外圍的 相對於CPU當然是外圍的) 就是我們CPU控制的外圍設備

簡單而言 你用樹莓派控制一個LED燈 你可以認爲樹莓派是CPU, LED燈是外設
這兩者的橋樑就是一個接口(interface)
我們說任何接口 都是有 溝通的橋樑的意思
IO設備與CPU的接口就是IO(input output輸入輸出) 接口

爲啥叫 輸入輸出接口呢? 因爲信息是雙向的啊 既有輸入也有輸出
比如,
CPU想通過+5V的信號讓燈亮 就是CPU往接口輸入+5V的信號 然後LED自然就接受到了這個+5V然後亮起來了咯
當然 外設除了我們給它供電的(燈 舵機)
也有反饋信息的 比如傳感器(sensor)
這個時候 在CPU的角度上看 接口是輸出信息的(來源於傳感器)
所以 接口可以發送或者接收信息 所謂輸入 輸出接口
(當然 設置這個接口的功能是輸入還是輸出 是推輓輸出還是端口複用 都是我們編程序控制的)

所以CPU和外設的關係可以簡單地看成這樣:
在這裏插入圖片描述
接口有很多種 爲了適用於 或者說驅動(drive)不同的外設 這裏大致看看了解就好
在這裏插入圖片描述

CPU

物理意義上 就是分爲內部與外部

  • 外部:
    存儲器就是我們熟知的內存
    CPU只負責計算 當然還有少量的寄存器存儲計算結果的 但是容量很少
    在這裏插入圖片描述
    前面講了IO端口(就是IO接口 一個意思)那麼這玩意在哪裏呢?屬於CPU 這是肯定的
    就在主板上:)一堆集成電路里面 是和CPU配套的電路 但不屬於CPU:)
    再問個簡單的問題:爲啥內存能夠和CPU直接連接 爲啥硬盤不行?
    CPU頻率動不動幾個GHZ 內存也是如此,但是硬盤?喵喵喵?慢的一批啊
    所以只有內存跟得上CPU的speed 還有顯存(可能比內存還快) 同理。
    • 地址總線address bus
      我們CPU訪問IO端口或者訪問存儲單元(在內存裏面的),需要通過地址來找到他們的位置 這時需要地址總線 傳地址(地址碼)。這是單向的
    • 數據總線data bus
      顧名思義 就是傳數據 但是請注意 程序也是數據 指令也是數據 單純的0001H也是數據
    • 控制總線control bus
      管理上面兩個總線的 一般是傳送控制指令 或者外設反饋狀態信息 (不用深究)
    • 總線寬度的影響
      地址線寬度影響尋址能力 就是內存可以劃分成一個個字節位單位的存儲單位 那你需要給每個字節都來個標號 這就是地址 類似每個人家的門牌號
      220B=10241024B=1MB2^{20}B=1024*1024B=1MB 20位的地址就可以對應1024*1024個字節 其他同理
      在這裏插入圖片描述
      內部:
      在這裏插入圖片描述
      在這裏插入圖片描述

CPU結構 單元化 功能性的視角

實際上 我們嵌入式等常見的應用(各種調試工具)看待CPU 都是以功能的角度看待其內部結構的
我們可以理解CPU爲大型機房 自然機房裏面有很多服務器 類似一個個單元(unity)
CPU也是如此 由一個個單元組成 其中

名稱 英文 中文
EU execution 執行單元
ALU arithmetic 算術單元
BIU bus interface 總線接口單元

在這裏插入圖片描述
我們之前說 接口是CPU與外設的橋樑
而CPU內部與接口對接的就是BIU 總線接口單元

注意 我們常常說CPU做了什麼 其實具體實現,是靠這一個個單元,他們功能幾乎相同,所以我們抽象出一個集合體。就類似 阿里的服務器機房 是響應所有訪問阿里服務的請求的主體 具體幹活的是服務器 不是機房

執行單元

執行單元就是執行我們彙編程序的第一站 類似CPU處理程序的接口

比方我們做一個加法運算 彙編可能就寫

mov ax, 0EA04H      
mov bx, 4ae0H     

add ax, bx

在這裏插入圖片描述
注意圖上那個AH AL 那就是16位寄存器AX的高8位和低八位
也就是 我們的加數 都在通用寄存器裏面存着呢
那麼EU 包含的東西 就是我們彙編程序裏面的參數 操作指令等 可謂是與程序最相關的單元

當然 EU只是執行了 解釋程序的功能 也就是把參數放好 指令放好(放到寄存器裏面方便BIU的進一步操作)

BIU

BIU就是接手EU工作的 它調用EU之前修改的寄存器(EU把程序參數存放好了) 然後具體的去找
比如 找指令 找立即數
這個“找”的過程 就是尋址 尋找地址 然後去使用

之後 把運算結果通過 外部總線(就是這條線與接口相連),再通過接口 最終傳到外設上 比如傳遞高電平 燈就亮了

有沒有注意一個好玩的事情:我們所有寄存器都是16位的 那麼 20位的地址 到底怎麼出來的呢?地址加法器扮演一個什麼角色?

我們可以利用兩個16位的寄存器值相加 得到20位
當然不是直接相加 可以移位操作一波
這就是8086尋址的基本套路 後面會細講

所謂的“兩個“寄存器 一個是 段寄存器(segment register),一個是專用寄存器
聽起來有點奇怪 其實就是 存儲器太大了 我們將它分段處理 非常類似我們硬盤的分區
那麼我們找數據就是 先定位分區(我們就用到段寄存器的值),
定位分區後,內部定位,就需要知道具體是多少字節到多少字節,比如000FF - 字節 00FFF是存放電影的,打比方 ,這就是指針寄存器的值了
你可以和 在一棟樓裏面去找你女朋友爲例
整棟樓是存儲器 我們分成10段 也就是10層樓
具體在幾樓 請看段寄存器的值 比方說是5樓
到了5樓 哪個門牌號呢?
請看指針寄存器的值 比方說01
那麼 地址就是 501

後面還會設計到“”的概念 你需要知道 彙編找(定位)數據 都是先定位段 再定位段內的地址
接下來我們會細講 具體有哪些 指針寄存器和段寄存器 分別用在哪些場合

寄存器

相信前面在BIU EU中看到了不少寄存器了
我們將寄存器大致分下類:

  • 通用寄存器 general purpose —— 存儲任何指令的地址和數據的寄存器
    • AX adder 累加寄存器
    • BX base 基址寄存器
    • CX count 計數寄存器
    • DX data 數據寄存器
  • 專用寄存器 —— 與段寄存器合作 完成尋址
    • 指針寄存器
      • IP instruction point 指令指針寄存器
      • SP stack 堆棧指針寄存器
    • 變址寄存器
      • SI source 源變址寄存器
      • DI destination 目標變址寄存器
  • 段寄存器 segment
    • CS code 代碼段寄存器
    • DS data 數據段寄存器
    • ES extra 附加段寄存器
    • SS stack 堆棧段寄存器
  • 標誌寄存器 FLAGS 也就是flag
    • 作用
      • 反映指令執行結果(比如做加法 是否進位 是否溢出等)
      • 控制指令形式
    • 構成
      • 狀態標誌
        • CF carry 進位 標誌位
        • OF overflow 溢出 標誌位
        • ZF zero 結果是否爲零
        • SF sign 符號
        • PF 結果的奇偶性
        • AF auxiliary 輔助進位(不用管)
      • 控制標誌
        • DF direction
        • TF trap

存儲器組織結構 尋址方式

前面稍微提到 是專用寄存器與段寄存器的合作 產生20位地址 才能進行尋址 接下來看錶:

寄存器名稱 舉例 地址名稱 形象描述
段寄存器 CS DS ES SS 基地址 段地址 女朋友住幾樓
專用寄存器 IP SP SI DI 偏移地址 有效地址(EA) 女朋友家門牌號

我們用16位的段地址 指示數據在哪一段 總共有16段
用16位的偏移量 也就是門牌號 指示 數據具體位置相對於每一段的開頭 偏移了多少
比如 門牌號510的偏移量是10,因爲 相對於每層樓的開頭500,差了10戶人家
偏移量也稱爲有效地址(EA)
那麼 具體16位的EA 能夠對應多少戶人家呢?答案是216 B = 64KB
所以 一段(segment)= 64KB 也就是大概64000戶人家

這裏 也把 段地址:有效地址 稱爲邏輯地址 就是一種鍵值對
而真正得到的數據地址 也就是女朋友門牌號 稱爲物理地址
一個物理地址可以對應多個邏輯地址 反過來 一個邏輯地址對應一個物理地址
因爲 邏輯地址 通過 加法 得到物理地址 加法組合無窮 結果唯一

具體操作 我們就會
段地址*16 + 有效地址 = 物理地址
乘16是爲了 將段地址 左移4位
在這裏插入圖片描述
當然 物理地址還可以繼續劃分 畢竟要尋址的內容特別複雜 可能是指令 可能只是個數據 我們大致這麼分類:

  • 取指令尋址 CS+IP
  • 堆棧尋址
    • SS+SP
    • SS+BP
  • 存儲器尋址
    • DS+SI
    • DS+DI

段寄存器

我們看一條指令吧

MOV [0], al;

這個[0]指代的是存儲器(對CPU來說是“存儲器”,其實就是內存)的地址,這條指令是想讓AL寄存器的值傳到偏移地址爲0H(也就是第一個字節)那邊去
問題來了 我們知道偏移地址 那段地址計算機咋知道的呢
他會去DS 數據段寄存器裏面找

類似強盜藏寶約定個地方,到時候去老地方分贓一樣,我們約定數據(在內存的數據)的段地址 一定放在DS裏面 當數據操作指令(讀取或者寫入內存的數據 比如剛剛寫的MOV)執行的時候,就會去DS看看:)

所以 我們想讓AL寄存器的值傳到物理地址爲1000H:0H這個位置該怎麼辦呢?

MOV bx, 1000H;
MOV ds,bx;
MOV [0],al;

爲啥要用bx這個中介呢?多此一舉?

事實上 段寄存器地位很特殊 你看看 很多指令都需要執行的時候看段寄存器的臉色
因此 intel設計的規則就是 不能直接把常數放進段寄存器
你放進通用寄存器就可以

這裏 所謂常數 在彙編的世界叫做立即數

總結 ´◡`

這些是我其他學習的部分 希望能幫到你

  • 想學習數據庫嘛? 不妨從MySQL入手
    MySQL專欄

  • python這麼火 想要深入學習python 玩一下簡單的應用嘛?可以看我專欄 還在持續更新中哦:
    python應用

  • 小孩子才做選擇 大人全都要!對後端感興趣嗎?收下它吧:)
    手把手帶你學後端(服務端)

  • 謝謝大佬支持! 萌新有禮了:)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章