www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 嵌入式 > 嵌入式教程
[導讀]編譯器一項很重要的優(yōu)化功能就是對寄存器的分配。與分配在寄存器中的變量相比,分配到內存的變量訪問要慢得多。所以如何將盡可能多的變量分配到寄存器,是編程時應該重點考慮的問題。

14.7寄存器分配

編譯器一項很重要的優(yōu)化功能就是對寄存器的分配。與分配在寄存器中的變量相比,分配到內存的變量訪問要慢得多。所以如何將盡可能多的變量分配到寄存器,是編程時應該重點考慮的問題。

注意

當使用-g或-dubug選項編譯程序時,為了確保調試信息的完整性,寄存器分配的效率比不使用-g或-dubug選項低很多。

14.7.1變量寄存器分配

一般情況下,編譯器會對C函數(shù)中的每一個局部變量分配一個寄存器。如果多個局部變量不會交迭使用,那么編譯器會對它們分配同一個寄存器。當局部變量多于可用的寄存器時,編譯器會把多余的變量存儲到堆棧。這些被寫入堆棧需要訪問存儲器的變量被稱為溢出(Spilled)變量。

為了提高程序的執(zhí)行效率:

·使溢出變量的數(shù)量最少;

·確保最重要的和經(jīng)常用到的變量被分配在寄存器中。

可以被分配到寄存器的變量包括:

·程序中的局部變量;

·調用子程序時傳遞的參數(shù);

·與地址無關變量。

另外,在一些特定條件下,結構體中的域也可以被分配到寄存器中。

表14.1顯示了當C編譯器采用ARM-Thumb過程調用標準時,內部寄存器的編號、名字和分配方法。

表14.1 C編譯器寄存器用法

寄存器編號

可選寄存器名

特殊寄存器名

寄存器用法

r0

a1

函數(shù)調用時的參數(shù)寄存器,用來存放前4個函數(shù)參數(shù)和存放返回值。在函數(shù)內如果將這些寄存器用作其他用途,將破壞其值。

r1

a2

r2

a3

r3

a4

r4

v1

通用變量寄存器

r5

v2

r6

v3

r7

v4

r8

v5

r9

v6或SB或TR

平臺寄存器,不同的平臺對該寄存器的定義不同

r10

v7

通用變量寄存器。在使用堆棧邊界檢測的情況下,r10保存堆棧邊界的地址

r11

v8

通用變量寄存器。

r12

IP

臨時過渡寄存器,函數(shù)調用時會破壞其中的值

r13

SP

堆棧指針

r14

LR

鏈接寄存器

r15

PC

程序計數(shù)器

從表14.1可以看出,編譯器可以分配14個變量到寄存器而不會發(fā)生溢出。但有些寄存器編譯器會有特殊用途(如r12),所以在編寫程序時應盡量限制變量的數(shù)目,使函數(shù)內部最多使用12個寄存器。

注意

在C語言中,可以使用關鍵詞register給指定變量分配專用寄存器。但不同的編譯器對該關鍵詞的處理可能不同,使用時要查閱相關手冊。

14.7.2指針別名

C語言中的指針變量可以給編程帶來很大的方便。但使用指針變量時要特別小心,它很可能使程序的執(zhí)行效率下降。在一個函數(shù)中,編譯器通常不知道是否有2個或2個以上的指針指向同一個地址對象。所以編譯器認為,對任何一個指針的寫入都將會影響從任何其他指針的讀出,但這樣會明顯降低代碼執(zhí)行的效率。這就是著名的“寄存器別名(PointerAliasing)”問題。

注意

一些編譯器提供了“忽略指針別名”選項,但這可能給程序帶來潛在的bug。ARM編譯器是遵循ANSI/ISO標準的編譯器,不提供該選項。

1.局部變量指針別名問題

通常情況下,編譯器會試圖對C函數(shù)中的每一個局部變量分配一個寄存器。但當局部變量是指向內存地址的指針時,情況有所不同。先來看一個簡單的例子。

voidadd(int*i)

{

inttotal1=0,total2=0;

total1+=*i;

total2+=*i;

}

編譯后生成:

add:

0000807CE3A01000MOVr1,#0

>>>POINTALIAS\#3inttotal1=0,total2=0;

00008080E3A02000MOVr2,#0

>>>POINTALIAS\#5total1+=*i;

