欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

匯編基礎(chǔ)教程段的定義應(yīng)用詳解

 更新時間:2021年11月04日 16:52:25   作者:LyncDwight  
這篇文章主要為大家介紹了匯編基礎(chǔ)教程段的基本定義與應(yīng)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步

將一段內(nèi)存定義為一個段,用一個段地址指示段,用偏移地址訪問段內(nèi)的單元

種類

代碼段

定義

對于8086PC機,在編程時,可以根據(jù)需要,將一組內(nèi)存單元定義為一個段。

可以將長度為 N( N≤64KB )的一組代碼,存在一組地址連續(xù)、起始地址為 16的倍數(shù)的內(nèi)存單元中,這段內(nèi)存是用來存放代碼的,從而定義了一個代碼段。

例如

這段長度為 10 字節(jié)的字節(jié)的指令,存在從123B0H~123B9H的一組內(nèi)存單元中,我們就可以認(rèn)為,123B0H~123B9H這段內(nèi)存單元是用來存放代碼的 ,是一個代碼段 ,它的段地址為123BH,長度為10字節(jié)。

如何使得代碼段中的指令被執(zhí)行

  • CPU 只認(rèn)被 CS:IP 指向的內(nèi)存單元中的內(nèi)容為指令。
  • 所以要將CS:IP指向所定義的代碼段中的第一條指令的首地址。
  • CS = 123BH,IP = 0000H。

數(shù)據(jù)段

定義

我們可以將一組長度為N(N≤64K)、地址連續(xù)、起始地址為16的倍數(shù)的內(nèi)存單元當(dāng)作專門存儲數(shù)據(jù)的內(nèi)存空間,從而定義了一個數(shù)據(jù)段。

比如我們用123B0H~123B9H這段空間來存放數(shù)據(jù):

  • 段地址:123BH
  • 長度:10字節(jié)

將一段內(nèi)存當(dāng)作數(shù)據(jù)段,是我們在編程時的一種安排,我們可以在具體操作的時候 ,用 ds 存放數(shù)據(jù)段的段地址,再根據(jù)需要,用相關(guān)指令訪問數(shù)據(jù)段中的具體單元。

DS和[address]

我們要讀取10000H單元的內(nèi)容

CPU要讀取一個內(nèi)存單元的時候,必須先給出這個內(nèi)存單元的地址

  • 在8086PC中,內(nèi)存地址由段地址和偏移地址組成。
  • 8086CPU中有一個 DS寄存器,通常用來存放要訪問的數(shù)據(jù)的段地址。

將10000H(1000:0)中的數(shù)據(jù)讀到al中。

mov bx,1000H

mov ds,bx

mov al,[0]

mov 指令可以將一個內(nèi)存單元中的內(nèi)容送入一個寄存器。

mov指令的格式:

  • mov 寄存器名,內(nèi)存單元地址
  • “[…]”表示一個內(nèi)存單元, “[…]”中的0表示內(nèi)存單元的偏移地址。

如何用mov指令從10000H中讀取數(shù)據(jù)?

  • 10000H表示為1000:0(段地址:偏移地址)
  • 將段地址1000H放入ds
  • 用mov al,[0]完成傳送(mov指令中的[]說明操作對象是一個內(nèi)存單元,[]中的0說明這個內(nèi)存單元的偏移地址是0,它的段地址默認(rèn)放在ds中)

如何把1000H送入ds?

  • 8086CPU不支持將數(shù)據(jù)直接送入段寄存器的操作,ds是一個段寄存器。(硬件設(shè)計的問題)
  • mov ds,1000H 是非法的。
  • 數(shù)據(jù)>>一般的寄存器>>段寄存器

例如

我們將123B0H~123BAH的內(nèi)存單元定義為數(shù)據(jù)段,我們現(xiàn)在要累加這個數(shù)據(jù)段中的前3個單元中的數(shù)據(jù),

代碼如下:

棧段

棧空間當(dāng)然也是內(nèi)存空間一部分,它只是一段可以以一種特殊方式進(jìn)行訪問的內(nèi)存空間。

操作方式

棧有兩個基本的操作

入棧:將一個新的元素放到棧頂

出棧:從棧頂取出一個元素

棧頂?shù)脑乜偸亲詈笕霔#枰鰲r,又最先被從棧中取出

棧的操作規(guī)則:LIFO(Last In First Out,后進(jìn)先出)

