在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式匯編中g(shù)o to到c代碼label最簡(jiǎn)單的用法

Linux閱碼場(chǎng) ? 來(lái)源:CSDN ? 作者:dog250 ? 2021-04-04 17:18 ? 次閱讀

越來(lái)越多的工作現(xiàn)如今都交給了編譯器,甚至連動(dòng)態(tài)代碼修改的數(shù)據(jù)組織這種事都交給了編譯器。gcc提供了一個(gè)特性用于嵌入式匯編,那就是asm goto,其實(shí)這個(gè)特性沒(méi)有什么神秘之處,就是在嵌入式匯編中g(shù)o to到c代碼的label,其最簡(jiǎn)單的用法如下(來(lái)自gcc的文檔):

d0f90b8c-8cdd-11eb-8b86-12bb97331649.png

asm goto其實(shí)就是在outputs,inputs,registers-modified之外提供了嵌入式匯編的第四個(gè)“:”,后面可以跟一系列的c語(yǔ)言的label,然后你可以在嵌入式匯編中g(shù)o to到這些label中一個(gè)。然而使用asm goto可以巧妙地將“一個(gè)大家都能想到的點(diǎn)子”規(guī)范化,就是說(shuō)你只需要調(diào)用一個(gè)統(tǒng)一的接口--一個(gè)宏,編譯器就將你想實(shí)現(xiàn)的東西給實(shí)現(xiàn)了,要不然代碼寫起來(lái)會(huì)很麻煩,這點(diǎn)上,編譯器不嫌麻煩。這一個(gè)大家都能想出的點(diǎn)子的由來(lái)還得從內(nèi)核的效率說(shuō)起。

以下的代碼來(lái)自lwn的《Jump label》:

d11a53be-8cdd-11eb-8b86-12bb97331649.png

即使有了unlikey優(yōu)化,既然有if判斷,cpu的分支預(yù)測(cè)就有可能失敗,再者do_trace在代碼上離if這么近,即使編譯器再聰明,二進(jìn)制代碼的do_trace也不會(huì)離前面的代碼太遠(yuǎn)的,這樣由于局部性原理和cpu的預(yù)取機(jī)制,do_trace的代碼很有可能就被預(yù)取入了cpu的cache,就算我們從來(lái)不打算trace代碼也是如此。

我們需要的是如果不開啟trace,那么do_trace永遠(yuǎn)不被欲取或者被預(yù)測(cè),唯一的辦法就是去掉if判斷,永遠(yuǎn)不調(diào)用goto語(yǔ)句,像下面這樣:

d16ccc02-8cdd-11eb-8b86-12bb97331649.png

在運(yùn)行時(shí)修改載入內(nèi)存的二進(jìn)制代碼就是我們大家都能想到的點(diǎn)子,就是說(shuō)在運(yùn)行的時(shí)候當(dāng)我們知道trace_foo_enabled在某一時(shí)刻被設(shè)置為0的時(shí)候,我們動(dòng)態(tài)的將二進(jìn)制代碼修改掉,將if代碼段去掉,這樣一個(gè)分支預(yù)測(cè)就不存在了,而且trace_foo_enabled這一個(gè)變量也不需要再被訪問(wèn)了(該變量在內(nèi)存中,訪問(wèn)它肯定會(huì)涉及l(fā)oad/flush cache的動(dòng)作,為了一個(gè)很可能沒(méi)有用的變量操作cache很不值)。提前要說(shuō)的是,我們可以使用這種方式去掉所有的分支預(yù)測(cè),然而這并不可取,因?yàn)槌绦蚴莿?dòng)態(tài)運(yùn)行的,很多用于判斷的變量值都是根據(jù)程序的執(zhí)行瞬息萬(wàn)變,正是這種根據(jù)判斷結(jié)果采取不同動(dòng)作的機(jī)制給與了程序靈活性,如果每當(dāng)我們確定一個(gè)值時(shí)就修改二進(jìn)制代碼取消分支預(yù)測(cè)的話,其本身的開銷將會(huì)遠(yuǎn)遠(yuǎn)大于分支預(yù)測(cè)的開銷,更重要的是,緊接著那個(gè)值又變化了,我們不得不再次修改二進(jìn)制代碼,這期間要訪問(wèn)那個(gè)變量好幾次。所以,只有在我們確定不經(jīng)常變化的變量的判斷上才能用這種方式取消分支預(yù)測(cè),而像trace與否的判斷正好符合我們的需求。

