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

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

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

Cortex-M反編譯入門

嵌入式大雜燴 ? 來源:嵌入式大雜燴 ? 作者:嵌入式大雜燴 ? 2023-05-01 01:22 ? 次閱讀

我們在寫單片機裸機程序時,在主函數(shù)之前,會有一段啟動代碼,而啟動代碼是用匯編寫的,有些朋友可能看到匯編頭都大了,當(dāng)時要想深入研究底層架構(gòu),這快硬骨頭就必須去啃。

匯編 :匯編文件轉(zhuǎn)換為目標(biāo)文件(里面是機器碼)。

反匯編 :可執(zhí)行文件(目標(biāo)文件,里面是機器碼),轉(zhuǎn)換為匯編文件。

關(guān)于匯編的基礎(chǔ)知識,請看筆者以前的文章。

今天筆者以STM32F1的點燈程序為例,帶領(lǐng)大家進行反匯編,并閱讀反匯編后的代碼。

1 新建LED裸機程序

關(guān)于STM32裸機程序的創(chuàng)建,請看筆者博文:

https://bruceou.blog.csdn.net/article/details/78244735

但是今天這個程序非常簡單,不應(yīng)那么復(fù)雜。

1.新建文件夾

新建文件夾“STM32F1”,當(dāng)然名字也可以另取,在 STM32F1文件夾下,我們新建五個文件夾,分別為CMSIS、Listing、Output、Project、User。

1682861784044ce1xngvdb1

其中CMSIS文件夾放啟動文件:

1682861784745y77tys7nql

筆者的開發(fā)板芯片是STM32F103ZE,這個文件是根據(jù)STM32的固件庫startup_stm32f10x_md.s文件修改而來。

2.新建工程

打開Keil,在工具欄 Project->New μVision Project…新建我們的工程文件。

1682861785045yci29v8yep

輸入工程名,保存即可。

1682861785347ejt3txvtdg

窗口是讓我們選擇公司跟芯片的型號,我們用的芯片是 ST 公司的STM32F103ZE,有64K SRAM,512K Flash,屬于高集成度的芯片。按如下選擇即可。

1682861785701fybynmt941

然后點擊項目管理。

16828617860678xirkyf7u2

最后修改后的內(nèi)容如下:

168286178659146c097dxaa

并添加相應(yīng)的文件。

1682861786890i3ruwx50xk

其中main.c的內(nèi)容如下所示:

/**
  * @brief  延時函數(shù)
  * @param  d
  * @retval None
  */
void delay(int d)
{
    while(d--);
}

/**
  * @brief  main
  * @param  None
  * @retval int
  */
int main(void)
{
    unsigned int *pReg;
    
    /* 使能GPIOB */
    pReg = (unsigned int *)(0x40021000 + 0x18);
    *pReg |= (1<<3);
    
    /* 設(shè)置GPIOB0為輸出引腳 */
    pReg = (unsigned int *)(0x40010C00 + 0x00);
    *pReg |= (1<<0);

    pReg = (unsigned int *)(0x40010C00 + 0x0C);
    
    while (1)
    {
        /* 設(shè)置GPIOB0輸出1 */
        *pReg |= (1<<0);
        
        delay(1000000);

        /* 設(shè)置GPIOB0輸出0 */
        *pReg &= ~(1<<0);
        
        delay(1000000);
    }
}

startup.s文件的內(nèi)容如下:

;************************************ STM32F1 ************************************
;* File Name          : startup.s
;* Author             : BruceOu
;* Version            : V1.0
;* Date               : 2021-06-27
;* Description        : STM32F10x Medium Density Devices vector table for MDK-ARM 
;*                      toolchain.  
;*                      This module performs:
;*                      - Set the initial SP
;*                      - Set the initial PC == Reset_Handler
;*                      - Set the vector table entries with the exceptions ISR address
;*                      - Configure the clock system
;*                      - Branches to __main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the CortexM3 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.
;*******************************************************************************
                PRESERVE8
                THUMB


; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY
				EXPORT  __Vectors
					
__Vectors       DCD     0                  
                DCD     Reset_Handler              ; Reset Handler

				AREA    |.text|, CODE, READONLY

; Reset handler
Reset_Handler   PROC
				EXPORT  Reset_Handler             [WEAK]
                IMPORT  main

				LDR SP, =(0x20000000+0x10000)
				BL main

                ENDP 
                
                END

接下來還有配置工程。

16828617871720kp1099zbj

選擇Output文件夾。

1682861787441yb2iav40ku

