0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

解析CPU究竟是怎么執(zhí)行一條指令的?

FPGA之家 ? 來源:IOT物聯(lián)網(wǎng)小鎮(zhèn) ? 作者:道哥 ? 2021-07-06 10:21 ? 次閱讀

Linux 從頭學(xué)】是什么這兩年多以來,我的本職工作重心一直是在 x86 Linux 系統(tǒng)這一塊,從驅(qū)動到中間層,再到應(yīng)用層的開發(fā)。

隨著內(nèi)容的不斷擴展,越發(fā)覺得之前很多基礎(chǔ)的東西都差不多忘記了

描述Linux 系統(tǒng)中幾個段描述符信息。

數(shù)據(jù)段和代碼段,仔細看一下相關(guān)書籍就知道這些描述符代表什么意思,但是:

為什么這幾個段的 Base 地址都是 0x00000000?

為什么 Limit 都是 0xfffff?

為什么它們的 Type 類型和優(yōu)先級 DPL 又各不相同?

如果沒有對 x86 平臺的一些基礎(chǔ)知識的理解,要啃完這本書真的是挺費力氣的!

更要命的是,隨著 Linux 內(nèi)核代碼的體積不斷膨脹,最新的 5.13 版本壓縮檔已經(jīng)是一百多兆了:

這么一個龐然大物,如何下手才能真正的學(xué)好 Linux 呢?!

即便是從 Linux 0.11 版本開始,其中的很多代碼看起來也是非常費勁的!

Linux 系統(tǒng)中的很多關(guān)于分段、內(nèi)存、寄存器相關(guān)的設(shè)計,都可以在這些書籍中找到基礎(chǔ)支撐。

于是乎,我就有了一個想法:是否可以把這些書籍中,與 Linux 系統(tǒng)相關(guān)的內(nèi)容進行一次重讀和整理,但絕不是簡單的知識搬運。

考慮了一下,大概有下面幾個想法:

先確定最終目標(biāo)的目標(biāo):學(xué)習(xí) Linux 操作系統(tǒng);

這幾本書寫的都是匯編語言,以及比較基礎(chǔ)的底層知識。我們會淡化匯編語言部分,把重點放在與 Linux 操作系統(tǒng)有關(guān)聯(lián)的原理部分;

不會嚴(yán)格按照書中的內(nèi)容、順序來輸出文章,而是把幾本書中內(nèi)容相關(guān)的部分放在一起學(xué)習(xí)、討論;

有些內(nèi)容,可以與 Linux 2.6 版本中的相關(guān)部分進行對比分析,這樣的話在以后學(xué)習(xí) Linux 內(nèi)核部分時,可以找到底層的支撐;

最后,希望我自己能堅持這個系列,也算是給自己的一個梳理吧。

一句話:以基礎(chǔ)知識為主!

作為開篇第一章,本文將會描述執(zhí)行步驟:

現(xiàn)在就開始吧!

古老的 Intel8086 處理器8086 是 Intel 公司的第一款 16 位處理器,誕生于 1978 年,應(yīng)該比各位小伙伴的年齡都大一些。

在 Intel 公司的所有處理器中,它占有很重要的地位,是整個 Intel 32 位架構(gòu)處理器(IA-32)的開山鼻祖。

那么,問題來了,什么叫 16 位的處理器?

有些人會把處理器的位數(shù)與地址總線的位數(shù)搞混在一起!

我們知道,CPU 在訪問內(nèi)存的時候,是通過地址總線來傳送物理地址的。

8086 CPU 有 20 位的地址線,可以傳送 20 位地址。

每一根地址線都表示一個 bit,那么 20 個 bit 可以表示的最大值就是 2 的 20 次方。

也就是說:最大可以定位到 1M 地址的內(nèi)存,這稱作 CPU 的尋址能力。

但是,8086 處理器卻是 16 位的,因為:

運算器一次最多可以處理 16 位的數(shù)據(jù);

寄存器的最大寬度為 16 位;

