www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 程序喵大人
[導(dǎo)讀]本文介紹了關(guān)于寄存器的相關(guān)內(nèi)容。

點(diǎn)擊藍(lán)色“程序員cxuan?”關(guān)注我喲

加個(gè)“星標(biāo)”,歡迎來(lái)撩


這是程序員cxuan的第 41期原創(chuàng)分享


下面我們就來(lái)介紹一下關(guān)于寄存器的相關(guān)內(nèi)容。我們知道,寄存器是 CPU 內(nèi)部的構(gòu)造,它主要用于信息的存儲(chǔ)。除此之外,CPU 內(nèi)部還有運(yùn)算器,負(fù)責(zé)處理數(shù)據(jù);控制器控制其他組件;外部總線連接 CPU 和各種部件,進(jìn)行數(shù)據(jù)傳輸;內(nèi)部總線負(fù)責(zé) CPU 內(nèi)部各種組件的數(shù)據(jù)處理。

那么對(duì)于我們所了解的匯編語(yǔ)言來(lái)說(shuō),我們的主要關(guān)注點(diǎn)就是 寄存器

為什么會(huì)出現(xiàn)寄存器?因?yàn)槲覀冎溃绦蛟趦?nèi)存中裝載,由 CPU 來(lái)運(yùn)行,CPU 的主要職責(zé)就是用來(lái)處理數(shù)據(jù)。那么這個(gè)過(guò)程勢(shì)必涉及到從存儲(chǔ)器中讀取和寫入數(shù)據(jù),因?yàn)樗婕巴ㄟ^(guò)控制總線發(fā)送數(shù)據(jù)請(qǐng)求并進(jìn)入存儲(chǔ)器存儲(chǔ)單元,通過(guò)同一通道獲取數(shù)據(jù),這個(gè)過(guò)程非常的繁瑣并且會(huì)涉及到大量的內(nèi)存占用,而且有一些常用的內(nèi)存頁(yè)存在,其實(shí)是沒(méi)有必要的,因此出現(xiàn)了寄存器,存儲(chǔ)在 CPU 內(nèi)部。

認(rèn)識(shí)寄存器

寄存器的官方叫法有很多,Wiki 上面的叫法是 Processing Register, 也可以稱為 CPU Register,計(jì)算機(jī)中經(jīng)常有一個(gè)東西多種叫法的情況,反正你知道都說(shuō)的是寄存器就可以了。

認(rèn)識(shí)寄存器之前,我們首先先來(lái)看一下 CPU 內(nèi)部的構(gòu)造。

CPU 從邏輯上可以分為 3 個(gè)模塊,分別是控制單元、運(yùn)算單元和存儲(chǔ)單元,這三部分由 CPU 內(nèi)部總線連接起來(lái)。

幾乎所有的馮·諾伊曼型計(jì)算機(jī)的 CPU,其工作都可以分為5個(gè)階段:「取指令、指令譯碼、執(zhí)行指令、訪存取數(shù)、結(jié)果寫回」

  • 取指令階段是將內(nèi)存中的指令讀取到 CPU 中寄存器的過(guò)程,程序寄存器用于存儲(chǔ)下一條指令所在的地址
  • 指令譯碼階段,在取指令完成后,立馬進(jìn)入指令譯碼階段,在指令譯碼階段,指令譯碼器按照預(yù)定的指令格式,對(duì)取回的指令進(jìn)行拆分和解釋,識(shí)別區(qū)分出不同的指令類別以及各種獲取操作數(shù)的方法。
  • 執(zhí)行指令階段,譯碼完成后,就需要執(zhí)行這一條指令了,此階段的任務(wù)是完成指令所規(guī)定的各種操作,具體實(shí)現(xiàn)指令的功能。
  • 訪問(wèn)取數(shù)階段,根據(jù)指令的需要,有可能需要從內(nèi)存中提取數(shù)據(jù),此階段的任務(wù)是:根據(jù)指令地址碼,得到操作數(shù)在主存中的地址,并從主存中讀取該操作數(shù)用于運(yùn)算。
  • 結(jié)果寫回階段,作為最后一個(gè)階段,結(jié)果寫回(Write Back,WB)階段把執(zhí)行指令階段的運(yùn)行結(jié)果數(shù)據(jù)寫回到 CPU 的內(nèi)部寄存器中,以便被后續(xù)的指令快速地存取;