選擇Listing文件夾。

168286178774709w1fbwxlj

基本配置就這些,接下來編譯工程。

1682861788115kc6kgvwaat

只要沒有錯誤就可以了,最后就是下載程序,筆者使用的是J-Link,最后的現(xiàn)象如下:

1682861788425ht484axtbw

LED會不停閃爍。

2 Keil反匯編

接下來才是今天正題,反匯編。

在KEIL的User選項中,如下圖添加這兩項:

fromelf --bin --output=STM32F1.bin ../Output/STM32F1.axf

fromelf --text -a -c --output=STM32F1.dis ../Output/STM32F1.axf

然后重新編譯,即可得到二進制文件STM32F1.bin(以后會分析)、反匯編文件STM32F1.dis。

如下圖所示:

1682861788915ugsuzllsu3

正常編譯過程是分為四個階段進行的,即預(yù)處理(也稱預(yù)編譯,Preprocessing)、編譯(Compilation)、匯編 (Assembly)和鏈接(Linking)。

但是反編譯是講為二進制文件反編譯成匯編文件,因此反匯編的流程如下:

1682861789194tjjboqezsx

3 反匯編代碼解析

接下來就是查看反編譯代碼,打開反編譯文件Project/STM32F1.dis。這里只截取一段查看,因為格式都是一樣的,知識每條內(nèi)容不同罷了。

C:\\Users\\BruceOu\\Desktop\\20210628222656.png

第一列是鏈接地址,第二列是機器碼,第三列是匯編指令。

根本匯編指令,我們找到ARM?v7-M Architecture Reference Manual_DDI 0403E.d (ID070218)中的LDR指令。

1682861789789h0yw0lt7wp

我們將F8DFD004變成二進制。

1682861790181wc7gex8qa6

這個使用的32位的Thumb2指令集。

16828617907087x3urvsswf

其中b0~b11是立即數(shù),這里是4,對應(yīng)的匯編代碼的也是4,這里要注意的是,ARM指令采用流水線機制,當(dāng)前執(zhí)行地址A的指令,同時已經(jīng)在對下一條指令進行譯碼同時已經(jīng)在讀取下下一條指令:PC = A +4 (Thumb/Thumb2指令集)。

1682861791012zlh0i8hbkk

B12~b15是寄存器,這段大小是0XC,對應(yīng)的寄存器就是sp;

1682861791382rgl1c89djy

后面16bit除了23位意外,全是固定的,其中‘U’表示無條件執(zhí)行,這里置為1。

其他的匯編指令對應(yīng)的機器碼也是類似的,值得注意的是,不同的架構(gòu)對應(yīng)的機器碼也是不同的,這也就回答了為了不同的處理器架構(gòu)會對應(yīng)不同的指令集。

有興趣的可以對比Cortex-M系列和Cortex-A系列的的指令集。請參考以下手冊:

ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.pdf

ARM?v7-M Architecture Reference Manual.pdf

4 反匯編代碼全解析

進入debug模式,在View下選擇disassembly window。

1682861791732udl87y2hkk

這樣就可將機器碼和對應(yīng)的代碼對應(yīng)起來。當(dāng)程序運行起來了,也就從異常向量表中跳轉(zhuǎn)到Reset_Handler中,然后跳轉(zhuǎn)到main函數(shù)中,而main函數(shù)是在棧中,因此需要設(shè)置占空間的起始位置。根據(jù)STM32的參考手冊,SRAM的其起始地址和大小如下:

1682861792161laj05ypw17

因此棧頂為起始位置加上棧的大小即可,只要不超過SRAM即可。

1682861792494kvv8rmggr9

值得注意的是,棧是__向低地址擴展的數(shù)據(jù)結(jié)構(gòu)__,是一塊連續(xù)的內(nèi)存區(qū)域,棧頂?shù)牡刂泛蜅5淖畲笕萘渴窃谕ㄟ^LDR設(shè)置,因此需要根據(jù)應(yīng)用需求合理分配??臻g。

接下來往下走,如果在匯編中不打斷點,會默認(rèn)進入main函數(shù)的一條指令,就從這里分析。為了分析方便,這里還有使用上一節(jié)方便出來的文件。

1682861792854yx7buaxbnh

168286179328181dgh7q884

【C代碼33行】

從內(nèi)存地址0x0800 017c拷貝數(shù)據(jù)0x40021018到r3中,也就是

r3 = * 0x0800 017c

也就是將pReg指針保存到r3中。

1682861793680n54j8yfcae

【C代碼34行】