寄存器和運算器之間的通路為 16 位;

也就是說:在 8086 處理器的內(nèi)部,能夠一次性處理、傳輸、暫時存儲的最大長度是 16 位,因此,我們說它是 16 位結(jié)構(gòu)的 CPU。

主存儲器是什么?計算機的本質(zhì)就是對數(shù)據(jù)的存儲和處理,那么參與計算的數(shù)據(jù)是從哪里來的呢?那就是一個稱作 存儲器(Storage 或 Memory)的物理器件。

從廣義上來說,只要能存儲數(shù)據(jù)的器件都可以稱作存儲器,比如:硬盤、U盤等。

但是,在計算機內(nèi)部,有一種專門與 CPU 相連接,用來存儲正在執(zhí)行的程序和數(shù)據(jù)的存儲器,一般稱作內(nèi)存儲器或者主存儲器,簡稱:內(nèi)存或主存。

內(nèi)存按照字節(jié)來組織,單次訪問的最小單位是 1 個字節(jié),這是最基本的存儲單元。

每一個存儲單元,也就是一個字節(jié),都對應(yīng)著一個地址。

CPU 就通過地址總線來確定:對內(nèi)存中的哪一個存儲單元中的數(shù)據(jù)進行訪問。

第 1 個字節(jié)的地址是 0000H,第 2 個字節(jié)的地址是 0001H,后面以此類推。

圖中的這個內(nèi)存,最大存儲單元的地址是 FFFFH,換算成十進制就是 65535,因此這個內(nèi)存的容量是 65536 字節(jié),也就是 64 KB。

這里有一個原子操作的問題可以考慮一下。

在 Linux 內(nèi)核代碼中,很多地方使用了原子操作,比如:互斥鎖的實現(xiàn)代碼。

為什么原子操作需要對變量的類型限制為 int 型呢?這就涉及到對內(nèi)存的讀寫操作了。

盡管內(nèi)存的最小組成單位是字節(jié),但是,經(jīng)過精心的設(shè)計和安排,不同位數(shù)的 CPU,能夠按照字節(jié)、字、雙字進行訪問。

換句話說,僅通過單次訪問,16 位處理器就能處理 16 位的二進制數(shù),32 位處理器就能處理 32 位的二進制數(shù)。

寄存器是什么?在 CPU 內(nèi)部,一些都是代表 0 或 1 的電信號,這些二進制數(shù)字的一組電信號出現(xiàn)在處理器內(nèi)部線路上,它們是一排高低電平的組合,代表著二進制數(shù)中的每一位。

在處理器內(nèi)部,必須用一個稱為寄存器的電路把這些數(shù)據(jù)鎖存起來。

因此,寄存器本質(zhì)上也屬于存儲器的一種。只不過它們位于處理器的內(nèi)部,CPU 訪問寄存器比訪問內(nèi)存的速度更快。

處理器總是很忙的,在它操作的過程中,所有數(shù)據(jù)在寄存器里面只能是臨時存在一小會,然后再被送往別處,這就是為什么它被叫做“寄存器”。

8086 中的寄存器都是 16 位的,可以存放 2 個字節(jié),或者說 1 個字。高字節(jié)在前(bit8 ~ bit15),低字節(jié)在后(bit0 ~ bit7)。

剛才說了,這些寄存器都是 16 位的。由于需要與以前更古老的處理器兼容,其中的 4 個寄存器:AX、BX、CX、DX 還可以當(dāng)成 2 個 8 位的寄存器來使用。

比如:AX 代表一個 16 位的寄存器,AH、AL 分別代表一個 8 位的寄存器。

mov AX, 5D 表示把 005D 送入 AX 寄存器(16 位)

mov AL, 5D 表示把 5D 送入 AL 寄存器(8 位)

三個總線當(dāng)我們啟動一個應(yīng)用程序的時候,這個程序的代碼和數(shù)據(jù)都被加載到物理內(nèi)存中。