計(jì)算機(jī)架構(gòu)中的寄存器

寄存器是一塊速度非常快的計(jì)算機(jī)內(nèi)存,下面是現(xiàn)代計(jì)算機(jī)中具有存儲(chǔ)功能的部件比對(duì),可以看到,寄存器的速度是最快的,同時(shí)也是造價(jià)最高昂的。

我們以 intel 8086 處理器為例來(lái)進(jìn)行探討,8086 處理器是 x86 架構(gòu)的前身。在 8086 后面又衍生出來(lái)了 8088 。

在 8086 CPU 中,地址總線達(dá)到 20 根,因此最大尋址能力是 2^20 次冪也就是 1MB 的尋址能力,8088 也是如此。

在 8086 架構(gòu)中,所有的內(nèi)部寄存器、內(nèi)部以及外部總線都是 16 位寬,可以存儲(chǔ)兩個(gè)字節(jié),因?yàn)槭峭耆?16 位微處理器。8086 處理器有 14 個(gè)寄存器,每個(gè)寄存器都有一個(gè)特有的名稱,即

「AX,BX,CX,DX,SP,BP,SI,DI,IP,F(xiàn)LAG,CS,DS,SS,ES」

這 14 個(gè)寄存器有可能進(jìn)行具體的劃分,按照功能可以分為三種

  • 通用寄存器
  • 控制寄存器
  • 段寄存器

下面我們分別介紹一下這幾種寄存器

通用寄存器

通用寄存器主要有四種 ,即 「AX、BX、CX、DX」 同樣的,這四個(gè)寄存器也是 16 位的,能存放兩個(gè)字節(jié)。AX、BX、CX、DX 這四個(gè)寄存器一般用來(lái)存放數(shù)據(jù),也被稱為 數(shù)據(jù)寄存器。它們的結(jié)構(gòu)如下

8086 CPU 的上一代寄存器是 8080 ,它是一類 8 位的 CPU,為了保證兼容性,8086 在 8080 上做了很小的修改,8086 中的通用寄存器 AX、BX、CX、DX 都可以獨(dú)立使用兩個(gè) 8 位寄存器來(lái)使用。

在細(xì)節(jié)方面,AX、BX、CX、DX 可以再向下進(jìn)行劃分

  • AX(Accumulator Register) :累加寄存器,它主要用于輸入/輸出和大規(guī)模的指令運(yùn)算。
  • BX(Base Register):基址寄存器,用來(lái)存儲(chǔ)基礎(chǔ)訪問(wèn)地址
  • CX(Count Register):計(jì)數(shù)寄存器,CX 寄存器在迭代的操作中會(huì)循環(huán)計(jì)數(shù)
  • DX(data Register):數(shù)據(jù)寄存器,它也用于輸入/輸出操作。它還與 AX 寄存器以及 DX 一起使用,用于涉及大數(shù)值的乘法和除法運(yùn)算。

這四種寄存器可以分為上半部分和下半部分,用作八個(gè) 8 位數(shù)據(jù)寄存器

  • 「AX 寄存器可以分為兩個(gè)獨(dú)立的 8 位的 AH 和 AL 寄存器;」
  • 「BX 寄存器可以分為兩個(gè)獨(dú)立的 8 位的 BH 和 BL 寄存器;」
  • 「CX 寄存器可以分為兩個(gè)獨(dú)立的 8 位的 CH 和 CL 寄存器;」
  • 「DX 寄存器可以分為兩個(gè)獨(dú)立的 8 位的 DH 和 DL 寄存器;」

除了上面 AX、BX、CX、DX 寄存器以外,其他寄存器均不可以分為兩個(gè)獨(dú)立的 8 位寄存器

如下圖所示。

合起來(lái)就是

AX 的低位(0 - 7)位構(gòu)成了 AL 寄存器,高 8 位(8 - 15)位構(gòu)成了 AH 寄存器。AH 和 AL 寄存器是可以使用的 8 位寄存器,其他同理。

在認(rèn)識(shí)了寄存器之后,我們通過(guò)一個(gè)示例來(lái)看一下數(shù)據(jù)的具體存儲(chǔ)方式。