這里對應(yīng)3條指令

168286179399049x6zh3xs2

首先將r3拷貝到r0中,然后將r0或上1左移3位,也就是

ORR r0,r0,#8

最后將r0的值寫入r3所指地址中。

【C代碼37行】

同33行,從內(nèi)存地址0x0800 0180拷貝數(shù)據(jù)40010c00到r3中

1682861794278a3l8unid93

【C代碼38行】

同34行,這里也對應(yīng)3條指令:

1682861794643xsiexuccee

【C代碼40行】

和33行不同的是,這里分了兩條指令:

1682861794920c8o1lnkcmn

筆者認(rèn)為前面是編譯器優(yōu)化了。根據(jù)ARM指令采用流水線機制,當(dāng)前執(zhí)行地址A的指令,同時已經(jīng)在對下一條指令進行譯碼同時已經(jīng)在讀取下下一條指令:PC = A +4 (Thumb/Thumb2指令集)。因此前面類似的代碼被優(yōu)化了。

接下來就進入循環(huán)中。

1682861795209ylxlhden5n

后面就移植在死循環(huán)中,不斷操作GPIO的亮滅。

【C代碼45行】

這里是將B0設(shè)置為1,和34行類似。

1682861795497jylbjwsdjc

【C代碼47行】

這里將進入延時函數(shù)。

1682861795758qdjan7453d

進入延時函數(shù):

1682861796046vsclfk8ad3

NOP是字節(jié)對齊,減少指令的內(nèi)存訪問次數(shù)。首先將變量d保存到r0,然后將r0賦給r1,接著是r0自減1,緊接著是r1與0比較,如果r1等于0,則會返回,否則,又從頭開始,值得注意的是,這里先比較,然后r0才自減的。

為了進一步說明,可以看--d的匯編代碼。

1682861796329nl965tt4jm

這里就是相當(dāng)于r1先減1,然后再比較的。

【C代碼50行】

這行代碼對應(yīng)一下指令,很簡單。

1682861796601o6xh8txu3q

5 總結(jié)

在前面使用Keil進行了反匯編,也對相應(yīng)的C代碼進行了分析。我們看到的反匯編代碼如下:

C:\\Users\\BruceOu\\Desktop\\20210630233351.png

根據(jù)反匯編的代碼,可將其對應(yīng)到Flash,在Flash上的內(nèi)容如下表所示:

地址 Flash****內(nèi)容
0x08000000 00000000
0x08000004 08000009
0x08000008 f8dfd004
0x0800000c f000f80c

最后總結(jié)下點燈的流程:

第一步:設(shè)置棧CPU會從0x08000000讀取值,用來設(shè)置SP。

第二步:跳轉(zhuǎn) :CPU從0x08000004得到地址值,根據(jù)它的BIT0切換為ARM狀態(tài)或Thumb狀態(tài),然后跳轉(zhuǎn)。

__第三步:__對于cortex M3/M4,它只支持Thumb狀態(tài),所以0x08000004上的值bit0必定是1,0x08000004上的值 = Reset_Handler + 1。從Reset_Handler繼續(xù)執(zhí)行。

第四步 :然后進入到主函數(shù)中執(zhí)行相應(yīng)C代碼。

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

    關(guān)注

    6030

    文章

    44489

    瀏覽量

    631998
  • 匯編
    +關(guān)注

    關(guān)注

    2

    文章

    214

    瀏覽量

    25890
  • 編譯
    +關(guān)注

    關(guān)注

    0

    文章

    649

    瀏覽量

    32775
  • 反編譯
    +關(guān)注

    關(guān)注

    1

    文章

    14

    瀏覽量

    8503
  • Cortex-M
    +關(guān)注

    關(guān)注

    2

    文章

    227

    瀏覽量

    29708