gcc編譯器提供了asm goto的機(jī)制來(lái)滿足我們的需求,使得我們可以在asm goto的基礎(chǔ)上構(gòu)建出一個(gè)叫做jump label的東西。下面的代碼段說(shuō)明了jump label的用法和原理:

d1e01e96-8cdd-11eb-8b86-12bb97331649.png

標(biāo)號(hào)0僅僅執(zhí)行一個(gè)nop,不涉及cache,后面的pushsection保存現(xiàn)有的section,很多情況下當(dāng)前的section就是text,然后定義一個(gè)“表”,表中有兩個(gè)元素:0b和trace#NUM,其實(shí)就是兩個(gè)標(biāo)號(hào),在asm goto機(jī)制中,標(biāo)號(hào)還可以更多,它們?cè)谇度胧絽R編的最后一個(gè)“:”后面依次排布。這些標(biāo)號(hào)就是供選擇的標(biāo)號(hào),執(zhí)行流將跳入其中的一個(gè)標(biāo)號(hào)處,具體跳到哪一個(gè)就看當(dāng)前的二進(jìn)制代碼被修改成了“跳到哪一個(gè)”,因此asm goto為我們做的僅僅是提供一個(gè)地方(一個(gè)“:”)供我們將label傳入,保存了一系列的表還是需要我們的c代碼邏輯--jump label實(shí)現(xiàn),這些表(其實(shí)就是一系列的三元組)方便我們根據(jù)這些表來(lái)修改運(yùn)行中的二進(jìn)制代碼,最終修改二進(jìn)制代碼還是要由我們自己寫代碼完成的。

有了這個(gè)asm goto以及我們jump label代碼的支持,內(nèi)核對(duì)于是否trace這種小事就再也不用愁了(使用中的kernel一般是不用trace的,只有在出了問(wèn)題以后或者調(diào)試內(nèi)核時(shí)才使用trace,因此在主代碼中加入“是否trace”的判斷實(shí)在是一種沉重的負(fù)擔(dān)),如果對(duì)于某一個(gè)函數(shù)不需要trace,內(nèi)核只需要執(zhí)行一個(gè)操作將asm goto附近的代碼改掉即可,比如改稱下面這樣:

d1fcdf54-8cdd-11eb-8b86-12bb97331649.png

如果需要trace,那么就改成:

d227dd30-8cdd-11eb-8b86-12bb97331649.png

這一切在kernel中的用法如下:

d246edba-8cdd-11eb-8b86-12bb97331649.png

第一行的“1”是一個(gè)標(biāo)號(hào),該標(biāo)號(hào)后的代碼執(zhí)行的內(nèi)容就是nop-第二行,第三行重新開始了一個(gè)section,這樣的意義很大,下面的三元組:[instruction address] [jump target] [tracepoint key]的二進(jìn)制代碼就不會(huì)緊接著標(biāo)號(hào)1(nop)了,這個(gè)三元組就是jump label機(jī)制的核心,指示了所有可能跳轉(zhuǎn)到的標(biāo)號(hào),這里的技巧在于標(biāo)號(hào)1,標(biāo)號(hào)1也作為一個(gè)合法的可能跳轉(zhuǎn)到的標(biāo)號(hào)存在,和標(biāo)號(hào)label是并列的,由于pushsection和popsection的存在,上面的代碼匯編結(jié)果看起來(lái)是下面這樣:

d262c2c4-8cdd-11eb-8b86-12bb97331649.png

如果啟用了trace,那么只需要將標(biāo)號(hào)1修改成標(biāo)號(hào)label就可以了:

d2b347f8-8cdd-11eb-8b86-12bb97331649.png