比如數(shù)據(jù) 19 ,它在 16 位存儲(chǔ)器中所存儲(chǔ)的表示如下

寄存器的存儲(chǔ)方式是先存儲(chǔ)低位,如果低位滿足不了就存儲(chǔ)高位,如果低位能夠滿足,高位用 0 補(bǔ)全,在其他低位能滿足的情況下,其余位也用 0 補(bǔ)全。

8086 CPU 可以一次存儲(chǔ)兩種類型的數(shù)據(jù)

  • 字節(jié)(byte):一個(gè)字節(jié)由 8 bit 組成,這是一種恒定不變的存儲(chǔ)方式
  • 字(word):字是由指令集或處理器硬件作為單元處理的固定大小的數(shù)據(jù),對(duì)于 intel 來(lái)說(shuō),一個(gè)字長(zhǎng)就是兩個(gè)字節(jié),字是計(jì)算機(jī)一個(gè)非常重要的特征,針對(duì)不同的指令集架構(gòu)來(lái)說(shuō),計(jì)算機(jī)一次處理的數(shù)據(jù)也是不同的。也就是說(shuō),針對(duì)不同指令集的機(jī)器,一次能處理不用的字長(zhǎng),有字、雙字(32位)、四字(64位)等。

AX 寄存器

我們上面探討過(guò),AX 的另外一個(gè)名字叫做累加寄存器或者簡(jiǎn)稱為累加器,其可以分為 2 個(gè)獨(dú)立的 8 位寄存器 AH 和 AL;在編寫匯編程序中,AX 寄存器可以說(shuō)是使用頻率最高的寄存器。

下面是幾段匯編代碼

mov ax,20   /* 將 20 送入寄存器 AX*/
mov ah,80 /* 將 80 送入寄存器 AH*/
add ax,10 /* 將寄存器 AX 中的數(shù)值加上 8 */

這里注意下:上面代碼中出現(xiàn)的是 ax、ah ,而注釋中確是 AX、AH ,其實(shí)含義是一樣的,不區(qū)分大小寫。

AX 相比于其他通用寄存器來(lái)說(shuō),有一點(diǎn)比較特殊,AX 具有一種特殊功能的使用,那就是使用 DIV 和 MUL 指令式使用。

DIV 是 8086 CPU 中的除法指令。

MUL 是 8086 CPU 中的乘法指令。

BX 寄存器

BX 被稱為數(shù)據(jù)寄存器,即表明其能夠暫存一般數(shù)據(jù)。同樣為了適應(yīng)以前的 8 位 CPU ,而可以將 BX 當(dāng)做兩個(gè)獨(dú)立的 8 位寄存器使用,即有 BH 和 BL。BX 除了具有暫存數(shù)據(jù)的功能外,還用于 尋址,即尋找物理內(nèi)存地址。BX 寄存器中存放的數(shù)據(jù)一般是用來(lái)作為偏移地址 使用的,因?yàn)槠频刂樊?dāng)然是在基址地址上的偏移了。偏移地址是在段寄存器中存儲(chǔ)的,關(guān)于段寄存器的介紹,我們后面再說(shuō)。

CX 寄存器

CX 也是數(shù)據(jù)寄存器,能夠暫存一般性數(shù)據(jù)。同樣為了適應(yīng)以前的 8 位 CPU ,而可以將 CX 當(dāng)做兩個(gè)獨(dú)立的 8 位寄存器使用,即有 CH 和 CL。除此之外,CX 也是有其專門的用途的,CX 中的 C 被翻譯為 Counting 也就是計(jì)數(shù)器的功能。當(dāng)在匯編指令中使用循環(huán) LOOP 指令時(shí),可以通過(guò) CX 來(lái)指定需要循環(huán)的次數(shù),每次執(zhí)行循環(huán) LOOP 時(shí)候,CPU 會(huì)做兩件事

  • 一件事是計(jì)數(shù)器自動(dòng)減 1

  • 還有一件就是判斷 CX 中的值,如果 CX 中的值為 0 則會(huì)跳出循環(huán),而繼續(xù)執(zhí)行循環(huán)下面的指令,

    當(dāng)然如果 CX 中的值不為 0 ,則會(huì)繼續(xù)執(zhí)行循環(huán)中所指定的指令 。

