1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        編譯器如何處理函數(shù)的調(diào)用

        共 2445字,需瀏覽 5分鐘

         ·

        2024-05-22 07:33


                


        概要

        網(wǎng)上對(duì)函數(shù)調(diào)用未做系統(tǒng)化分析,本文主要根據(jù)匯編,寄存器,堆棧,map,內(nèi)存4個(gè)角度進(jìn)行分析,在函數(shù)進(jìn)行調(diào)用的時(shí)候,編譯器做什么工作進(jìn)行舉例分析;

        環(huán)境介紹

        函數(shù)流程如下:
        1)串口輸入指令;
        2)中斷調(diào)用接口uint16_t getUartData(void);
        3)getUartData 中調(diào)用了shell_cmd_parse接口;從開始調(diào)用shell_cmd_parse進(jìn)行講解,即下圖斷電位置;

        步驟

        斷點(diǎn)位置(2800行),寄存器分析如下:

        1)寄存器

        由于示例采用的是多進(jìn)程方式,調(diào)用getUartData前的接口可能是任何一個(gè)函數(shù),故【R0-R12】寄存器的值不確定,上圖【R0-R12】值無(wú)特別意義;

        SP為當(dāng)前堆棧地址0x20008948

        LR為調(diào)用getUartData前地址,查詢.map文件可知,getUartData運(yùn)行完成返回parseIni接口

        PC為當(dāng)前程序運(yùn)行地址0x801B3BC,查看.map文件可知為當(dāng)前函數(shù)getUartData里面某個(gè)位置(圖1中打印斷電的地方)

        觀察Diassembly窗口,程序即將運(yùn)行的兩步

        MOV r1,r4 r4getUartData函數(shù)中存放局部變量debug_rcv_len=0x8E)賦值給r1;


        LDR r0,[PC,#116]    PC+116地址中的值給到r0,其中最終結(jié)果為0x801B434,對(duì)應(yīng)PC=0x801B3C0,比指令LDR r0,[PC,#116]PC2,原因時(shí)流水線的問題(3級(jí)流水線導(dǎo)致,取值和運(yùn)行同時(shí)進(jìn)行會(huì)導(dǎo)致計(jì)算的時(shí)候PC已經(jīng)+2);

            注:地址0x801B343存的就是全局變量debugUartRcvData的值,查詢.map可知,該值在代碼中RO數(shù)據(jù)段;查詢Memory1可知其具體的值為0x20017EE0;

        單步Step(F11)進(jìn)入函數(shù)shell_cmd_parse,進(jìn)入后如下圖所示

        變化的值有四個(gè)[R0][R1][LR][PC]

        [R0]:變?yōu)楹瘮?shù)shell_cmd_parse(unsigned char *puc_buf, uint16_t us_len)形參puc_buf(=0x20017EE0);

        [R1]:形參us_len=0x8E

        [LR]:執(zhí)行完shell_cmd_parse后需要返回的地址,為圖1斷點(diǎn)處地址(0x801B3BC+8=0x801B3C5;

        [PC]:0x08029A18,查詢.map可知,在函數(shù)shell_cmd_parse開頭

        3)查看Disassembly窗口,如下圖所示

        1、現(xiàn)場(chǎng)保護(hù):

        保護(hù)LR,即將函數(shù)執(zhí)行完的后需要返回的地址0x801B3C5,如下圖,即代碼執(zhí)行完shell_cmd_parse后下一行代碼memset(debugUartRcvData,0,sizeof(debugUartRcvData))位置;

        保護(hù)R4-R11寄存器中的值,這些值為調(diào)用shell_cmd_parse的函數(shù)getUartData需要保護(hù)的值,譬如R4存放了getUartData局部變量debug_rcv_len的值;

        2、堆棧向下偏移由0x20008948-偏移4*r4-r11,lr9=0x2008924


        查詢堆棧數(shù)據(jù),Memory1

        0x20008948-0x20008924依次存放LR=0x0801B3C5R11=0xA5A5A5A5, R10=0xA5A5A5A5, R9=0xA5A5A5A5, R8=0xA5A5A5A5, R7=0xA5A5A5A5, R6=0xA5A5A5A5, R5=0x00000000, R4=0x0000008E,

        3、將r0,r1(函數(shù)shell_cmd_parse的形參,puc_buf,us_len的值共2個(gè))保存到寄存器r7r8中。

        4、為shell_cmd_parse分配堆棧大小

        5、查看分配后堆棧,一次性分配好0xA4=164=40*4+4,分配了40個(gè)char*[](即指針數(shù)組,共40個(gè)char*指針)+一個(gè)地址的空間(endstart存放在了r4寄存器里面,剩下的放到堆棧里面);

        6、局部變量及堆棧使用情況如下圖

        7、堆棧溢出底層原理,當(dāng)指令輸出長(zhǎng)度過長(zhǎng),pac_argv發(fā)生越界訪問時(shí),可通過查詢堆棧發(fā)現(xiàn),數(shù)據(jù)對(duì)原本保護(hù)的數(shù)據(jù),譬如LR指針發(fā)生變化,導(dǎo)致出現(xiàn)hard fault程序跑飛現(xiàn)象;



        春招已經(jīng)開始啦,大家如果不做好充足準(zhǔn)備的話,春招很難找到好工作。


        送大家一份就業(yè)大禮包,大家可以突擊一下春招,找個(gè)好工作!


        瀏覽 82
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            社区操逼视频 | 97人人操人人干 | 人人操天天摸 | 成人免费视频 观看 | 男女做事网站 | 久久网成人片一区二区香港A片 | 久久免费看片 | 绝顶小早川熟绝顶アナル狂い | 欧美黑人一级视频 | 大鸡巴操逼网站 |