日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Linux系統(tǒng)中堆棧的espeip解析(linux堆棧espeip)

Linux系統(tǒng)中堆棧的ESP/EIP解析

在計(jì)算機(jī)系統(tǒng)中,棧是一種常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),常作為程序的運(yùn)行空間之一,其中堆棧是最常用的一種。Linux系統(tǒng)中的棧是用C語(yǔ)言實(shí)現(xiàn)的,并且在內(nèi)存中以“后進(jìn)先出”的方式進(jìn)行存儲(chǔ)和管理。在程序運(yùn)行時(shí),棧被用來(lái)保存函數(shù)調(diào)用的返回地址和局部變量,還用來(lái)作為內(nèi)存緩存圈和臨時(shí)存儲(chǔ)區(qū)域。在本文中,將詳細(xì)分析Linux系統(tǒng)中堆棧的ESP/EIP解析。

ESP是指棧指針寄存器,EIP是指指令指針寄存器,它們都是CPU寄存器中的一種。ESP通常用來(lái)記錄棧的棧頂位置,而EIP則用來(lái)記錄程序?qū)⒁獔?zhí)行的下一條指令的地址。它們?cè)谝黄鸨挥脕?lái)為CPU提供一個(gè)基于棧的函數(shù)調(diào)用機(jī)制。

當(dāng)程序執(zhí)行到函數(shù)調(diào)用指令時(shí),會(huì)將當(dāng)前指令的地址壓入棧中,同時(shí)將ESP指針向下移動(dòng),指向新的棧頂。接著程序會(huì)跳轉(zhuǎn)到指定的函數(shù)地址,并繼續(xù)執(zhí)行函數(shù)中的代碼。在函數(shù)執(zhí)行過(guò)程中,棧會(huì)被用來(lái)存放函數(shù)的參數(shù)和局部變量。在函數(shù)執(zhí)行完畢后,原來(lái)的棧頂?shù)刂繁粡棾?,同時(shí)ESP指針向上移動(dòng),指向新的棧頂。此時(shí),程序會(huì)繼續(xù)執(zhí)行上一層函數(shù)中的代碼,通過(guò)EIP指針跳轉(zhuǎn)到之前保存的返回地址中。

在多層函數(shù)調(diào)用時(shí),棧會(huì)不斷地被創(chuàng)建和銷毀,同時(shí)ESP和EIP指針也會(huì)有相應(yīng)的變化。當(dāng)一個(gè)函數(shù)A調(diào)用另一個(gè)函數(shù)B時(shí),程序必須將A函數(shù)的ESP和EIP指針保存下來(lái),以便在B函數(shù)執(zhí)行完畢后,能夠正確地返回到A函數(shù)中。這種保存ESP和EIP指針的機(jī)制稱為棧幀,是用來(lái)管理?xiàng)V懈鱾€(gè)函數(shù)調(diào)用過(guò)程的重要數(shù)據(jù)結(jié)構(gòu)。

在Linux系統(tǒng)中,ESP和EIP指針的值是由操作系統(tǒng)內(nèi)核進(jìn)行管理的。當(dāng)一個(gè)程序通過(guò)系統(tǒng)調(diào)用向操作系統(tǒng)請(qǐng)求分配內(nèi)存時(shí),內(nèi)核會(huì)自動(dòng)將堆棧分配給該程序,并分配相應(yīng)的ESP和EIP寄存器。同時(shí),內(nèi)核還會(huì)為程序分配一個(gè)初始的棧幀,用來(lái)存儲(chǔ)程序執(zhí)行過(guò)程中的基本信息。隨著程序的執(zhí)行,內(nèi)核會(huì)根據(jù)需要?jiǎng)討B(tài)地創(chuàng)建和銷毀棧幀,并更新ESP和EIP指針的值。這樣,程序在運(yùn)行過(guò)程中就可以訪問(wèn)正確的棧空間,同時(shí)能夠正確地返回到上一層函數(shù)中。

在分析Linux系統(tǒng)中的ESP/EIP解析時(shí),需要注意的是,ESP指針向下移動(dòng)表示棧頂向下移動(dòng),而EIP指針向上移動(dòng)表示程序?qū)⒁獔?zhí)行的下一條指令向上移動(dòng)。它們?cè)谡麄€(gè)程序執(zhí)行過(guò)程中都是相對(duì)變化的,而不是絕對(duì)變化的。因此,在編寫Linux程序時(shí),需要明確掌握棧和棧幀的相關(guān)知識(shí),正確使用ESP和EIP指針,以確保程序能夠正確地運(yùn)行和返回。