CPU 無論是讀取指令,還是操作數(shù)據(jù),都需要與內(nèi)存進行信息的交互:

確定存儲單元的地址(地址信息);

器件的選擇,讀或?qū)懙拿睿刂菩畔ⅲ?

讀或?qū)懙臄?shù)據(jù)(數(shù)據(jù)信息);

在計算機中,有專門連接 CPU 和其他芯片的數(shù)據(jù),稱為總線。

從邏輯上來分類,包括下面 3 種總線:

地址總線:用來確定存儲單元的地址;

控制總線: CPU 對外部期間進行控制;

數(shù)據(jù)總線: CPU 與內(nèi)存或其他器件之間傳送數(shù)據(jù);

8086 有 20 根地址線,稱作地址總線的寬度,它可以尋址 2 的 20 次方個內(nèi)存單元。

同樣的道理,8086 數(shù)據(jù)總線的寬度是 16,也就是一次性可以傳送 16 bit 的數(shù)據(jù)。

控制總線決定了 CPU 可以對外進行多少種控制,決定了 CPU 對外部器件的控制能力。

CPU 如何對內(nèi)存進行尋址?在 Linux 2.6 內(nèi)核代碼中,編譯器產(chǎn)生的地址叫做虛擬地址(也稱作:邏輯地址),這個邏輯地址經(jīng)過段轉(zhuǎn)換之后,變成線性地址,線性地址再經(jīng)過分頁轉(zhuǎn)換,就得到最終物理內(nèi)存上的物理地址。

還記得文章開頭的那張段描述符的表格嗎?

其中的代碼段和數(shù)據(jù)段描述符的起始地址都是 0x00000000,也就是說: 在數(shù)值上虛擬地址和轉(zhuǎn)換后的線性地址是相等的(稍后就會明白為什么是這樣)。

我們再來看看一下 8086 中更簡單的地址轉(zhuǎn)換。

剛才說到,內(nèi)存是一個線性的存儲器件,CPU 依賴地址來定位每一個存儲單元。

對于 8086 CPU 來說,它有 20 根地址線,可以傳送 20 位地址,達到 1MB 的尋址能力。

但是 8086 又是 16 位的結(jié)構(gòu),在內(nèi)部一次性處理、傳輸、暫時存儲的地址只有 16 位。

從內(nèi)部結(jié)構(gòu)來看,如果將地址從內(nèi)部簡單的發(fā)出到地址總線上,只能送出 16 位的地址,這樣的話,尋址能力只有 64KB。

那么應(yīng)該怎么才能充分利用 20 根地址線呢?

8086 CPU 采用: 在內(nèi)部使用兩個 16 位地址合成的方法,來形成一個 20 位的物理地址。

第一個 16 位的地址稱為段地址,第二個 16 位的地址稱為偏移地址。

地址加法器采用下面的這個公式,來“合成”得到一個 20 位的物理地址:

物理地址 = 段地址 x 16 + 偏移地址

例如:我們編寫的程序,在加載到內(nèi)存中之后,放在一個內(nèi)存空間中。

CPU 在執(zhí)行這些指令的時候,把 CS 寄存器當(dāng)做段寄存器,把 IP 寄存器當(dāng)做偏移寄存器,然后計算 CS x 16 + IP 的值,就得到了指令的物理地址。

從以上的描述中可以看出:8086 CPU 似乎是因為寄存器無法直接輸出 20 位的物理地址,不得已才使用這樣的地址合成方式。

其實更本質(zhì)的原因是:8086 CPU 就是想通過 基地址 + 偏移量 的方式來對內(nèi)存進行尋址(這里的基地址,就是段地址左移 4 位)。

也就是說,即使 CPU 有能力直接輸出一個 20 位的地址,它仍然可能會采用 基地址 + 偏移量的方式來進行內(nèi)存尋址。

想一下:我們在 Linux 系統(tǒng)中編譯一個庫文件的時候,一般都會在編譯選項中添加 -fPIC 選項,表示編譯出來的動態(tài)庫是地址無關(guān)的,在被加載到內(nèi)存時需要被重定位。

