- 相關(guān)推薦
華為面試題:怎樣判斷棧的增長(cháng)方向
在華為面試中有這么一道考試,請給出棧增長(cháng)方向的判斷方法。下面一起來(lái)看看這道題的參考答案,僅供大家參考!
該題目屬于考查計算機組成原理中棧結構知識的題目。其參考答案如下:
可以編寫(xiě)一個(gè)帶有過(guò)程(函數)調用的C程序,然后按照以下方法進(jìn)行判斷(采用類(lèi)似思想,還可以寫(xiě)出許多答案)。
方法一:通過(guò)比較被調用過(guò)程中的入口參數所在地址和局部變量所在地址之間的大小來(lái)判斷。若入口參數所在地址大于局部變量所在地址,則棧是向低地址增長(cháng)的。
方法二:直接閱讀匯編指令來(lái)判斷。例如,在IA-32中,如果在一個(gè)過(guò)程的開(kāi)始階段(準備段)出現類(lèi)似“sub $0x10,%esp”指令,說(shuō)明棧頂指針(%esp)是變小的,因此棧是向低地址增長(cháng)的。
方法三:顯示棧頂指針寄存器的內容。在某個(gè)過(guò)程的開(kāi)始階段和結束階段分別顯示棧頂指針寄存器的內容,比較它們的大小。若開(kāi)始處的值比結束處的大,則說(shuō)明棧是向低地址增長(cháng)的。
后面兩種方法,需要對程序的機器級代碼(匯編指令)進(jìn)行調試,例如,利用Linux系統中的程序調試工具軟件GDB進(jìn)行調試。
該題是開(kāi)放題目,答案應該沒(méi)有唯一性。通過(guò)這個(gè)題目的回答可以考查出學(xué)生對計算機系統中棧結構的掌握情況。
棧是存儲空間中的一個(gè)區域,分用戶(hù)棧和內核棧兩種類(lèi)型。用戶(hù)棧主要用來(lái)存放用戶(hù)進(jìn)程每次過(guò)程(函數)調用時(shí),在被調用過(guò)程中使用的局部信息,每次過(guò)程調用都在棧中生長(cháng)出一個(gè)新的棧幀,因此,棧幀是通過(guò)執行相應的指令動(dòng)態(tài)生長(cháng)出來(lái)的;內核棧是操作系統內核中的動(dòng)態(tài)存儲區域,用于保存操作系統內核和硬件所需要的動(dòng)態(tài)信息。
在采用虛擬存儲管理機制的系統中,內核棧和用戶(hù)棧都是虛擬地址空間中的一個(gè)存儲區。每個(gè)源程序經(jīng)編譯、匯編、鏈接等處理生成可執行的二進(jìn)制機器目標代碼時(shí),每個(gè)程序的目標代碼都被映射到同樣的虛擬地址空間,所有用戶(hù)進(jìn)程的虛擬地址空間是一致的。例如,圖1給出了在IA32/Linux操作系統下hello程序的一個(gè)進(jìn)程對應的虛擬地址空間映像。它分為兩大部分:內核區(kernelarea)和用戶(hù)區(userarea)。
從圖1可以看出,內核區在0xC0000000以上的高端地址上,用來(lái)存放操作系統內核代碼和數據以及與每個(gè)進(jìn)程相關(guān)的數據結構(如進(jìn)程標識信息、進(jìn)程現場(chǎng)信息、頁(yè)表等進(jìn)程控制信息以及內核棧等),其中內核代碼和數據區在每個(gè)進(jìn)程的地址空間中都相同。用戶(hù)程序沒(méi)有權限訪(fǎng)問(wèn)內核區。
用戶(hù)區用來(lái)存放用戶(hù)進(jìn)程的代碼和數據,它被分為以下幾個(gè)區域。
(1) 用戶(hù)棧。用來(lái)存放程序運行時(shí)過(guò)程調用的參數、返回值、返回地址、過(guò)程局部變量等,隨著(zhù)程序的執行,該區會(huì )不斷動(dòng)態(tài)地從高地址向低地址增長(cháng)或向反方向減退。
(2) 共享庫。用來(lái)存放公共的共享函數庫代碼,如hello中的printf( )函數等。
(3) 堆。用于動(dòng)態(tài)申請存儲區,例如,C語(yǔ)言中用malloc()函數分配的存儲區,或C++中用new操作符分配的存儲區。申請一塊內存時(shí),動(dòng)態(tài)地從低地址向高地址增長(cháng),用free( )函數或delete操作符釋放一塊內存時(shí),動(dòng)態(tài)地從高地址向低地址減退。
(4) 可讀寫(xiě)數據區。存放用戶(hù)進(jìn)程中的靜態(tài)全局變量,堆區從該區域的結尾處開(kāi)始向高地址增長(cháng)。
(5) 只讀數據和代碼區。存放用戶(hù)進(jìn)程中的代碼和只讀數據,如hello進(jìn)程中的程序代碼和字符串“hello,world\n”。
每個(gè)區域都有相應的起始位置,堆區和棧區相向生長(cháng),棧區從內核起始位置0xC0000000開(kāi)始向低地址增長(cháng),堆棧中的共享庫代碼區從0x40000000開(kāi)始向高地址增長(cháng)。代碼和只讀數據區從0x08048000開(kāi)始向高地址增長(cháng)。
對于棧的訪(fǎng)問(wèn)操作,有些指令集系統結構提供了專(zhuān)門(mén)的入棧和出棧指令,例如Intel架構中的push指令和pop指令分別用于入棧和出棧操作;有些架構則不提供專(zhuān)門(mén)的入棧和出棧指令,而是通過(guò)訪(fǎng)存指令和加/減指令來(lái)實(shí)現入棧和出棧操作,例如,MIPS架構中用sw指令和add或sub指令實(shí)現入棧操作,用lw指令和add或sub指令實(shí)現出棧操作。
對于像Intel這樣提供專(zhuān)門(mén)入棧和出棧指令的情況,棧的增長(cháng)方向可以根據入棧、出棧指令的功能來(lái)確定,例如,IA-31架構中的push指令自動(dòng)將棧頂指針減4,而pop指令則自動(dòng)將棧頂指針加4。因而,?偸菑母叩刂废虻偷刂吩鲩L(cháng)。
對于像MIPS架構這種沒(méi)有專(zhuān)門(mén)入棧和出棧指令的情況,棧的增長(cháng)方向就不一定,可能是高地址向低地址增長(cháng),或是相反。
因為棧是通過(guò)執行指令動(dòng)態(tài)增長(cháng)的,所以,最直接的判斷辦法就是在機器級代碼層面(通常是匯編指令)來(lái)閱讀或調試程序。
當一個(gè)過(guò)程P調用一個(gè)被調用過(guò)程Q,則P中傳遞給Q的參數會(huì )先入棧,然后執行調用指令(如IA-32中的call指令),跳轉到Q執行,在被調用過(guò)程Q中,再將Q的局部變量入棧,因此,通過(guò)比較Q過(guò)程的入口參數所在地址和局部變量所在地址之間的大小,可以判斷出棧的增長(cháng)方向。
相關(guān)文章推薦:
10.2016年華為上機考試題
【華為面試題:怎樣判斷棧的增長(cháng)方向】相關(guān)文章:
華為Java面試題精選10-13
華為測試面試題匯總09-19
怎樣打方向06-18
2017華為筆試面試題庫09-03
華為c語(yǔ)言筆試面試題題庫08-22
健身期間怎樣飲食增長(cháng)肌肉10-26
如何判斷方向盤(pán)回正 方向盤(pán)回正技巧06-19
2016年華為筆試面試題及答案07-03
怎樣判斷電腦電源壞了08-15