內(nèi)核之所以能夠找到需要修改代碼的地址,就是借助于上面說(shuō)的那個(gè)三元組(instruction address,jump target,tracepoint key),其中instruction address就是這個(gè)地址,在linux的JUMP LABEL機(jī)制中,它固定為標(biāo)號(hào)1,也就是nop的標(biāo)號(hào),如果不啟用trace,那么直接執(zhí)行nop,如果啟用了trace,那么將nop修改為jmp label即可,如果后來(lái)又禁用了trace,只需將它再次修改成三元組中的標(biāo)號(hào)1即可,這一切過(guò)程中,三元組本身是不會(huì)改變的。注意,三元組中的tracepoint key在jump label機(jī)制中并沒(méi)有什么實(shí)質(zhì)的意義,它僅僅是為了組織kernel中“是否trace”變量用的,所有的“是否trace”變量組織成一個(gè)鏈表,鏈表的每一個(gè)節(jié)點(diǎn)下面掛著另一個(gè)子鏈表,該子鏈表中元素是所有使用這個(gè)“是否trace”變量的代碼環(huán)境,包括代碼的地址,標(biāo)號(hào)的地址等。

下面看一下kernel對(duì)于JUMP_LABEL的實(shí)現(xiàn)框架。首先看一下三元組的數(shù)據(jù)結(jié)構(gòu):

d2f035e6-8cdd-11eb-8b86-12bb97331649.png

其次一個(gè)比較重要的數(shù)據(jù)結(jié)構(gòu)是一個(gè)key節(jié)點(diǎn),表示一個(gè)“是否trace”的變量:

d33b7420-8cdd-11eb-8b86-12bb97331649.png

啟用一個(gè)trace意味著需要將一個(gè)key(類似于trace_foo_enabled)設(shè)置為1,然后修改所有判斷該key的代碼附近的二進(jìn)制代碼:

d3842de6-8cdd-11eb-8b86-12bb97331649.png

d3b8bc78-8cdd-11eb-8b86-12bb97331649.png

以上就是使用asm goto實(shí)現(xiàn)的jump label,在2.6.37內(nèi)核中被引入。

附:.section以及.previous

在匯編語(yǔ)言中使用.section和.previous指令可以將它們之間的代碼編譯到不同的section中,也就是不緊接著.section上面的代碼。linux kernel中的異常處理就是用這兩個(gè)偽指令實(shí)現(xiàn)的,定義了一個(gè)叫做fix的section和一個(gè)叫做ex_table的section,可能出現(xiàn)exception的代碼用一個(gè)標(biāo)號(hào)表示,ex_table中保存了一些二元組(出現(xiàn)異常代碼的標(biāo)號(hào),異常處理程序的標(biāo)號(hào)),異常處理程序在fix這個(gè)section中,這樣雖然代碼看起來(lái)是下面這樣:

d3f8c854-8cdd-11eb-8b86-12bb97331649.png

然而編譯器會(huì)將fix和ex_table放到離text很遠(yuǎn)的地方的,這樣cpu預(yù)取時(shí)就不會(huì)將fix或者ex_table的代碼預(yù)取到執(zhí)行cache了,只有在發(fā)生異常的時(shí)候才會(huì)使用fix和ex_table,而發(fā)生異常畢竟是一種罕見現(xiàn)象,這就是一種優(yōu)化。

原文標(biāo)題:asm goto與JUMP_LABEL

文章出處:【微信公眾號(hào):Linuxer】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4793

    瀏覽量

    68700
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1634

    瀏覽量

    49160

原文標(biāo)題:asm goto與JUMP_LABEL