而基地址+偏移量的尋址模式,就為重定位提供了底層支撐。

我們是如何控制 CPU 的?CPU 其實是一個很純粹、很呆板的一個東西,它唯一做的事情就是:到 CS:IP 這兩個寄存器指定的內(nèi)存單元中取出一條指令,然后執(zhí)行這條指令。

當(dāng)然了,還需要預(yù)先定義一套指令集,在內(nèi)存中的指令區(qū)中,存儲的都必須是合法的指令,否則 CPU 就不認識了。

每一條指令都是用某些特定的數(shù)(指令碼)來指示 CPU 進行特定的操作。

CPU 認識這些指令,一看到這些指令碼,CPU 就知道這個指令碼后面還有幾個字節(jié)的操作數(shù)、需要進行什么樣的操作。

例如:指令碼 F4H 表示讓處理器停機,當(dāng) CPU 執(zhí)行這條指令的時候,就停止工作。

(其實這里說 CPU 已經(jīng)有點不準(zhǔn)確了,因為 CPU 是囊括了很多器件的一個整體,也許這里說 CPU 中的執(zhí)行單元會更準(zhǔn)確些。)

另外有一點可以提前說一下:內(nèi)存中的一切都是數(shù)據(jù),至于把其中的哪一部分數(shù)據(jù)當(dāng)做指令來執(zhí)行,哪一部分數(shù)據(jù)當(dāng)做被指令操作的“變量”,這完全是由操作系統(tǒng)的設(shè)計者來規(guī)劃的。

在 8086 處理器的層面來說,只要是 CS:IP “指向”的內(nèi)存區(qū)域,都被當(dāng)做指令來執(zhí)行。

從以上描述可以看出:在 CPU 中,程序員能夠用指令讀寫的器件只有寄存器,我們可以通過改變寄存器中的內(nèi)容,來實現(xiàn)對 CPU 的控制。

更直白的說就是:我們可以通過改變 CS、IP 寄存器中的內(nèi)容,來控制 CPU 執(zhí)行目標(biāo)指令。

作為一名合格的嵌入式開發(fā)者,大家估計都配置過一些單片機里的寄存器,以達到一些功能定義、端口復(fù)用的目的,其實這些操作,都可以看做是我們對 CPU 的控制。

如果把 CPU 比作木偶,那么 寄存器就是控制木偶的繩索。

我們再把 CPU 與 工控領(lǐng)域的 PLC 編程進行類比一下。

我們在拿到一個新的 PLC 設(shè)備之后,其中只有一個運行時(runtime),這個運行時執(zhí)行的本職工作就是:

掃描所有的輸入端口,鎖存在輸入映象區(qū);

執(zhí)行一個運算、控制邏輯,得到一些列輸出信號,鎖存到輸出映象區(qū);

把輸出映象區(qū)的信號,刷新到輸出端口;

在一個全新的 PLC 中,其中第 2 個步驟中需要的運算、控制邏輯可能就不存在。

因此,單單一個 runtime,PLC 是無法完成一件有意義的工作的。

為了讓 PLC 完成一個具體的控制目標(biāo),我們還需要利用 PLC 廠家提供的上位機編程軟件,開發(fā)一個運算、控制邏輯程序,編程語言一般都是梯形圖居多。

當(dāng)這個程序被下載到 PLC 中之后,它就可以控制運行時來做一些有意義的工作了。

我們可以簡單的認為:梯形圖就是用來控制 PLC 的運行時。

對于 CPU 來說,想讓它執(zhí)行某個內(nèi)存單元的指令,只要修改寄存器 CS 和 IP 即可。

換句話說:只要對一個程序的內(nèi)存布局足夠的清楚,可以把 CPU 玩弄于股掌之間,讓它執(zhí)行哪里的代碼都可以。

CPU 執(zhí)行指令流程現(xiàn)在我們已經(jīng)明白了地址轉(zhuǎn)換、內(nèi)存的尋址,距離 CPU 執(zhí)行一條指令需要的最小單元還剩下:指令緩沖區(qū)和控制電路