DX 寄存器

DX 也是數(shù)據(jù)寄存器,能夠暫存一般性數(shù)據(jù)。同樣為了適應(yīng)以前的 8 位 CPU ,DX 的用途其實(shí)在前面介紹 AX 寄存器時(shí)便已經(jīng)有所介紹了,那就是支持 MUL 和 DIV 指令。同時(shí)也支持?jǐn)?shù)值溢出等。

段寄存器

CPU 包含四個(gè)段寄存器,用作程序指令,數(shù)據(jù)或棧的基礎(chǔ)位置。實(shí)際上,對(duì) IBM PC 上所有內(nèi)存的引用都包含一個(gè)段寄存器作為基本位置。

段寄存器主要包含

  • CS(Code Segment) :代碼寄存器,程序代碼的基礎(chǔ)位置
  • DS(Data Segment):數(shù)據(jù)寄存器,變量的基本位置
  • SS(Stack Segment):棧寄存器,棧的基礎(chǔ)位置
  • ES(Extra Segment):其他寄存器,內(nèi)存中變量的其他基本位置。

索引寄存器

索引寄存器主要包含段地址的偏移量,索引寄存器主要分為

  • BP(Base Pointer):基礎(chǔ)指針,它是棧寄存器上的偏移量,用來(lái)定位棧上變量
  • SP(Stack Pointer): 棧指針,它是棧寄存器上的偏移量,用來(lái)定位棧頂
  • SI(Source Index): 變址寄存器,用來(lái)拷貝源字符串
  • DI(Destination Index): 目標(biāo)變址寄存器,用來(lái)復(fù)制到目標(biāo)字符串

狀態(tài)和控制寄存器

就剩下兩種寄存器還沒(méi)聊了,這兩種寄存器是指令指針寄存器和標(biāo)志寄存器:

  • IP(Instruction Pointer):指令指針寄存器,它是從 Code Segment 代碼寄存器處的偏移來(lái)存儲(chǔ)執(zhí)行的下一條指令
  • FLAG : Flag 寄存器用于存儲(chǔ)當(dāng)前進(jìn)程的狀態(tài),這些狀態(tài)有
    • 位置 (Direction):用于數(shù)據(jù)塊的傳輸方向,是向上傳輸還是向下傳輸
    • 中斷標(biāo)志位 (Interrupt) :1 - 允許;0 - 禁止
    • 陷入位 (Trap) :確定每條指令執(zhí)行完成后,CPU 是否應(yīng)該停止。1 - 開(kāi)啟,0 - 關(guān)閉
    • 進(jìn)位 (Carry) : 設(shè)置最后一個(gè)無(wú)符號(hào)算術(shù)運(yùn)算是否帶有進(jìn)位
    • 溢出 (Overflow) : 設(shè)置最后一個(gè)有符號(hào)運(yùn)算是否溢出
    • 符號(hào) (Sign) : 如果最后一次算術(shù)運(yùn)算為負(fù),則設(shè)置 ?1 =負(fù),0 =正
    • 零位 (Zero) : 如果最后一次算術(shù)運(yùn)算結(jié)果為零,1 = 零
    • 輔助進(jìn)位 (Aux Carry) :用于第三位到第四位的進(jìn)位
    • 奇偶校驗(yàn) (Parity) : 用于奇偶校驗(yàn)

物理地址

我們大家都知道, CPU 訪問(wèn)內(nèi)存時(shí),需要知道訪問(wèn)內(nèi)存的具體地址,內(nèi)存單元是內(nèi)存的基本單位,每一個(gè)內(nèi)存單元在內(nèi)存中都有唯一的地址,這個(gè)地址即是 物理地址。而 CPU 和內(nèi)存之間的交互有三條總線,即數(shù)據(jù)總線、控制總線和地址總線。

CPU 通過(guò)地址總線將物理地址送入存儲(chǔ)器,那么 CPU 是如何形成的物理地址呢?這將是我們接下來(lái)的討論重點(diǎn)。

現(xiàn)在,我們先來(lái)討論一下和 8086 CPU 有關(guān)的結(jié)構(gòu)問(wèn)題。