收藏 人收藏

    評論

    相關(guān)推薦

    為什么說Cortex-M是低功耗應(yīng)用的首選

    雖然Cortex-M處理器家族目標(biāo)瞄準(zhǔn)效能光譜較低端的區(qū)域,但是和大多數(shù)微控制器(MCU)采用的其他典型處理器相比,Cortex-M的效能依然算相當(dāng)強悍。舉例來說,像是許多高效能微控制器所采用的Cortex-M4與
    發(fā)表于 07-28 09:44 ?3453次閱讀
    為什么說<b class='flag-5'>Cortex-M</b>是低功耗應(yīng)用的首選

    Cortex-M入門資料和書籍分享

    Cortex-M入門在網(wǎng)上看博客逛論壇也是能學(xué)到些東西的,但通常是知識點,不能構(gòu)成知識面。書籍通常會系統(tǒng)性地講述,通過書籍可以建立起知識面,只有建立起了知識面才算是掌握。推薦兩本書:《ARM
    發(fā)表于 07-01 09:38

    Cortex-M內(nèi)核的GCC編譯

    下載ARM官方對應(yīng)Cortex-M內(nèi)核的GCC編譯
    發(fā)表于 08-24 06:44

    Android反編譯工具

    Android反編譯工具
    發(fā)表于 12-17 15:59 ?21次下載

    【ARM白皮書】ARM Cortex-M處理器入門

    ARM Cortex-M處理器家族現(xiàn)在有8款處理器成員。在本文中,會比較Cortex-M系列處理器之間的產(chǎn)品特性,重點講述如何根據(jù)產(chǎn)品應(yīng)用選擇正確的Cortex-M處理器。本文中會詳細(xì)的對照C
    發(fā)表于 04-20 15:34 ?39次下載

    Atmel Studio 6軟件中如何調(diào)試ARM Cortex-M

    Atmel Studio 6軟件中如何調(diào)試ARM Cortex-M
    的頭像 發(fā)表于 07-04 10:49 ?4205次閱讀

    關(guān)于STM32和Cortex-M內(nèi)核系列介紹(1)

    Cortex-M內(nèi)核系列和STM32-講座
    的頭像 發(fā)表于 07-05 01:07 ?7987次閱讀

    關(guān)于STM32與Cortex-M內(nèi)核系列的介紹(2)

    Cortex-M內(nèi)核系列和STM32-講座3
    的頭像 發(fā)表于 07-05 00:45 ?4491次閱讀

    關(guān)于Cortex-M 調(diào)試應(yīng)用的介紹

    Cortex-M 調(diào)試應(yīng)用
    的頭像 發(fā)表于 07-10 00:56 ?2580次閱讀

    米爾科技Cortex-M Prototyping System +介紹

    ARM? Cortex?-M原型系統(tǒng) MPS2+,為Cortex-M 系列微處理器設(shè)計的原型驗證評估系統(tǒng),包含最新的Cortex-M7 及Corte
    的頭像 發(fā)表于 11-14 10:45 ?1825次閱讀
    米爾科技<b class='flag-5'>Cortex-M</b> Prototyping System +介紹

    Cortex-M內(nèi)核的MPU內(nèi)存保護單元

    講講Cortex-M內(nèi)核的MPU內(nèi)存保護單元
    的頭像 發(fā)表于 03-04 11:17 ?3598次閱讀
    <b class='flag-5'>Cortex-M</b>內(nèi)核的MPU內(nèi)存保護單元

    Cortex-M可以跑Linux操作系統(tǒng)嗎?

    Cortex-M可以跑Linux操作系統(tǒng)嗎?
    發(fā)表于 12-01 11:36 ?2次下載
    <b class='flag-5'>Cortex-M</b>可以跑Linux操作系統(tǒng)嗎?

    no cortex-m sw device found 問題解決【轉(zhuǎn)】

    no cortex-m sw device found 問題解決【轉(zhuǎn)】
    發(fā)表于 12-02 17:36 ?33次下載
    no <b class='flag-5'>cortex-m</b> sw device found 問題解決【轉(zhuǎn)】

    【專欄精選】Cortex-M反編譯入門

    做電子發(fā)燒友技術(shù)探索官,分享你的原創(chuàng)電子行業(yè)文章! 本期為大家推薦一篇嵌入式相關(guān)技術(shù)文章,作者主要從事嵌入式領(lǐng)域的開發(fā),感興趣的小伙伴可以關(guān)注學(xué)習(xí)哦~ 本期推 薦 專欄作者 : 嵌入式大雜燴 (點擊查看作者主頁) 介紹:該專欄主要介紹嵌入式開發(fā)相關(guān)的知識,與大家一起交流學(xué)習(xí)。 ?? 我們在寫 單片機 裸機程序時,在主函數(shù)之前,會有一段啟動代碼,而啟動代碼是用 匯編 寫的,有些朋友可能看到匯編頭都大了,當(dāng)時要想深入研究底層
    的頭像 發(fā)表于 05-16 09:35 ?1363次閱讀

    Cortex-M位帶操作的原理

    Cortex-M位帶操作的原理
    的頭像 發(fā)表于 10-24 15:27 ?815次閱讀
    <b class='flag-5'>Cortex-M</b>位帶操作的原理