簡單來說:指令緩沖區(qū)用來緩存從內(nèi)存中讀取的指令,控制電路用來協(xié)調(diào)各種器件對總線等資源的使用。

對于下面這張圖來說,它一共有 4 條指令:

以第一條指令來舉例,它一共經(jīng)過 5 個步驟:

把 CS:IP 內(nèi)容送入地址加法器,計算得到 20 位的物理地址 20000H;

控制電路把 20 位的地址,送入到地址總線;

內(nèi)存中 20000H 單元處的指令 B8 23 01,經(jīng)過數(shù)據(jù)總線被送到指令緩沖區(qū);

指令偏移寄存器 IP 的值要加 3,指向下一條等待被執(zhí)行的偏移地址(因為指令碼 B8 代表當(dāng)前指令的長度是 3 個字節(jié));

執(zhí)行指令緩沖區(qū)中的指令: 把數(shù)值 0123H 送入寄存器 AX 中;

以上就是一條指令的執(zhí)行最基本步驟,當(dāng)然,現(xiàn)代處理器的指令執(zhí)行流程,比這里的要復(fù)雜的多得多。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5362

    瀏覽量

    120886
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    10898

    瀏覽量

    212558
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4816

    瀏覽量

    68863
  • LINUX內(nèi)核
    +關(guān)注

    關(guān)注

    1

    文章

    316

    瀏覽量

    21695

原文標(biāo)題:Linux 從頭學(xué) 01:CPU 是如何執(zhí)行一條指令的?