綜上所述,Linux系統(tǒng)中的ESP和EIP指針是用來(lái)管理?xiàng):蜅闹匾拇嫫?。它們?cè)诔绦虻暮瘮?shù)調(diào)用和返回過(guò)程中發(fā)揮重要的作用,是程序正確執(zhí)行的關(guān)鍵。在編寫Linux程序時(shí),需要充分理解ESP和EIP指針在程序中的作用,合理管理?xiàng):蜅?,以確保程序能夠正確運(yùn)行。

相關(guān)問(wèn)題拓展閱讀:

  • linux c 引用傳遞參數(shù)
  • 從用戶狀態(tài)轉(zhuǎn)換到核心狀態(tài)是通過(guò)什么實(shí)現(xiàn)的?

linux c 引用傳遞參數(shù)

C/C++函數(shù)參數(shù)的傳遞方式有三種:值傳遞(pass by value)、指針傳遞(pass bypointer)、引用傳遞(pass by reference)。

C/C++函數(shù)參數(shù)的傳遞通道是通過(guò)堆棧傳遞,默認(rèn)遵循弊改__cdecl(C聲明方式),參數(shù)由改檔調(diào)用者從右往左逐個(gè)壓入堆棧,在函數(shù)調(diào)用完成之后再由調(diào)用者恢復(fù)堆棧。(Win32API遵循stdcall傳參規(guī)范的,不在本文討論范圍)

下面是測(cè)試代碼

void Swap(__int64* _pnX, __int64* _pnY)

{

__int64 nTemp = *_pnX;

*_pnX = *_pnY;

*_pnY = nTemp;

}

void Swap(__int64& _nX, __int64& _nY)

{

__int64 nTemp = _nX;

_nX = _nY;

_nY = nTemp;

}

void SetValue(__int64 _nX)

{

__int64 nTemp = _nX;

}

// Test001

void GetMemory(__int64* _pBuff)

{

_pBuff = new __int64;

}

// Test002

void GetMemory(__int64** _ppBuff)

{

*_ppBuff = new __int64;

}

int _tmain(int argc, _TCHAR* argv)

{

__int64 nA = 0x10;

__int64 nB = 0x20;

// Test to pass by pointer

Swap(&nA, &nB);

// Test to pass by reference

Swap(nA, nB);

// Test to pass by value

SetValue(nA);

// Test the pointer that points the pointer

__int64* _pArray = NULL;

GetMemory(&_pArray);

delete _pArray;

_pArray = NULL;

//租殲判 Test the pointer

GetMemory(_pArray);

return 0;

}

指針傳遞和引用傳遞

// 下面看一下對(duì)應(yīng)的反匯編的代碼(VS版)

__int64 nA = 0x10;

E movdword ptr ,10h

movdword ptr ,0

__int64 nB = 0x20;

C movdword ptr ,20h

movdword ptr ,0

// Test to pass by pointer

Swap(&nA, &nB);

A leaeax,

D pusheax

E leaecx,

pushecx

callSwap (4111E5h)

addesp,8

// Test to pass by reference

Swap(nA, nB);

A leaeax,

D pusheax

E leaecx,

pushecx

callSwap (4111E0h)

addesp,8

// GCC版

0x: lea eax,

0x: mov DWORD PTR ,eax

0xa : lea eax,

0xe : mov DWORD PTR ,eax

0x: call 0x

0x: lea eax,

0xa : mov DWORD PTR ,eax

0xe : lea eax,

0x004015a2 : mov DWORD PTR ,eax

0x004015a5 : call 0x

通過(guò)上面的反匯編代碼,我們可以看出指針傳遞和引用傳遞在機(jī)制是一樣的,都是將指針值(即地址)壓入棧中,調(diào)用函數(shù),然后恢復(fù)棧。Swap(nA, nB)和Swap(&nA, &nB);在實(shí)際上的匯編代碼也基本上一模一樣,都是從棧中取出地址來(lái)。由此可以看出引用和指針在效率上是一樣的。這也是為什么指針和引用都可以達(dá)到多態(tài)的效果。指針傳遞和引用傳遞其實(shí)都是改變的地址指向的內(nèi)存上的值來(lái)達(dá)到修改參數(shù)的效果。

