對(duì)棧進(jìn)行push 和 pop
?程序運(yùn)行時(shí),會(huì)在內(nèi)存上申請(qǐng)分配一個(gè)稱為 「?!?/strong> 的數(shù)據(jù)空間。
?
在棧中,數(shù)據(jù)在存儲(chǔ)時(shí)是從內(nèi)存的下層(大的地址編號(hào)
)逐漸往上層(小的地址編號(hào)
)累積,讀出時(shí)則是按照從上往下的順序進(jìn)行。
棧是 「存儲(chǔ)臨時(shí)數(shù)據(jù)的區(qū)域」 ,它的特點(diǎn)是通過(guò)push
指令和pop
指令進(jìn)行數(shù)據(jù)的存儲(chǔ)和讀出。push
指令和pop
指令中只有一個(gè)操作數(shù)。該操作數(shù)表示的是 「push的是什么及pop的是什么」 ,而不需要指定”對(duì)哪一個(gè)地址編號(hào)的內(nèi)存進(jìn)行push
或pop
“。
這是因?yàn)?,?duì)棧進(jìn)行讀寫的內(nèi)存地址是有esp
寄存器(棧指針)進(jìn)行管理的。push
指令和pop
指令運(yùn)行后,esp
寄存器的值會(huì) 「自動(dòng)進(jìn)行更新」 (push
指令是-4
,pop
指令是+4
),因而就沒(méi)有必要指定內(nèi)存地址了。
函數(shù)調(diào)用機(jī)制
假設(shè)存在如下的C語(yǔ)言
代碼片段。
// 返回兩個(gè)參數(shù)值之和的函數(shù)
int AddNum(int a,int b){
return a + b;
}
// 調(diào)用AddNum函數(shù)的函數(shù)
void MyFunc(){
int c;
c = AddNum(123,456);
}
轉(zhuǎn)換成對(duì)應(yīng)的匯編語(yǔ)言的代碼如下。
這里我們先介紹(3)~(6)
的部分,這對(duì)了解函數(shù)調(diào)用的機(jī)制很重要。
(3)
和(4)
表示的是將傳遞給AddNum
函數(shù)的參數(shù)通過(guò)push
入棧。在C語(yǔ)言
中,雖然記述為函數(shù)AddNum(123,456)
,但入棧的則會(huì)按照456
、123
這樣的順序,也就是位于 「后面的數(shù)值先入?!?/strong> 。
(5)
的call
指令,把程序流程跳轉(zhuǎn)到了操作數(shù)中指定的AddNum
函數(shù)所在的內(nèi)存地址處。在匯編語(yǔ)言中, 「函數(shù)名表示的是函數(shù)所在的內(nèi)存地址」 。AddNum
函數(shù)處理完畢后,程序流程必須要返回到編號(hào)(6)
這一行。call
指令運(yùn)行后,call
指令的下一行((6)
這一行)的內(nèi)存地址會(huì) 「自動(dòng)」 push
入棧。該值會(huì)在AddNum
函數(shù)處理的最后通過(guò)ret
指令pop
出棧,然后程序流程就會(huì)返回到(6)
這一行。
(6)
部分會(huì)把棧中存儲(chǔ)的兩個(gè)參數(shù)(456
和123
)進(jìn)行銷毀處理,也就是 「棧清理處理」 。雖然通過(guò)使用兩次pop
指令也可以實(shí)現(xiàn),不過(guò) 「采用esp
寄存器加8的方式更有效率」 (處理一次)。對(duì)棧進(jìn)行數(shù)值的輸入輸出時(shí),數(shù)值的單位是4字節(jié)。因此,通過(guò)在棧地址管理的esp
寄存器加上4的2倍8,就可以達(dá)到和運(yùn)行兩次pop
命令同樣的效果。
AddNum函數(shù)調(diào)用前后棧的狀態(tài)變化
函數(shù)內(nèi)部的處理
繼續(xù)分析執(zhí)行AddNum
函數(shù)的源代碼部分。
ebp
寄存器的值在(1)
中入棧,在(5)
中出棧。這主要是為了把函數(shù)中用到的ebp
寄存器的內(nèi)容,恢復(fù)到函數(shù)調(diào)用前的狀態(tài)。CPU
擁有的寄存器是有數(shù)量的限制的。在函數(shù)調(diào)用前,調(diào)用源有可能已經(jīng)在使用ebp
寄存器了。因而, 「在函數(shù)內(nèi)部用的寄存器,要盡量返回到函數(shù)調(diào)用前的狀態(tài)」 。
(2)
中負(fù)責(zé)管理?xiàng)5刂返?code>esp寄存器的值賦值到了ebp
寄存器中。這是因?yàn)椋?code>mov指令中方括號(hào)內(nèi)的參數(shù),是不允許指定esp
寄存器的。因此,這里就采用了不直接通過(guò)esp
,而是用ebp
寄存器來(lái)讀寫棧內(nèi)容的方法。
(3)
是用[ebp+8]
指定棧中存儲(chǔ)的第1個(gè)參數(shù)123
,并將其讀出到eax
寄存器中。eax
寄存器是負(fù)責(zé)運(yùn)算的累加寄存器
通過(guò)(4)
的add
指令,把當(dāng)前eax
寄存器的值同第2個(gè)參數(shù)相加后的結(jié)果存儲(chǔ)在eax
寄存器中。 「函數(shù)的參數(shù)是通過(guò)棧來(lái)傳遞,返回值是通過(guò)寄存器來(lái)返回的」 。
(6)
中ret
指令運(yùn)行后,函數(shù)返回目的地的內(nèi)存地址會(huì)自動(dòng)出棧。
AddNum函數(shù)內(nèi)部的棧狀態(tài)變化
全局變量用的內(nèi)存空間
在一些高級(jí)編程語(yǔ)言中,在函數(shù)外部定義的變量稱為 「全局變量」 ,在函數(shù)內(nèi)部定義的變量稱為 「局部變量」 。全局變量可以在源代碼的任意部分被引用,而局部變量只能在定義該變量的函數(shù)內(nèi)進(jìn)行引用。
高級(jí)程序語(yǔ)言被編譯后,會(huì)被歸類到名為 「段」 定義的組。
- 初始化的全局變量被匯總到名為
_DATA
的段定義中 - 沒(méi)有初始化的全局變量被匯總到名為
_BSS
的段定義中 - 指令被匯總到名為
_TEXT
的段定義中
局部變量的內(nèi)存空間
「局部變量只能在定義該變量的函數(shù)內(nèi)進(jìn)行引用」 ,這是因?yàn)?,局部變量是臨時(shí)保存在寄存器和棧中的。
函數(shù)內(nèi)部利用的棧,在函數(shù)處理完畢后會(huì)恢復(fù)到初始狀態(tài),因此局部變量的值也就會(huì)被銷毀,而寄存器也可能被用于其他目的。因此,局部變量只是在函數(shù)處理運(yùn)行期間臨時(shí)存儲(chǔ)在寄存器和棧上。
用于局部變量的??臻g的申請(qǐng)分配和釋放
循環(huán)處理的實(shí)現(xiàn)方法
假設(shè)我們存在如下的代碼,將局部變量i
作為循環(huán)計(jì)數(shù)器連續(xù)進(jìn)行10次循環(huán)的C
語(yǔ)言源代碼。
// 定義MySub函數(shù)
void MySub(){
// 省略部分處理
}
// 定義MyFunc函數(shù)
void MyFunc(){
int i;
for(i=0;i<10;i++){
// 重復(fù)調(diào)用MySub函數(shù)10次
MySub();
}
}
將上述的代碼轉(zhuǎn)換成匯編語(yǔ)言如下(僅展示for
片段)
C語(yǔ)言
的for
語(yǔ)句是通過(guò)在括號(hào)中指定 「循環(huán)計(jì)數(shù)器」 的初始值(i=0
)、循環(huán)的繼續(xù)條件(i<10
)、循環(huán)計(jì)數(shù)器的更新(i++
)這3種形式來(lái)進(jìn)行循環(huán)處理。與此相對(duì),
?在匯編語(yǔ)言的源代碼中,循環(huán)是通過(guò) 「比較指令」 (
cmp
)和 「跳轉(zhuǎn)指令」 (jl
)來(lái)實(shí)現(xiàn)。?
具體流程我們就不在這里贅述。這里挑選比較重要的點(diǎn)來(lái)分析下。
cmp
指令是用來(lái)對(duì)第一個(gè)操作數(shù)和第二個(gè)操作數(shù)的數(shù)值進(jìn)行比較的指令。cmp ebx,10
就相當(dāng)于C語(yǔ)言
的i<10
這一處理,意思是把ebx
寄存器的數(shù)值同10進(jìn)行比較。匯編語(yǔ)言中比較指令的結(jié)果,會(huì)存儲(chǔ)在CPU
的 「標(biāo)志寄存器」 中。
最后一行的jl
是jump on less than
(小于的話就跳轉(zhuǎn))的意思。也就是說(shuō),jl short @4
的意思就是,前面運(yùn)行的比較指令的結(jié)果,若 「小」 的話就跳轉(zhuǎn)到@4
這個(gè) 「標(biāo)簽」 。
條件分支的實(shí)現(xiàn)方式
條件分支的實(shí)現(xiàn)方法同循環(huán)的實(shí)現(xiàn)方法類似,使用的也是cmp
指令和跳轉(zhuǎn)指令。
-
cpu
+關(guān)注
關(guān)注
68文章
11080瀏覽量
217116 -
計(jì)算機(jī)
+關(guān)注
關(guān)注
19文章
7663瀏覽量
90824 -
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7632瀏覽量
141790 -
編譯器
+關(guān)注
關(guān)注
1文章
1662瀏覽量
50228
發(fā)布評(píng)論請(qǐng)先 登錄
《微機(jī)原理與匯編語(yǔ)言》微機(jī)基礎(chǔ)知識(shí)
匯編語(yǔ)言是什么?怎樣去學(xué)習(xí)匯編語(yǔ)言呢
計(jì)算機(jī)的基礎(chǔ)知識(shí)
什么是匯編語(yǔ)言
計(jì)算機(jī)組成原理與匯編語(yǔ)言程序設(shè)計(jì)