文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    PCM1861 INT腳究竟是輸出還是輸入?

    這個芯片activce或是idle. 是否有人解釋下,INT腳究竟是輸出還是輸入。我希望是輸出,我需要讀取到是否有analog audio輸入的信息。 或者,輸入輸出與否還要靠其他什么地方設(shè)置? 盼望有人回復(fù)解答,不勝感激!
    發(fā)表于 10-29 07:29

    超高頻讀寫器究竟是什么,能做什么?文讀懂!

    在物聯(lián)網(wǎng)技術(shù)日新月異的今天,超高頻讀寫器作為射頻識別(RFID)技術(shù)的重要組成部分,正逐漸滲透到我們生活的各個領(lǐng)域。那么,超高頻讀寫器究竟是什么?它又能做些什么呢?本文將帶您一探究竟。、超高頻
    的頭像 發(fā)表于 10-23 14:41 ?263次閱讀
    超高頻讀寫器<b class='flag-5'>究竟是</b>什么,能做什么?<b class='flag-5'>一</b>文讀懂!

    揭秘貼片功率電感發(fā)燙究竟是不是燒壞了

    電子發(fā)燒友網(wǎng)站提供《揭秘貼片功率電感發(fā)燙究竟是不是燒壞了.docx》資料免費下載
    發(fā)表于 09-30 14:44 ?0次下載

    CPU時鐘周期、機器周期和指令周期的關(guān)系

    CPU時鐘周期、機器周期和指令周期是計算機體系結(jié)構(gòu)中三個緊密相連且至關(guān)重要的概念,它們共同構(gòu)成了CPU執(zhí)行指令和處理數(shù)據(jù)的基本時間框架。以下
    的頭像 發(fā)表于 09-26 15:38 ?3556次閱讀

    電感器線徑究竟是粗好還是細好

    電子發(fā)燒友網(wǎng)站提供《電感器線徑究竟是粗好還是細好.docx》資料免費下載
    發(fā)表于 09-20 11:25 ?0次下載

    tas5756m使用GPIO口加內(nèi)部PLL產(chǎn)生MCLK的方法究竟是怎么樣的?

    tas5756m使用GPIO口加內(nèi)部PLL產(chǎn)生MCLK的方法究竟是怎么樣的?
    發(fā)表于 08-19 06:06

    如何在CANtest上通過報文發(fā)送實現(xiàn)CCP指令的發(fā)送

    Err33--access denied,有兄弟知道如何解決嗎?我確保我設(shè)置的MTA地址是正確的。 此外,我還發(fā)送了‘Set Status’指令將狀態(tài)設(shè)置為0x81,但是通過‘Get Status’返回的狀態(tài)為0x00,這個我也不是很清楚究竟是為什么。
    發(fā)表于 08-13 10:46

    如何給CyBootProgrammer.Img這個固件添加一條控制led狀態(tài)的指令

    我想對CyBootProgrammer.Img這個固件添加一條控制led狀態(tài)的指令,我是小白,我想知道怎么寫配置能控制引腳的高低電平
    發(fā)表于 05-27 08:28

    請問cH340G的TX引腳電平究竟是3v還是5v?

    用CD34G來實現(xiàn)usb轉(zhuǎn)串口的時候,直接用usb口的5v作為電源電壓,它的tx引腳輸出的高電平究竟是5v還是3v,我實測是3v,但網(wǎng)上有的人是5v,想進步得到大家的確認。
    發(fā)表于 05-14 08:15

    STM8L執(zhí)行一條語句大概需要幾個時鐘周期?

    STM8L執(zhí)行一條語句大概需要幾個時鐘周期
    發(fā)表于 05-06 06:16

    工業(yè)物聯(lián)網(wǎng)究竟是什么呢?它又有哪些作用呢?

    隨著科技的快速發(fā)展,物聯(lián)網(wǎng)技術(shù)已經(jīng)逐漸滲透到我們生活的各個角落,而 工業(yè)物聯(lián)網(wǎng)(IIoT) 更是引領(lǐng)著工業(yè)領(lǐng)域的數(shù)字化轉(zhuǎn)型。那么,工業(yè)物聯(lián)網(wǎng)究竟是什么呢?它又有哪些作用呢?本文將對此進行深度解析
    的頭像 發(fā)表于 04-22 15:26 ?433次閱讀

    stm32f103r8t6外部8M晶振,倍頻72M,執(zhí)行一條指令需要多少時間?

    stm32f103r8t6,外部8M晶振,倍頻72M. 執(zhí)行一條指令需要多少時間?? int main(void) { 初始化程序。。。。 初始化程序。。。。 while(1) { GPIOA->ODR^=GPIO_Pi
    發(fā)表于 04-22 07:16

    STM32擦除后數(shù)據(jù)究竟是0x00還是0xff ?

    STM32擦除后數(shù)據(jù)究竟是0x00還是0xff ,百度查了許多發(fā)現(xiàn)大多數(shù)都是0xff的多,都說SD卡(TF)儲存介質(zhì)是Flash 所以擦除后為0xff,但是我遇到了讀出來的數(shù)據(jù)是0x00的情況,為什么呢
    發(fā)表于 04-18 07:59

    MOSFET的柵源振蕩究竟是怎么來的?柵源振蕩的危害什么?如何抑制

    MOSFET的柵源振蕩究竟是怎么來的呢?柵源振蕩的危害什么?如何抑制或緩解柵源振蕩的現(xiàn)象呢? MOSFET(金屬-氧化物-半導(dǎo)體場效應(yīng)晶體管)的柵源振蕩是指在工作過程中,出現(xiàn)的柵極與源極之間產(chǎn)生
    的頭像 發(fā)表于 03-27 15:33 ?1807次閱讀

    吸塵器究竟是如何替你“吃灰”的【其利天下技術(shù)】

    如今,吸塵器已成為大多數(shù)人居家必備的小家電產(chǎn)品,那么說起吸塵器,你對吸塵器有了解多少呢?不知道大家知不知道它的原理是什么?今天我們就來說說吸塵器究竟是如何替你“吃灰”的。
    的頭像 發(fā)表于 03-07 21:17 ?920次閱讀
    吸塵器<b class='flag-5'>究竟是</b>如何替你“吃灰”的【其利天下技術(shù)】