文章出處:【微信號(hào):LinuxDev,微信公眾號(hào):Linux閱碼場(chǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    新手怎么學(xué)嵌入式?

    基本的概念。嵌入式系統(tǒng)是一種將計(jì)算機(jī)技術(shù)嵌入特定設(shè)備的系統(tǒng),它通常具有特定的功能和有限的資源。你需要學(xué)習(xí)一些計(jì)算機(jī)基礎(chǔ)知識(shí),如數(shù)據(jù)結(jié)構(gòu)、操作系統(tǒng)、計(jì)算機(jī)組成原理等。這些知識(shí)將幫助你
    發(fā)表于 12-12 10:51

    嵌入式學(xué)習(xí)建議

    原理的嵌入式操作系統(tǒng)進(jìn)行學(xué)習(xí)。不要一開始就學(xué)習(xí)幾種操作系統(tǒng),理解了基本原理,實(shí)踐確有實(shí)際需要再學(xué)習(xí)也不遲。人總是要不斷學(xué)習(xí)的。 ⑨關(guān)于匯編語(yǔ)言與C語(yǔ)言的取舍。隨著:MCU對(duì)
    發(fā)表于 10-22 11:41

    什么是嵌入式?一文讀懂嵌入式主板

    在現(xiàn)代科技浪潮嵌入式技術(shù)已成為支撐各種智能設(shè)備和系統(tǒng)運(yùn)行的核心力量。那么,究竟什么是嵌入式嵌入式系統(tǒng),顧名思義,是將計(jì)算機(jī)的硬件和軟件嵌入
    的頭像 發(fā)表于 10-16 10:14 ?1120次閱讀

    嵌入式主板是什么意思?嵌入式主板全面解析

    嵌入式主板,通常被稱為嵌入式系統(tǒng)的核心組件,是一種用于控制和數(shù)據(jù)處理的計(jì)算機(jī)硬件,其設(shè)計(jì)旨在嵌入特定設(shè)備執(zhí)行專門任務(wù)。嵌入式主板如同是設(shè)備
    的頭像 發(fā)表于 09-30 10:05 ?573次閱讀

    一種常用嵌入式開發(fā)代碼庫(kù)

    使用開源協(xié)議:GPL-2.0varch簡(jiǎn)介varch(we-architecture,意為我們的框架庫(kù))是嵌入式C語(yǔ)言常用代碼模塊庫(kù),包含了嵌入式中常用的算法庫(kù),數(shù)據(jù)結(jié)構(gòu)(容器)庫(kù),解
    的頭像 發(fā)表于 09-04 08:06 ?489次閱讀
    一種常用<b class='flag-5'>嵌入式</b>開發(fā)<b class='flag-5'>代碼</b>庫(kù)

    嵌入式系統(tǒng)工業(yè)4.0網(wǎng)絡(luò)安全

    CC++在嵌入式系統(tǒng)占主導(dǎo)地位。多年來(lái),實(shí)施工業(yè)4.0和物聯(lián)網(wǎng)的組織已經(jīng)認(rèn)識(shí)所有代碼
    的頭像 發(fā)表于 08-12 21:45 ?491次閱讀
    <b class='flag-5'>嵌入式</b>系統(tǒng)<b class='flag-5'>中</b>工業(yè)4.0網(wǎng)絡(luò)安全

    如何提升嵌入式編程能力?

    :掌握嵌入式系統(tǒng)的基本原理,包括中斷、并發(fā)、實(shí)時(shí)操作、低功耗設(shè)計(jì)等。 3. 實(shí)踐編程:通過(guò)實(shí)際編寫和測(cè)試代碼來(lái)提高技能。從簡(jiǎn)單的LED閃爍程序開始,逐步過(guò)渡到更復(fù)雜的項(xiàng)目,如定時(shí)器PWM應(yīng)用、串口、IIC
    發(fā)表于 06-21 10:01

    如何成為一名嵌入式C語(yǔ)言高手?

    。 三、通過(guò)實(shí)踐項(xiàng)目提升技能理論知識(shí)是建立在實(shí)踐基礎(chǔ)之上的。選擇一些小型的嵌入式項(xiàng)目,例如LED閃爍、溫度監(jiān)測(cè)等簡(jiǎn)單的應(yīng)用,將所學(xué)的C語(yǔ)言知識(shí)應(yīng)用到實(shí)際。通過(guò)實(shí)踐,你可以了解如何將
    發(fā)表于 04-07 16:03

    如何成為一名嵌入式C語(yǔ)言高手?

    。 三、通過(guò)實(shí)踐項(xiàng)目提升技能理論知識(shí)是建立在實(shí)踐基礎(chǔ)之上的。選擇一些小型的嵌入式項(xiàng)目,例如LED閃爍、溫度監(jiān)測(cè)等簡(jiǎn)單的應(yīng)用,將所學(xué)的C語(yǔ)言知識(shí)應(yīng)用到實(shí)際。通過(guò)實(shí)踐,你可以了解如何將
    發(fā)表于 03-25 14:12

    嵌入式fpga是什么意思

    嵌入式FPGA是指將FPGA技術(shù)集成嵌入式系統(tǒng)的一種解決方案。嵌入式系統(tǒng)是一種為特定應(yīng)用而設(shè)計(jì)的計(jì)算機(jī)系統(tǒng),它通常包括處理器、內(nèi)存、外設(shè)
    的頭像 發(fā)表于 03-15 14:29 ?1272次閱讀

    給大家講講嵌入式系統(tǒng)I2C總線的時(shí)序

    I2C總線在嵌入式系統(tǒng)很常見,今天就來(lái)給大家講講I2C總線的時(shí)序。
    的頭像 發(fā)表于 02-23 09:47 ?1684次閱讀
    給大家講講<b class='flag-5'>嵌入式</b>系統(tǒng)<b class='flag-5'>中</b>I2<b class='flag-5'>C</b>總線的時(shí)序

    嵌入式學(xué)習(xí)-ElfBoard ELF 1開發(fā)板-共創(chuàng)官學(xué)習(xí)筆記分享|將Go程序編譯ELF 1開發(fā)板

    ElfBoard組建的共創(chuàng)社是嵌入式科技創(chuàng)新與學(xué)習(xí)實(shí)踐的前沿陣地,我們有幸見證著每一位共創(chuàng)官積極投身于嵌入式技術(shù)的熱潮,用實(shí)際行動(dòng)詮釋著探索精神。今天就跟各位小伙伴分享一下共創(chuàng)官是怎樣將Go
    發(fā)表于 02-21 10:22

    嵌入式學(xué)習(xí)步驟

    硬件組件。 (4).開發(fā)固件:編寫嵌入式系統(tǒng)的固件,這是嵌入式系統(tǒng)的軟件部分。固件負(fù)責(zé)控制硬件并執(zhí)行特定任務(wù)。 (5).調(diào)試和測(cè)試:在將嵌入式系統(tǒng)部署實(shí)際環(huán)境
    發(fā)表于 02-02 15:24

    聊一聊嵌入式C語(yǔ)言

    作為一名嵌入式軟件開發(fā)者,熟練掌握嵌入式C語(yǔ)言對(duì)我的日常工作至關(guān)重要。
    的頭像 發(fā)表于 01-22 09:28 ?554次閱讀

    嵌入式自學(xué)好書推薦

    嵌入式自學(xué)好書推薦 在數(shù)字時(shí)代的浪潮嵌入式系統(tǒng)一直是數(shù)字電子產(chǎn)品的重要組成部分。無(wú)論是家用電器、工業(yè)控制、汽車電子、醫(yī)療保健、軍事應(yīng)用還是物聯(lián)網(wǎng),
    發(fā)表于 01-11 15:13
    主站蜘蛛池模板: 午夜色在线| 天天久久影视色香综合网| 1024手机看片日韩| 国产精品好好热在线观看| 国产午夜毛片一区二区三区| 国产高清小视频| 免费黄色大片视频| 午夜网站免费| 99久久精品免费看国产| 亚洲精品亚洲人成人网| 特级毛片aaa免费版| 人人澡人| 黄色网毛片| 站长工具天天爽视频| 51视频在线观看免费国产| 69色视频| 男女交性特一级| 亚洲人成网站色在线观看| 四虎成人免费网站在线| 欧美日韩精品一区二区在线线| 久久婷婷综合五月一区二区| www.激情五月.com| 日本一本一道久久香蕉免费| 99久久伊人一区二区yy5099| 亚洲视频在线观看一区| 中文字幕在线天堂| 日本三级免费| 性欧美高清强烈性视频| 三级黄色网址| 黄色网毛片| 午夜激情福利| 午夜视频高清在线aaa| 看片在线观看免费| 69日本人xxxx16-18| 欧美精品激情| 国产精品午夜自在在线精品| 四虎4hu| 久久这里只有精品免费视频| 97久久综合九色综合| 国产又大又黄又粗又爽| 求av网址|