真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

go語(yǔ)言的函數(shù)棧幀是 golang函數(shù)調(diào)用棧

"棧"和"棧幀"這兩個(gè)概念到底如何區(qū)分

1、棧:FILO先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)

創(chuàng)新互聯(lián)公司專業(yè)網(wǎng)站建設(shè)、成都網(wǎng)站制作,集網(wǎng)站策劃、網(wǎng)站設(shè)計(jì)、網(wǎng)站制作于一體,網(wǎng)站seo、網(wǎng)站優(yōu)化、網(wǎng)站營(yíng)銷、軟文發(fā)稿等專業(yè)人才根據(jù)搜索規(guī)律編程設(shè)計(jì),讓網(wǎng)站在運(yùn)行后,在搜索中有好的表現(xiàn),專業(yè)設(shè)計(jì)制作為您帶來(lái)效益的網(wǎng)站!讓網(wǎng)站建設(shè)為您創(chuàng)造效益。

棧底是第一個(gè)進(jìn)棧的數(shù)據(jù)的位置(壓箱?底)

棧頂是最后一個(gè)進(jìn)棧的數(shù)據(jù)位置

2、根據(jù)SP指針指向的位置,??煞譃?滿棧和空棧

滿棧:當(dāng)sp指針總是指向最后壓入堆棧?的數(shù)據(jù)(ARM采用滿棧)

空棧:當(dāng)堆棧指針SP總是指向下一個(gè)將?要放入數(shù)據(jù)的空位置。

3、根據(jù)SP指針移動(dòng)的方向,可分為升?棧和降棧

升棧:隨數(shù)據(jù)的入棧,SP由低地址--?高地址

降棧:隨數(shù)據(jù)的入棧,SP由高地址--?低地址(ARM采用降棧)

4、棧幀:存儲(chǔ)在用戶棧上的(當(dāng)然內(nèi)核棧同樣適用)每一次函數(shù)調(diào)用涉及的相關(guān)信息的記錄單元 ;?棧幀(stack frame)就是一個(gè)函數(shù)所使用的那部分棧,所有函數(shù)的棧幀串起來(lái)就組成了一個(gè)完整的棧。

棧幀的兩個(gè)邊界分別有FP(R11)和SP(R13)L來(lái)限定。

棧幀

棧的作用:

1)保存局部變量

分析代碼:

[html]?view plain?copy

#include?stdio.h

int?main()

{

int?a;

a++;

return?a;

}/span

反匯編之后的代碼;

[html]?view plain?copy

stack:?file?format?elf32-littlearm

Disassembly?of?section?.text:

00000000?main:

#include?stdio.h

int?main()