cxuan 和你聊了這么久,你應(yīng)該知道 8086 CPU 是 16 位的 CPU 了,那么,什么是 16 位的 CPU 呢?

你可能大致聽(tīng)過(guò)這個(gè)回答,16 位 CPU 指的是 CPU 一次能處理的數(shù)據(jù)是 16 位的,能回答這個(gè)問(wèn)題代表你的底層還不錯(cuò),但是不夠全面,其實(shí),16 位的 CPU 指的是

  • CPU 內(nèi)部的運(yùn)算器一次最多能處理 16 位的數(shù)據(jù)

運(yùn)算器其實(shí)就是 ALU,運(yùn)算控制單元,它是 CPU 內(nèi)部的三大核心器件之一,主要負(fù)責(zé)數(shù)據(jù)的運(yùn)算。

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

這個(gè)寄存器的最大寬度值就是通用寄存器能處理的二進(jìn)制數(shù)的最大位數(shù)

  • 寄存器和運(yùn)算器之間的通路為 16 位

這個(gè)指的是寄存器和運(yùn)算器之間的總線,一次能傳輸 16 位的數(shù)據(jù)

好了,現(xiàn)在你應(yīng)該知道為什么叫做 16 位 CPU 了吧。

在你知道上面這個(gè)問(wèn)題的答案之后,我們下面就來(lái)聊一聊如何計(jì)算物理地址。

8086 CPU 有 20 位地址總線,每一條總線都可以傳輸一位的地址,所以 8086 CPU 可以傳送 20 位地址,也就是說(shuō),8086 CPU 可以達(dá)到 2^20 次冪的尋址能力,也就是 1MB。8086 CPU 又是 16 位的結(jié)構(gòu),從 8086 CPU 的結(jié)構(gòu)看,它只能傳輸 16 位的地址,也就是 2^16 次冪也就是 64 KB,那么它如何達(dá)到 1MB 的尋址能力呢?

原來(lái),8086 CPU 的內(nèi)部采用兩個(gè) 16 位地址合成的方式來(lái)傳輸一個(gè) 20 位的物理地址,如下圖所示

敘述一下上圖描述的過(guò)程

CPU 相關(guān)組件提供兩個(gè)地址:段地址和偏移地址,這兩個(gè)地址都是 16 位的,他們經(jīng)由地址加法器變?yōu)?20 位的物理地址,這個(gè)地址即是輸入輸出控制電路傳遞給內(nèi)存的物理地址,由此完成物理地址的轉(zhuǎn)換。

地址加法器采用 「物理地址 = 段地址 * 16 + 偏移地址」 的方法用段地址和偏移地址合成物理地址。

下面是地址加法器的工作流程

其實(shí)段地址 * 16 ,就是左移 4 位。在上面的敘述中,物理地址 = 段地址 * 16 + 偏移地址,其實(shí)就是「基礎(chǔ)地址 + 偏移地址 = 物理地址」 尋址模式的一種具體實(shí)現(xiàn)方案?;A(chǔ)地址其實(shí)就等于段地址 * 16。

你可能不太清楚 的概念,下面我們就來(lái)探討一下。

什么是段

段這個(gè)概念經(jīng)常出現(xiàn)在操作系統(tǒng)中,比如在內(nèi)存管理中,操作系統(tǒng)會(huì)把不同的數(shù)據(jù)分成 來(lái)存儲(chǔ),比如 「代碼段、數(shù)據(jù)段、bss 段、rodata 段」 等。

但是這些的劃分并不是內(nèi)存干的,cxuan 告訴你是誰(shuí)干的,這其實(shí)是幕后 Boss CPU 搞的,內(nèi)存當(dāng)作了聲討的對(duì)象。

其實(shí),內(nèi)存沒(méi)有進(jìn)行分段,分段完全是由 CPU 搞的,上面聊過(guò)的通過(guò)基礎(chǔ)地址 + 偏移地址 = 物理地址的方式給出內(nèi)存單元的物理地址,使得我們可以分段管理 CPU。

如圖所示

這是兩個(gè) 16 KB 的程序分別被裝載進(jìn)內(nèi)存的示意圖,可以看到,這兩個(gè)程序的段地址的大小都是 16380。