微機(jī)原理與匯編語(yǔ)言程序設(shè)計(jì)課件

計(jì)算機(jī)組成原理與匯編語(yǔ)言習(xí)題一
計(jì)算機(jī)基礎(chǔ)知識(shí)介紹
《微機(jī)原理與匯編語(yǔ)言》微機(jī)基礎(chǔ)知識(shí)
計(jì)算機(jī)學(xué)習(xí)教程之指令系統(tǒng)與匯編語(yǔ)言程序設(shè)計(jì)課件免費(fèi)下載
計(jì)算機(jī)的機(jī)器語(yǔ)言和匯編語(yǔ)言與高級(jí)語(yǔ)言的詳細(xì)資料介紹
[從零學(xué)習(xí)匯編語(yǔ)言] - 計(jì)算機(jī)中的硬件與軟件
![[從零學(xué)習(xí)<b class='flag-5'>匯編語(yǔ)言</b>] - <b class='flag-5'>計(jì)算機(jī)</b>中的硬件與軟件](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
構(gòu)建 4 位計(jì)算機(jī):匯編語(yǔ)言和匯編器(第 2 部分)

構(gòu)建 4 位計(jì)算機(jī):匯編語(yǔ)言和匯編器(第 1 部分)

計(jì)算機(jī)基礎(chǔ)知識(shí)之匯編語(yǔ)言1

評(píng)論