8086CPU的入棧和出棧操作都是以字為單位進(jìn)行的。

注意:字型數(shù)據(jù)用兩個單元存放,高地址單元放高 8 位,低地址單元放低8 位。

8086CPU提供入棧和出棧指令

 SS:SP  

8086CPU中,有兩個寄存器:

  • 段寄存器SS  存放棧頂?shù)亩蔚刂?/li>
  • 寄存器SP  存放棧頂?shù)钠频刂?/li>

任意時刻,SS:SP指向棧頂元素。

SS和SP只記錄了棧頂?shù)牡刂?,依靠SS和SP可以保證在入棧和出棧時找到棧頂。

棧頂超界的問題

種類

  • 當(dāng)棧滿的時候再使用push指令入棧,
  • ??盏臅r候再使用pop指令出棧,

8086CPU不保證對棧的操作不會超界。

8086CPU 只知道棧頂在何處(由SS:SP指示),而不知道讀者安排的棧空間有多大。

8086CPU的工作機理,只考慮當(dāng)前的情況:

  • 當(dāng)前棧頂在何處;
  • 當(dāng)前要執(zhí)行的指令是哪一條。

解決辦法

  • 要根據(jù)可能用到的最大棧空間,來安排棧的大小,防止入棧的數(shù)據(jù)太多而導(dǎo)致的超界
  • 執(zhí)行出棧操作的時候也要注意,以防??盏臅r候繼續(xù)出棧而導(dǎo)致的超界。

push、pop指令

定義

push和pop指令是可以在寄存器和內(nèi)存之間傳送數(shù)據(jù)的。

PUSH(入棧)

push ax:將寄存器ax中的數(shù)據(jù)送入棧中;

執(zhí)行過程 push ax

(1)SP=SP–2;

(2)將ax中的內(nèi)容送入SS:SP指向的內(nèi)存單元處,SS:SP此時指向新棧頂。

圖示

入棧時,棧頂從高地址向低地址方向增長

POP(出棧)

pop ax :從棧頂取出數(shù)據(jù)送入ax。執(zhí)行過程 (1)將SS:SP指向的內(nèi)存單元處的數(shù)據(jù)送入ax中;(2)SP = SP+2,SS:SP指向當(dāng)前棧頂下面的單元,以當(dāng)前棧頂下面的單元為新的棧頂。

圖示

 

注意:

出棧后,SS:SP指向新的棧頂 1000EH,pop操作前的棧頂元素,1000CH 處的2266H 依然存在 ,但是,它已不在棧中。

當(dāng)再次執(zhí)行push等入棧指令后,SS:SP移至1000CH,并在里面寫入新的數(shù)據(jù),它將被覆蓋。

格式

(1)

push 寄存器:將一個寄存器中的數(shù)據(jù)入棧

pop 寄存器:出棧,用一個寄存器接收出棧的數(shù)據(jù)

例如:push axpop bx

(2)

push 段寄存器:將一個段寄存器中的數(shù)據(jù)入棧 pop

段寄存器:出棧,用一個段寄存器接收出棧的數(shù)據(jù)

例如:push dspop es

(3)

push 內(nèi)存單元:將一個內(nèi)存單元處的字入棧(棧操作都是以字為單位)

pop 內(nèi)存單元:出棧,用一個內(nèi)存字單元接收出棧的數(shù)據(jù)

例如:push [0] pop [2]

指令執(zhí)行時 ,CPU 要知道內(nèi)存單元的地址,可以在 push、pop 指令中給出內(nèi)存單元的偏移地址,段地址在指令執(zhí)行時,CPU從ds中取得。

注意

與mov指令不同的是,push和pop指令訪問的內(nèi)存單元的地址不是在指令中給出的,而是由SS:SP指出的。

CPU執(zhí)行mov指令只需一步操作,就是傳送,而執(zhí)行push、pop指令卻需要兩步操作

執(zhí)行push時:先改變SP,后向SS:SP處傳送。

執(zhí)行pop時: 先讀取SS:SP處的數(shù)據(jù),后改變SP。

push、pop 等棧操作指令,修改的只是SP。也就是說,棧頂?shù)淖兓秶畲鬄椋?~FFFFH。

提供:SS、SP指示棧頂;改變SP后寫內(nèi)存的入棧指令;讀內(nèi)存后改變SP的出棧指令。