值傳遞

下面是值傳遞對(duì)應(yīng)的反匯編代碼

// Test to pass by value

SetValue(nA);

A moveax,dword ptr

D pusheax

E movecx,dword ptr

pushecx

callSetValue (4111EAh)

addesp,8

因?yàn)槲业臋C(jī)器是32位的CPU,從上面的匯編代碼可以看64Bit的變量被分成2個(gè)32Bit的參數(shù)壓入棧中。這也是我們常說(shuō)的,值傳遞會(huì)形成一個(gè)拷貝。如果是一個(gè)自定義的結(jié)構(gòu)類型,并且有很多參數(shù),那么如果用值傳遞,這個(gè)結(jié)構(gòu)體將被分割為非常多個(gè)32Bit的逐個(gè)拷貝到棧中去,這樣的參數(shù)傳遞效率是非常慢的。所以結(jié)構(gòu)體等自定義類型,都使用引用傳遞,如果不希望別人修改結(jié)構(gòu)體變量,可以加上const修飾,如(const MY_STRUCT& _value);

下面來(lái)看一下Test001函數(shù)對(duì)應(yīng)的反匯編代碼的參數(shù)傳遞

__int64* _pArray = NULL;

004137E0 movdword ptr ,0

// Test the pointer

GetMemory(_pArray);

moveax,dword ptr

pusheax

callGetMemory (411203h)

B addesp,4

從上面的匯編代碼可以看出,其實(shí)是0被壓入到棧中作為參數(shù),所以GetMemory(_pArray)無(wú)論做什么事,其實(shí)都與指針變量_pArray無(wú)關(guān)。GetMemory()分配的空間是讓棧中的臨時(shí)變量指向的,當(dāng)函數(shù)退出時(shí),棧得到恢復(fù),結(jié)果申請(qǐng)的空間沒(méi)有人管,就產(chǎn)生內(nèi)存泄露的問(wèn)題了?!禖++ Primer》將參數(shù)傳遞分為引用傳遞和非引用傳遞兩種,非引用傳遞其實(shí)可以理解為值傳遞。這樣看來(lái),指針傳遞在某種意義上也是值傳遞,因?yàn)閭鬟f的是指針的值(1個(gè)4BYTE的值)。值傳遞都不會(huì)改變傳入實(shí)參的值的。而且普通的指針傳遞其實(shí)是改變的指針變量指向的內(nèi)容。

下面再看一下Test002函數(shù)對(duì)應(yīng)的反匯編代碼的參數(shù)傳遞

__int64* _pArray = NULL;

004137E0 movdword ptr ,0

GetMemory(&_pArray);

004137E7 leaeax,

004137EA pusheax

004137EB callGetMemory (4111FEh)

004137F0 addesp,4

從上面的匯編代碼lea eax, 可以看出,_pArray的地址被壓入到棧中去了。

然后看一看GetMemory(&_pArray)的實(shí)現(xiàn)匯編代碼。

0xb :push ebp

0xc :mov ebp,esp

0xe :sub esp,0x18

0x004015a1 :mov DWORD PTR ,0x20

0x004015a8 :call 0x473ef0

0x004015ad :mov edx,DWORD PTR

0x004015b0 :mov DWORD PTR ,eax

0x004015b2 :leave

0x004015b3 :ret

藍(lán)色的代碼是分配臨時(shí)變量空間,然后調(diào)用分配空間函數(shù)分配空間,得到的空間指針即eax.

然后紅色的匯編代碼即從ebp+0x8的棧上取到上面壓入棧中的參數(shù)_pArray的地址.

mov DWORD PTR ,eax即相當(dāng)于把分配的空間指針eax讓edx指向,也即讓_pArray指向分配的空間eax.

從用戶狀態(tài)轉(zhuǎn)換到核心狀態(tài)是通過(guò)什么實(shí)現(xiàn)的?

用戶態(tài)和內(nèi)核態(tài)的轉(zhuǎn)換

1)用戶態(tài)切換到內(nèi)核態(tài)的3種方式