{

0:???e52db004?push???{fp}?????;?(str?fp,?[sp,?#-4]!)?@將棧幀底部指針FP壓入棧中;創(chuàng)建屬于main函數(shù)的棧幀。

4:???e28db000?add????fp,?sp,?#0??;?0x0?@fp指針為函數(shù)棧幀的底部,

8:???e24dd00c?sub????sp,?sp,?#12?;?0xc???@sp指針為棧幀的頂部,同時(shí)為棧的棧頂。

int?a;

a++;

c:???e51b3008?ldr????r3,?[fp,?#-8]???@由此三句可知變量a在棧幀中執(zhí)行了加法操作,及棧幀具有保存局部變量的作用

10:???e2833001?add????r3,?r3,?#1??;?0x1

14:???e50b3008?str????r3,?[fp,?#-8]

return?a;

18:???e51b3008?ldr????r3,?[fp,?#-8]

}

/span

2)保存函數(shù)的參數(shù)

分析代碼:

[html]?view plain?copy

span?style="font-size:18px;"#include?stdio.h

void?func1(int?a,int?b,int?c,int?d,int?e,int?f)

{

int?k;

k=e+f;

}

int?main()

{

func1(1,2,3,4,5,6);

return?0;

}

反匯編之后的代碼;

void?func1(int?a,int?b,int?c,int?d,int?e,int?f)?@多于4個(gè)參數(shù)

{

0:???e52db004?push???{fp}?????;?(str?fp,?[sp,?#-4]!)@保存main函數(shù)的棧幀底部指針FP

4:???e28db000?add????fp,?sp,?#0??;?0x0

8:???e24dd01c?sub????sp,?sp,?#28?;?0x1c?@由棧幀頂部指針SP創(chuàng)建一片棧幀保存子函數(shù)的前四個(gè)參數(shù)

c:???e50b0010?str????r0,?[fp,?#-16]??@?a

10:???e50b1014?str????r1,?[fp,?#-20]??@?b

14:???e50b2018?str????r2,?[fp,?#-24]??@?c

18:???e50b301c?str????r3,?[fp,?#-28]??@?d

int?k;

k=e+f;

1c:???e59b3004?ldr????r3,?[fp,?#4]????@在子函數(shù)的棧幀中實(shí)現(xiàn)第五個(gè)參數(shù)與第六個(gè)參數(shù)的運(yùn)算

20:???e59b2008?ldr????r2,?[fp,?#8]?@由ldr??r2,?[fp,?#8]知參數(shù)保存在main函數(shù)的棧幀中,并運(yùn)算

24:???e0833002?add????r3,?r3,?r2???@以子函數(shù)的棧幀底部指針(fp)做參考坐標(biāo)實(shí)現(xiàn)對(duì)參數(shù)的查找

28:???e50b3008?str????r3,?[fp,?#-8]

}

2c:???e28bd000?add????sp,?fp,?#0??;?0x0

30:???e8bd0800?pop????{fp}

34:???e12fff1e?bx?lr

00000038?main:

int?main()

{

38:???e92d4800?push???{fp,?lr}????@由于調(diào)用子函數(shù),先保存main函數(shù)的棧幀底部指針FP和返回地址LR(當(dāng)前PC指針的下一地址)

3c:???e28db004?add????fp,?sp,?#4??;?0x4?@可知先壓入FP,后壓入lr.把此時(shí)子函數(shù)(被調(diào)用者)的棧幀底部指針FP指向保存在子函數(shù)棧幀的main函數(shù)(調(diào)用者)的棧幀底部指針FP

40:???e24dd008?sub????sp,?sp,?#8??;?0x8???@創(chuàng)建棧

func1(1,2,3,4,5,6);

44:???e3a03005?mov????r3,?#5??;?0x5

48:???e58d3000?str????r3,?[sp]

4c:???e3a03006?mov????r3,?#6??;?0x6

50:???e58d3004?str????r3,?[sp,?#4]

54:???e3a00001?mov????r0,?#1??;?0x1?@用通用寄存器保存前四個(gè)參數(shù)的值

58:???e3a01002?mov????r1,?#2??;?0x2

5c:???e3a02003?mov????r2,?#3??;?0x3

60:???e3a03004?mov????r3,?#4??;?0x4

64:???ebfffffe?bl?0?func1

return?0;

68:???e3a03000?mov????r3,?#0??;?0x0

}

6c:???e1a00003?mov????r0,?r3

70:???e24bd004?sub????sp,?fp,?#4??;?0x4

74:???e8bd4800?pop????{fp,?lr}

78:???e12fff1e?bx?lr/span

注:C中,若函數(shù)的參數(shù)小于等于4個(gè),則用通用寄存器保存其參數(shù)值,多于4個(gè)的參數(shù)保存在棧中

3)保存寄存器的值

分析代碼:

[html]?view plain?copy

span?style="font-size:18px;"include?stdio.h

void?func2(int?a,int?b)

{

int?k;

k=a+b;

}

void?func1(int?a,int?b)

{

int?c;

func2(3,4);

c=a+b;

}

int?main()

{

func1(1,2);

return?0;

}/span

反匯編之后的代碼;

[html]?view plain?copy

span?style="font-size:18px;"void?func2(int?a,int?b)

{

0:???e52db004?push???{fp}?????;?(str?fp,?[sp,?#-4]!)

4:???e28db000?add????fp,?sp,?#0??;?0x0

8:???e24dd014?sub????sp,?sp,?#20?;?0x14

c:???e50b0010?str????r0,?[fp,?#-16]?@保存寄存器的值

10:???e50b1014?str????r1,?[fp,?#-20]

int?k;

k=a+b;

14:???e51b3010?ldr????r3,?[fp,?#-16]

18:???e51b2014?ldr????r2,?[fp,?#-20]

1c:???e0833002?add????r3,?r3,?r2

20:???e50b3008?str????r3,?[fp,?#-8]

}

24:???e28bd000?add????sp,?fp,?#0??;?0x0

28:???e8bd0800?pop????{fp}

2c:???e12fff1e?bx?lr

00000030?func1:

void?func1(int?a,int?b)

{

30:???e92d4800?push???{fp,?lr}

34:???e28db004?add????fp,?sp,?#4??;?0x4

38:???e24dd010?sub????sp,?sp,?#16?;?0x10

3c:???e50b0010?str????r0,?[fp,?#-16]?@代碼44行調(diào)用func2函數(shù)后,又使用r0\r1保存參數(shù),所以此時(shí)將r0\r1寄存器的

40:???e50b1014?str????r1,?[fp,?#-20]??@值放入棧中

int?c;

func2(3,4);

44:???e3a00003?mov????r0,?#3??;?0x3

48:???e3a01004?mov????r1,?#4??;?0x4

4c:???ebfffffe?bl?0?func2

c=a+b;

50:???e51b3010?ldr????r3,?[fp,?#-16]

54:???e51b2014?ldr????r2,?[fp,?#-20]

58:???e0833002?add????r3,?r3,?r2

5c:???e50b3008?str????r3,?[fp,?#-8]

}

60:???e24bd004?sub????sp,?fp,?#4??;?0x4

64:???e8bd4800?pop????{fp,?lr}

68:???e12fff1e?bx?lr

0000006c?main:

int?main()

{

6c:???e92d4800?push???{fp,?lr}

70:???e28db004?add????fp,?sp,?#4??;?0x4

func1(1,2);

74:???e3a00001?mov????r0,?#1??;?0x1

78:???e3a01002?mov????r1,?#2??;?0x2

7c:???ebfffffe?bl?30?func1

return?0;

80:???e3a03000?mov????r3,?#0??;?0x0

}

84:???e1a00003?mov????r0,?r3

88:???e24bd004?sub????sp,?fp,?#4??;?0x4

8c:???e8bd4800?pop????{fp,?lr}

90:???e12fff1e?bx?lr/span

初始化棧:即對(duì)SP指針賦予一個(gè)內(nèi)存地址(統(tǒng)一標(biāo)準(zhǔn):2440、6410、210)

在內(nèi)存的64MB位置即ldr sp, =0x34000000(2440)

ldr sp, =0x54000000(6410)

ldr sp, =0x24000000(210)

由上可知ARM采用滿棧(指向剛?cè)霔5臄?shù)據(jù))、降棧(由高地址向低地址入棧)

問(wèn)題:因?yàn)锳RM不同工作模式有不同的棧,定義棧的技巧是什么,避免定義相同的地址使用不同棧?

轉(zhuǎn)自:

棧幀是什么

棧幀也叫過(guò)程活動(dòng)記錄,是編譯器用來(lái)實(shí)現(xiàn)過(guò)程或函數(shù)調(diào)用的一種數(shù)據(jù)結(jié)構(gòu)。

C語(yǔ)言中,每個(gè)棧幀對(duì)應(yīng)著一個(gè)未運(yùn)行完的函數(shù)。棧幀中保存了該函數(shù)的返回地址和局部變量。

棧幀,顧名思義,就是棧中的一幀,棧分成很多幀,就如同一個(gè)視頻動(dòng)作分成好多幀一樣。每個(gè)棧幀,對(duì)應(yīng)一個(gè)函數(shù),就是這個(gè)函數(shù)在棧中占用的部分。

golang - channel

通過(guò)var聲明或者make函數(shù)創(chuàng)建的channel變量是一個(gè)存儲(chǔ)在函數(shù)棧幀上的指針,占用8個(gè)字節(jié),指向堆上的hchan結(jié)構(gòu)體

源碼包中src/runtime/chan.go定義了hchan的數(shù)據(jù)結(jié)構(gòu)如下:

hchan結(jié)構(gòu)體的主要組成部分有四個(gè):

用來(lái)保存goroutine之間傳遞數(shù)據(jù)的循環(huán)數(shù)組:buf

用來(lái)記錄此循環(huán)數(shù)組當(dāng)前發(fā)送或接收數(shù)據(jù)的下標(biāo)值:sendx和recvx

用于保存向該chan發(fā)送和從該chan接收數(shù)據(jù)被阻塞的goroutine隊(duì)列: sendq 和 recvq

保證channel寫入和讀取數(shù)據(jù)時(shí)線程安全的鎖:lock

環(huán)形數(shù)組作為channel 的緩沖區(qū) 數(shù)組的長(zhǎng)度就是定義channnel 時(shí)channel 的緩沖大小

在hchan 中包括了讀/寫 等待隊(duì)列, waitq是一個(gè)雙向隊(duì)列,包括了一個(gè)頭結(jié)點(diǎn)和尾節(jié)點(diǎn)。 每個(gè)節(jié)點(diǎn)是一個(gè)sudog結(jié)構(gòu)體變量

channel有2種類型:無(wú)緩沖、有緩沖, 在創(chuàng)建時(shí) make(chan type cap) 通過(guò)cap 設(shè)定緩沖大小

channel有3種模式:寫操作模式(單向通道)、讀操作模式(單向通道)、讀寫操作模式(雙向通道)

channel有3種狀態(tài):未初始化、正常、關(guān)閉

如下幾種狀態(tài)會(huì)引發(fā)panic

channel 是線程安全的,channel的底層實(shí)現(xiàn)中,hchan結(jié)構(gòu)體中采用Mutex鎖來(lái)保證數(shù)據(jù)讀寫安全。在對(duì)循環(huán)數(shù)組buf中的數(shù)據(jù)進(jìn)行入隊(duì)和出隊(duì)操作時(shí),必須先獲取互斥鎖,才能操作channel數(shù)據(jù)


新聞標(biāo)題:go語(yǔ)言的函數(shù)棧幀是 golang函數(shù)調(diào)用棧
轉(zhuǎn)載注明:http://weahome.cn/article/doeoesg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部