棧段定義

  • 可以根據(jù)需要 ,將一組內(nèi)存單元定義為一個段
  • 比如我們將10010H~1001FH 這段長度為 16 字節(jié)的內(nèi)存空間當(dāng)作棧來用,以棧的方式進(jìn)行訪問。
  • 我們可以將長度為 N(N ≤64K )的一組地址連續(xù)、起始地址為16的倍數(shù)的內(nèi)存單元,當(dāng)作棧來用,從而定義了一個棧段
  • 這段空間就可以成為棧段,段地址為1000H,大小為16字節(jié)
  • 如何使的如push、pop 等棧操作指令訪問我們定義的棧段
  • 將SS:SP指向我們定義的棧段。

思考

我們將10000H~1FFFFH這段空間當(dāng)作棧段 ,SS=1000H ,??臻g大小為64KB ,棧最底部的字單元地址為1000:FFFE。

任意時刻,SS:SP指向棧頂,當(dāng)棧中只有一個元素的時候,SS=1000H,SP=FFFEH。

棧為空,就相當(dāng)于棧中唯一的元素出棧,出棧后,SP=SP+2。

SP原來為FFFEH,加2后SP=0,所以,當(dāng)棧為空的時候,SS=1000H,SP=0。

任意時刻,SS:SP指向棧頂元素,當(dāng)棧為空的時候 ,棧中沒有元素 ,也就不存在棧頂元素,所以SS:SP只能指向棧的最底部單元下面的單元 ,該單元的偏移地址為棧最底部的字單元的偏移地址+2 ,棧最底部字單元的地址為1000:FFFE,所以??諘r,SP=0000H。

訪問

對于數(shù)據(jù)段,將它的段地址放在 DS中,用mov、add、sub等訪問內(nèi)存單元的指令時,CPU就將我們定義的數(shù)據(jù)段中的內(nèi)容當(dāng)作數(shù)據(jù)段來訪問;

對于代碼段,將它的段地址放在 CS中,將段中第一條指令的偏移地址放在IP中,這樣CPU就將執(zhí)行我們定義的代碼段中的指令;

對于棧段,將它的段地址放在SS中,將棧頂單元的偏移地置放在 SP 中,這樣CPU在需要進(jìn)行棧操作的時候,比如執(zhí)行 push、pop 指令等,就將我們定義的棧段當(dāng)作棧空間來用。

可見,不管我們?nèi)绾伟才?,CPU 將內(nèi)存中的某段內(nèi)存當(dāng)作代碼 ,是因為CS:IP指向了那里;CPU將某段內(nèi)存當(dāng)作棧 ,是因為 SS:IP 指向了那里

比如我們將10000H~1001FH安排為代碼段,并在里面存儲如下代碼:

設(shè)置CS=1000H,IP=0,這段代碼將得到執(zhí)行。

可以看到,在這段代碼中,我們又將10000H~1001FH 安排為棧段和數(shù)據(jù)段。

10000H~1001FH這段內(nèi)存,既是代碼段,又是棧段和數(shù)據(jù)段。

一段內(nèi)存,可以既是代碼的存儲空間,又是數(shù)據(jù)的存儲空間,還可以是??臻g,也可以什么也不是。

關(guān)鍵在于CPU中寄存器的設(shè)置,即:CS、IP、SS、SP、DS的指向。

段前綴

在訪問內(nèi)存單元的指令中,用于顯式地指明內(nèi)存單元的段地址的“ds:”、“cs:”、“ss:”或“es:”

應(yīng)用

場景1

問題:將內(nèi)存ffff:0~ffff:b段元中的數(shù)據(jù)拷貝到 0:200~0:20b單元中。

分析

(1) 0:200~0:20b單元等同于0020:0~0020:b單元,它們描述的是同一段內(nèi)存空間

(2)拷貝的過程應(yīng)用循環(huán)實現(xiàn),簡要描述如下:

  • 初始化:X=0 循
  • 環(huán)12次

將ffff:X單元中的數(shù)據(jù)送入0020:X(需要用一個寄存器中轉(zhuǎn))

X=X+1

(3)在循環(huán)中,源單元ffff:X和目標(biāo)單元的0020:X的偏移地址X是變量。我們用bx來存放

(4)我們用將0:200~0:20b用0020:0~0020:b描述,就是為了使目標(biāo)單元的偏移地址和源始單元的偏移地址從同一數(shù)值0開始。

問題