00008084E5903000LDRr3,[r0,#0]

00008088E0831001ADDr1,r3,r1

>>>POINTALIAS\#6total2+=*i;

0000808CE5903000LDRr3,[r0,#0]

00008090E0832002ADDr2,r3,r2

>>>POINTALIAS\#8}

00008094E12FFF1EBXr14

>>>POINTALIAS\#11{

注意程序中i的值被裝載了兩次。因為編譯器不能確定指針*i是否有別名存在,這就使得編譯器不得不增加一條額外的Load指令。

另一個問題,當在函數(shù)中要獲得局部變量地址時,這個變量就被一個指針所對應,就可能與其他指針產(chǎn)生別名。為了防止別名發(fā)生,在每次對變量操作時,編譯器就會從堆棧中重新讀入數(shù)據(jù)??紤]下面的例子程序,分析其產(chǎn)生的編譯結果。

voidf(int*a);

intg(inta);

inttest1(inti)

{f(&i);

/*nowuse’i’extensively*/

i+=g(i);

i+=g(i);

returni;

}

編譯結果如下所示。

test1

STMDBsp!,{a1,lr}

MOVa1,sp

BLf

LDRa1,[sp,#0]

BLg

LDRa2,[sp,#0]

ADDa1,a1,a2

STRa1,[sp,#0]

BLg

LDRa2,[sp,#0]

ADDa1,a1,a2

ADDsp,sp,#4

LDMIAsp!,{pc}

從上面代碼的編譯結果可以看出,對每一次i操作,編譯器都將會從堆棧中讀出其值。這是因為,一旦在函數(shù)中出現(xiàn)對i的取值操作,編譯器就會擔心別名問題。為了避免這種情況,盡量不要在程序中使用局部變量地址。如果必須這么做,那么可以在使用之前先把局部變量的值復制到另外一個局部變量中。下面的程序是對test1函數(shù)的優(yōu)化。

inttest2(inti)

{

intdummy=i;

f(&dummy);

i=dummy;

/*nowuse’i’extensively*/

i+=g(i);

i+=g(i);

returni;

}

編譯后的結果如下。

test2

STMDBsp!,{v1,lr}

STRa1,[sp,#-4]!

MOVa1,sp

BLf

LDRv1,[sp,#0]

MOVa1,v1

BLg

ADDv1,a1,v1

MOVa1,v1

BLg

ADDa1,a1,v1

ADDsp,sp,#4

LDMIAsp!,{v1,pc}

從編譯結果可以看出,修改后的代碼只使用了2次內存訪問,而test1為4次內存訪問。

總上所述,為了在程序中避免指針別名,應該做到:

·避免使用局部變量地址;

·如果程序中出現(xiàn)多次對同一指針的訪問,應先將其值取出并保存到臨時變量中。

2.全局變量

通常情況下,編譯器不會為全局變量分配寄存器。這樣在程序中使用全局變量,很可能帶來內存訪問上的開銷。所有盡量避免在循環(huán)體內使用全局變量,以減少對內存的訪問次數(shù)。

如果在一段程序體內大量使用了同一個全局變量,建議在使用前先將其拷貝到一個局部的臨時變量中,當完成對它的全部操作后,再將其寫回到內存。

比較下面兩個完成同樣功能的函數(shù),分析全局變量的操作對程序性能的影響。

intf(void);

intg(void);

interrs;

voidtest1(void)

{

errs+=f();

errs+=g();

}

voidtest2(void)

{

intlocalerrs=errs;

localerrs+=f();

localerrs+=g();

errs=localerrs;

}

編譯結果如下。

test1

STMDBsp!,{v1,lr}

BLf

LDRv1,[pc,#L00002c-.-8]

LDRa2,[v1,#0]

ADDa1,a1,a2

STRa1,[v1,#0]

BLg

LDRa2,[v1,#0]

ADDa1,a1,a2

STRa1,[v1,#0]

LDMIAsp!,{v1,pc}

L00002c

DCD|x$dataseg|

test2

STMDBsp!,{v1,v2,lr}

LDRv1,[pc,#L00002c-.-8]

LDRv2,[v1,#0]

BLf

ADDv2,a1,v2

BLg

ADDa1,a1,v2

STRa1,[v1,#0]

LDMIAsp!,{v1,v2,pc}

從編譯的結果中可以看出,test1中每次對全局變量errs的訪問都會使用耗時的Load/Store指令;而test2只使用了一次內存訪問指令。這對提高程序的整體性能有很大幫助。

3.指針鏈

指針鏈(PointerChains)常被用來訪問結構體內部變量。下面的例子顯示了一個典型的指針鏈的使用。

typedefstruct{intx,y,z;}Point3;

typedefstruct{Point3*pos,*direction;}Object;

voidInitPos1(Object*p)

{

p->pos->x=0;

p->pos->y=0;

p->pos->z=0;

}

上面的代碼每次使用“p->pos”時都會對變量重新取值。為了提高代碼效率,將程序改寫如下。

voidInitPos2(Object*p)

{

Point3*pos=p->pos;

pos->x=0;

pos->y=0;

pos->z=0;

}

經(jīng)過改寫的代碼,減少了內存訪問次數(shù),提高程序的執(zhí)行效率,另外也可以在object結構體中增加一個point3域,專門作為指向p->pos的指針。

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉
關閉