這里需要注意一點(diǎn), 8086 CPU 段地址的計(jì)算方式是段地址 * 16,所以,16 位的尋址能力是 2^16 次方,所以一個(gè)段的長(zhǎng)度是 64 KB。

段寄存器

cxuan 在上面只是簡(jiǎn)單為你介紹了一下段寄存器的概念,介紹的有些淺,而且介紹段寄存器不介紹段也有「不知廬山真面目」的感覺(jué),現(xiàn)在為你詳細(xì)的介紹一下,相信看完上面的段的概念之后,段寄存器也是手到擒來(lái)。

我們?cè)诤铣晌锢淼刂返哪菑垐D提到了 相關(guān)部件 的概念,這個(gè)相關(guān)部件其實(shí)就是段寄存器,即 「CS、DS、SS、ES」 。8086 的 CPU 在訪問(wèn)內(nèi)存時(shí),由這四個(gè)寄存器提供內(nèi)存單元的段地址。

CS 寄存器

要聊 CS 寄存器,那么 IP 寄存器是你繞不過(guò)去的曾經(jīng)。CS 和 IP 都是 8086 CPU 非常重要的寄存器,它們指出了 CPU 當(dāng)前需要讀取指令的地址。

CS 的全稱是 Code Segment,即代碼寄存器;而 IP 的全稱是 Instruction Pointer ,即指令指針?,F(xiàn)在知道這兩個(gè)為什么一起出現(xiàn)了吧!

在 8086 CPU 中,由 CS:IP 指向的內(nèi)容當(dāng)作指令執(zhí)行。如下圖所示

說(shuō)明一下上圖

在 CPU 內(nèi)部,由 CS、IP 提供段地址,由加法器負(fù)責(zé)轉(zhuǎn)換為物理地址,輸入輸出控制電路負(fù)責(zé)輸入/輸出數(shù)據(jù),指令緩沖器負(fù)責(zé)緩沖指令,指令執(zhí)行器負(fù)責(zé)執(zhí)行指令。在內(nèi)存中有一段連續(xù)存儲(chǔ)的區(qū)域,區(qū)域內(nèi)部存儲(chǔ)的是機(jī)器碼、外面是地址和匯編指令。

上面這幅圖的段地址和偏移地址分別是 2000 和 0000,當(dāng)這兩個(gè)地址進(jìn)入地址加法器后,會(huì)由地址加法器負(fù)責(zé)將這兩個(gè)地址轉(zhuǎn)換為物理地址

然后地址加法器負(fù)責(zé)將指令輸送到輸入輸出控制電路中

輸入輸出控制電路將 20 位的地址總線送到內(nèi)存中。

然后取出對(duì)應(yīng)的數(shù)據(jù),也就是 「B8、23、01」,圖中的 B8、BB 都是操作數(shù)。

控制輸入/輸出電路會(huì)將 B8 23 01 送入指令緩存器中。

此時(shí)這個(gè)指令就已經(jīng)具備執(zhí)行條件,此時(shí) IP 也就是指令指針會(huì)自動(dòng)增加。我們上面說(shuō)到 IP 其實(shí)就是從 Code Segment 也就是 CS 處偏移的地址,也就是偏移地址。它會(huì)知道下一個(gè)需要讀取指令的地址,如下圖所示

在這之后,指令執(zhí)行執(zhí)行取出的 B8 23 01 這條指令。

然后下面再把 2000 和 0003 送到地址加法器中再進(jìn)行后續(xù)指令的讀取。后面的指令讀取過(guò)程和我們上面探討的如出一轍,這里 cxuan 就不再贅述啦。

通過(guò)對(duì)上面的描述,我們能總結(jié)一下 8086 CPU 的工作過(guò)程

  • 段寄存器提供段地址和偏移地址給地址加法器
  • 由地址加法器計(jì)算出物理地址通過(guò)輸入輸出控制電路將物理地址送到內(nèi)存中
  • 提取物理地址對(duì)應(yīng)的指令,經(jīng)由控制電路取回并送到指令緩存器中
  • IP 繼續(xù)指向下一條指令的地址,同時(shí)指令執(zhí)行器執(zhí)行指令緩沖器中的指令

什么是 Code Segment