因源單元ffff:X和目標(biāo)單元0020:X 相距大于64KB,在不同的64KB段里,程序中,每次循環(huán)要設(shè)置兩次ds。

這樣做是正確的,但是效率不高。

解決

我們可以使用兩個段寄存器分別存放源單元ffff:X和目標(biāo)單元0020:X的段地址,這樣就可以省略循環(huán)中需要重復(fù)做12次的設(shè)置ds的程序段。

改進(jìn)的程序中,使用 es 存放目標(biāo)空間0020:0~0020:b的段地址,用ds存放源空間ffff:0~ffff:b的段地址。

在訪問內(nèi)存單元的指令“mov es:[bx],al”中 ,顯式地用段前綴 “es:” 給出單元的段地址,這樣就不必在循環(huán)中重復(fù)設(shè)置ds

場景2

Debug和匯編編譯器Masm對指令的不同處理

Debug中

  • mov ax,[0]
  • 表示將ds:0處的數(shù)據(jù)送入al中。

在匯編源程序中,指令“mov ax,[0]”被編譯器當(dāng)作指令“mov ax,0”處理。

解決:利用段前綴顯性的指出段地址

以上就是匯編基礎(chǔ)教程段的定義應(yīng)用詳解的詳細(xì)內(nèi)容,更多關(guān)于匯編基礎(chǔ)教程段的資料請關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:

相關(guān)文章

  • 匯編語言系列之匯編實現(xiàn)字符串操作

    匯編語言系列之匯編實現(xiàn)字符串操作

    本文列出了字符串匹配和字符串輸入顯示的代碼,對匯編語言系列之匯編實現(xiàn)字符串操作相關(guān)知識感興趣的朋友跟隨小編一起看看吧
    2021-11-11
  • 匯編語言 跳轉(zhuǎn)指令與C語言的條件分支

    匯編語言 跳轉(zhuǎn)指令與C語言的條件分支

    這篇文章主要介紹了匯編語言 跳轉(zhuǎn)指令與C語言的條件分支,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • 匯編語言指令集之條件轉(zhuǎn)移指令實現(xiàn)

    匯編語言指令集之條件轉(zhuǎn)移指令實現(xiàn)

    這篇文章主要介紹了匯編語言指令集之條件轉(zhuǎn)移指令實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 匯編語言中cmp指令用法筆記與總結(jié)

    匯編語言中cmp指令用法筆記與總結(jié)

    這篇文章主要介紹了匯編語言中cmp指令用法,結(jié)合實例形式總結(jié)分析了匯編語言cmp指令基本功能、使用方法及操作注意事項,需要的朋友可以參考下
    2020-01-01
  • 匯編語言AND指令實現(xiàn)對兩個操作數(shù)進(jìn)行邏輯(按位)與操作

    匯編語言AND指令實現(xiàn)對兩個操作數(shù)進(jìn)行邏輯(按位)與操作

    這篇文章主要介紹了匯編語言AND指令實現(xiàn)對兩個操作數(shù)進(jìn)行邏輯(按位)與操作,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • 匯編語言lea指令使用方法解析

    匯編語言lea指令使用方法解析

    這篇文章主要介紹了匯編語言lea指令使用方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • UEFI開發(fā)基礎(chǔ)匯編代碼的使用

    UEFI開發(fā)基礎(chǔ)匯編代碼的使用

    這篇文章主要為大家介紹了UEFI開發(fā)基礎(chǔ)匯編代碼使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • 匯編語言中move指令的使用

    匯編語言中move指令的使用

    MOV指令是在ARM匯編語言中用于將數(shù)據(jù)從一個位置或寄存器復(fù)制到另一個位置或寄存器的指令,本文就來詳細(xì)的介紹一下move指令,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • 匯編語言Debug命令詳解教程

    匯編語言Debug命令詳解教程

    這篇文章主要為大家介紹了匯編語言Debug命令的教程,文中對Debug的命令進(jìn)行了全面的講解有需要的朋友可以借鑒參考共同學(xué)習(xí)下,希望能夠有所幫助
    2021-11-11
  • 匯編語言中mov和lea指令的區(qū)別詳解

    匯編語言中mov和lea指令的區(qū)別詳解

    指令(instruction)是一種語句,它在程序匯編編譯時變得可執(zhí)行。本文給大家總結(jié)一下匯編語言中mov和lea指令的區(qū)別詳解,感興趣的朋友跟隨小編一起看看吧
    2020-01-01

最新評論