a. 系統(tǒng)調(diào)用 這是用戶態(tài)進(jìn)程主動(dòng)要求切換到內(nèi)核態(tài)的一種方式,用戶態(tài)進(jìn)程通過(guò)系統(tǒng)調(diào)用申請(qǐng)使用操作系統(tǒng)提供的服務(wù)程序完成工作,比如前例中fork()實(shí)際上就是執(zhí)行了一個(gè)創(chuàng)建新進(jìn)程的系統(tǒng)調(diào)用。而系統(tǒng)調(diào)用的機(jī)制其核心還是使用了操作系統(tǒng)為用戶特別開放的一個(gè)中斷來(lái)實(shí)現(xiàn),例如Linux的int 80h中斷。系統(tǒng)調(diào)用實(shí)質(zhì)上是一個(gè)中斷,而匯編指令int 就可以實(shí)現(xiàn)用戶態(tài)向內(nèi)核態(tài)切換,iret實(shí)現(xiàn)內(nèi)核態(tài)向用戶態(tài)切換 b. 異常 當(dāng)CPU在執(zhí)行運(yùn)行在用戶態(tài)下的程序時(shí),發(fā)生了某些事先不可知的異常,這時(shí)會(huì)觸發(fā)由當(dāng)前運(yùn)行進(jìn)程切換到處理此異常的內(nèi)核相關(guān)程序中,也就轉(zhuǎn)到了內(nèi)核態(tài),比如缺頁(yè)異常。

c. 外圍設(shè)備的中斷 當(dāng)外圍設(shè)備完成用戶請(qǐng)求的操作后,會(huì)向CPU發(fā)出相應(yīng)的中斷信號(hào),這時(shí)CPU會(huì)暫停執(zhí)行下一條即將要執(zhí)行的指令轉(zhuǎn)而去執(zhí)行與中斷信號(hào)對(duì)應(yīng)的處理程序,如果先前執(zhí)行的指令是用戶態(tài)下的程序,那么這個(gè)轉(zhuǎn)換慎嫌的過(guò)程自然也就發(fā)生銀孝慧了由用戶態(tài)到內(nèi)核態(tài)的切換。比如硬盤讀寫操作完成,系統(tǒng)會(huì)切換到硬盤讀寫的中斷處理程序中執(zhí)行后續(xù)操作等。 這3種方式是系統(tǒng)在運(yùn)行時(shí)由用戶態(tài)轉(zhuǎn)到內(nèi)核態(tài)的最主要方式,其中系統(tǒng)調(diào)用可以認(rèn)為是用戶進(jìn)程主動(dòng)發(fā)起的,異常和外圍設(shè)備中斷則是被動(dòng)的。

2)具體的切換操作 從觸發(fā)方式上看,可以認(rèn)為存在前述3種不同的類型,但是從最終實(shí)際完成由用戶態(tài)到內(nèi)核態(tài)的切換操作上來(lái)說(shuō),涉及的關(guān)鍵步驟是完全一致的,沒(méi)有任何區(qū)別,都相當(dāng)于執(zhí)行了一個(gè)中斷響應(yīng)的過(guò)程,因?yàn)橄到y(tǒng)調(diào)用實(shí)際上最終是中斷機(jī)制實(shí)現(xiàn)的,而異常和中鋒答斷的處理機(jī)制基本上也是一致的,關(guān)于它們的具體區(qū)別這里不再贅述。關(guān)于中斷處理機(jī)制的細(xì)節(jié)和步驟這里也不做過(guò)多分析,涉及到由用戶態(tài)切換到內(nèi)核態(tài)的步驟主要包括:

從當(dāng)前進(jìn)程的描述符中提取其內(nèi)核棧的ss0及esp0信息。

使用ss0和esp0指向的內(nèi)核棧將當(dāng)前進(jìn)程的cs,eip,eflags,ss,esp信息保存起來(lái),這個(gè) 過(guò)程也完成了由用戶棧到內(nèi)核棧的切換過(guò)程,同時(shí)保存了被暫停執(zhí)行的程序的下一條指令。

將先前由中斷向量檢索得到的中斷處理程序的cs,eip信息裝入相應(yīng)的

寄存器

,開始 執(zhí)行中斷處理程序,這時(shí)就轉(zhuǎn)到了內(nèi)核態(tài)的程序執(zhí)行了。

關(guān)于linux堆棧espeip的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。

香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過(guò)10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn)。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊(cè)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。


文章標(biāo)題:Linux系統(tǒng)中堆棧的espeip解析(linux堆棧espeip)
本文來(lái)源:http://www.5511xx.com/article/dpphejj.html