Code Segment 即代碼段,它就是我們上面聊到就是 CS 寄存器中存儲(chǔ)的基礎(chǔ)地址,也就是段地址,段地址其本質(zhì)上就是一組內(nèi)存單元的地址,例如上面的 「mov ax,0123H 、mov bx, 0003H」。我們可以將長(zhǎng)度為 N 的一組代碼,存放在一組連續(xù)地址、其實(shí)地址為 16 的倍數(shù)的內(nèi)存單元中,我們可以認(rèn)為,這段內(nèi)存就是用來(lái)存放代碼的。

DS 寄存器

CPU 在讀寫一個(gè)內(nèi)存單元的時(shí)候,需要知道這個(gè)內(nèi)存單元的地址。在 8086 CPU 中,有一個(gè) DS 寄存器,通常用來(lái)存放訪問(wèn)數(shù)據(jù)的段地址。如果你想要讀取一個(gè) 10000H 的數(shù)據(jù),你可能會(huì)需要下面這段代碼

mov bx,10000H
mov ds,bx
mov a1,[0]

上面這三條指令就把 10000H 讀取到了 a1 中。

在上面匯編代碼中,mov 指令有兩種傳送方式

  • 一種是把數(shù)據(jù)直接送入寄存器
  • 一種是將一個(gè)寄存器的內(nèi)容送入另一個(gè)寄存器

但是不僅僅如此,mov 指令還具有下面這幾種表達(dá)方式

描述 舉例
mov 寄存器,數(shù)據(jù) 比如:mov ax,8
mov 寄存器,寄存器 比如:mov ax,bx
mov 寄存器,內(nèi)存單元 比如:mov ax,[0]
mov 內(nèi)存單元,寄存器 比如:mov[0], ax
mov 段寄存器,寄存器 比如:mov ds,ax

棧我相信大部分小伙伴已經(jīng)非常熟悉了,是一種具有特殊的訪問(wèn)方式的存儲(chǔ)空間。它的特殊性就在于,先進(jìn)入棧的元素,最后才出去,也就是我們常說(shuō)的 先入后出

它就像一個(gè)大的收納箱,你可以往里面放相同類型的東西,比如書,最先放進(jìn)收納箱的書在最下面,最后放進(jìn)收納箱的書在最上面,如果你想拿書的話, 必須從最上面開(kāi)始取,否則是無(wú)法取出最下面的書籍的。

棧的數(shù)據(jù)結(jié)構(gòu)就是這樣,你把書籍壓入收納箱的操作叫做壓入(push),你把書籍從收納箱取出的操作叫做彈出(pop),它的模型圖大概是這樣

入棧相當(dāng)于是增加操作,出棧相當(dāng)于是刪除操作,只不過(guò)叫法不一樣。棧和內(nèi)存不同,它不需要指定元素的地址。它的大概使用如下

//?壓入數(shù)據(jù)
Push(123);
Push(456);
Push(789);

//?彈出數(shù)據(jù)
j?=?Pop();
k?=?Pop();
l?=?Pop();

在棧中,LIFO 方式表示棧的數(shù)組中所保存的最后面的數(shù)據(jù)(Last In)會(huì)被最先讀取出來(lái)(First Out)。

棧和 SS 寄存器

下面我們就通過(guò)一段匯編代碼來(lái)描述一下棧的壓入彈出的過(guò)程

8086 CPU 提供入棧和出棧指令,最基本的兩個(gè)是 PUSH(入棧)POP(出棧)。比如 push ax 會(huì)把 ax 寄存器中的數(shù)據(jù)壓入棧中,pop ax 表示從棧頂取出數(shù)據(jù)送入 ax 寄存器中。

這里注意一點(diǎn):8086 CPU 中的入棧和出棧都是以字為單位進(jìn)行的。

我這里首先有一個(gè)初始的棧,沒(méi)有任何指令和數(shù)據(jù)。

然后我們向棧中 push 數(shù)據(jù)后,棧中數(shù)據(jù)如下

涉及的指令有

mov ax,2345H
push ax

注意,數(shù)據(jù)會(huì)用兩個(gè)單元存放,高地址單元存放高 8 位地址,低地址單元存放低 8 位。

再向棧中 push 數(shù)據(jù)

其中涉及的指令有

mov bx,0132H
push bx

現(xiàn)在棧中有兩條數(shù)據(jù),現(xiàn)在我們執(zhí)行出棧操作

其中涉及的指令有

pop ax
/* ax = 0132H */

再繼續(xù)取出數(shù)據(jù)

涉及的指令有

pop bx
/* bx = */

完整的 push 和 pop 過(guò)程如下

現(xiàn)在 cxuan 問(wèn)你一個(gè)問(wèn)題,我們上面描述的是 10000H ~ 1000FH 這段空間來(lái)作為 push 和 pop 指令的存取單元。但是,你怎么知道這個(gè)棧單元就是 10000H ~ 1000FH 呢?也就是說(shuō),你如何選擇指定的棧單元進(jìn)行存?。?/p>

事實(shí)上,8086 CPU 有一組關(guān)于棧的寄存器 SSSP。SS 是段寄存器,它存儲(chǔ)的是棧的基礎(chǔ)位置,也就是棧頂?shù)奈恢?,?SP 是棧指針,它存儲(chǔ)的是偏移地址。在任意時(shí)刻,SS:SP 都指向棧頂元素。push 和 pop 指令執(zhí)行時(shí),CPU 從 SS 和 SP 中得到棧頂?shù)牡刂贰?/p>

現(xiàn)在,我們可以完整的描述一下 push 和 pop 過(guò)程了,下面 cxuan 就給你推導(dǎo)一下這個(gè)過(guò)程。

上面這個(gè)過(guò)程主要涉及到的關(guān)鍵變化如下。

當(dāng)使用 「PUSH」 指令向棧中壓入 1 個(gè)字節(jié)單元時(shí),SP = SP - 1;即棧頂元素會(huì)發(fā)生變化;

而當(dāng)使用 「PUSH」 指令向棧中壓入 2 個(gè)字節(jié)的字單元時(shí),SP = SP – 2 ;即棧頂元素也要發(fā)生變化;

當(dāng)使用 「POP」 指令從棧中彈出 1 個(gè)字節(jié)單元時(shí), SP = SP + 1;即棧頂元素會(huì)發(fā)生變化;

當(dāng)使用 「POP」 指令從棧中彈出 2 個(gè)字節(jié)單元的字單元時(shí), SP = SP + 2 ;即棧頂元素會(huì)發(fā)生變化;

棧頂越界問(wèn)題

現(xiàn)在我們知道,8086 CPU 可以使用 SS 和 SP 指示棧頂?shù)牡刂?,并且提?PUSH 和 POP 指令實(shí)現(xiàn)入棧和出棧,所以,你現(xiàn)在知道了如何能夠找到棧頂位置,但是你如何能保證棧頂?shù)奈恢貌粫?huì)越界呢?棧頂越界會(huì)產(chǎn)生什么影響呢?

比如如下是一個(gè)棧頂越界的示意圖

第一開(kāi)始,SS:SP 寄存器指向了棧頂,然后向??臻g push 一定數(shù)量的元素后,SS:SP 位于??臻g頂部,此時(shí)再向??臻g內(nèi)部 push 元素,就會(huì)出現(xiàn)棧頂越界問(wèn)題。

棧頂越界是危險(xiǎn)的,因?yàn)槲覀兗热粚⒁粔K區(qū)域空間安排為棧,那么在??臻g外部也可能存放了其他指令和數(shù)據(jù),這些指令和數(shù)據(jù)有可能是其他程序的,所以如此操作會(huì)讓計(jì)算機(jī)懵逼

我們希望 8086 CPU 能自己解決問(wèn)題,畢竟 8086 CPU 已經(jīng)是個(gè)成熟的 CPU 了,要學(xué)會(huì)自己解決問(wèn)題了。

然鵝(故意的),這對(duì)于 8086 CPU 來(lái)說(shuō),這可能是它一輩子的 夙愿 了,真實(shí)情況是,8086 CPU 不會(huì)保證棧頂越界問(wèn)題,也就是說(shuō) 8086 CPU 只會(huì)告訴你棧頂在哪,并不會(huì)知道棧空間有多大,所以需要程序員自己手動(dòng)去保證。。。


往期推薦




免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