国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

ARM Cortex—M0+機(jī)器碼文件分析方法

2017-07-25 07:19蔡伯峰蔣建武王宜懷
現(xiàn)代電子技術(shù) 2017年14期

蔡伯峰+蔣建武+王宜懷

摘 要: MCU深層次應(yīng)用開發(fā)需要開發(fā)人員深入了解機(jī)器碼在MCU中的存儲(chǔ)和執(zhí)行機(jī)制,但機(jī)器碼自身可讀性差、相互關(guān)系不清晰等特點(diǎn)決定了對(duì)其閱讀、查找、分析難度較大。針對(duì)這一情況,以采用ARM Cortex?M0+內(nèi)核的KL25 MCU為藍(lán)本,根據(jù)工程編譯鏈接過程和鏈接腳本文件(.ld),分析機(jī)器碼文件的生成機(jī)制和組織結(jié)構(gòu)。在此基礎(chǔ)上針對(duì)機(jī)器碼文件中的中斷向量表、初始化代碼、函數(shù)、常變量、FLASH配置域等主要內(nèi)容,結(jié)合機(jī)器碼系列文件,給出了簡(jiǎn)明快捷實(shí)用的分析方法,為嵌入式開發(fā)人員優(yōu)化及動(dòng)態(tài)更新程序和數(shù)據(jù)、設(shè)計(jì)機(jī)器碼下載軟件等提供支撐,對(duì)其他內(nèi)核機(jī)器碼文件的分析有借鑒意義。

關(guān)鍵詞: ARM Cortex?M0+; 機(jī)器碼文件; KL25; 鏈接腳本

中圖分類號(hào): TN918.2?34; TP311 文獻(xiàn)標(biāo)識(shí)碼: A 文章編號(hào): 1004?373X(2017)14?0044?05

Abstract: MCU deep?level application development requires its developers to understand storage and enforcement mechanisms of machine codes in MCU, but the machine code itself has poor readability and unclear structure, thus it is difficult to be directly read, searched and analyzed. In response to this situation, using the ARM Cortex?M0+ KL25 MCU as a model, and according to engineering compiling linking process and linker script files (.ld) of MCU application project, the generative mechanism and structure of machine code file are analyzed. On this basis, a concise, efficient and practical analysis method is given in allusion to the interrupt vector table, initialization code, functions, constants, variables and Flash configuration domain. This is helpful for the embedded developers to update dynamically and optimize programs and data, design machine code download software, and analyze machine code files of other kernels.

Keywords: ARM Cortex?M0+; machine?code file; KL25; linker script

0 引 言

用C語言開發(fā)的MCU應(yīng)用工程經(jīng)過編譯鏈接后生成機(jī)器碼目標(biāo)文件,正確全面深入地掌握機(jī)器碼文件的分析方法是快速進(jìn)行MCU深層次應(yīng)用開發(fā)必備的技能。機(jī)器碼文件要通過機(jī)器碼下載軟件下載到目標(biāo)板上芯片的FLASH存儲(chǔ)區(qū)中運(yùn)行,下載軟件一般需要開發(fā)人員自行設(shè)計(jì),因?yàn)镵DS(Kinetis Design Studio)等集成開發(fā)環(huán)境提供的下載方法在脫離開發(fā)環(huán)境后無法使用,不便于產(chǎn)品的批量生產(chǎn);而在程序正常運(yùn)行后,有時(shí)需要?jiǎng)討B(tài)在線更新或升級(jí)部分程序和數(shù)據(jù),如濾波算法程序、排序算法程序、系統(tǒng)參數(shù)等;嵌入式系統(tǒng)的存儲(chǔ)資源與通用計(jì)算機(jī)系統(tǒng)相比,相對(duì)匱乏、速度較低,對(duì)實(shí)時(shí)性、可靠性要求較高[1],需要根據(jù)實(shí)際情況動(dòng)態(tài)修改或優(yōu)化程序和數(shù)據(jù)等。這一切都需要開發(fā)人員對(duì)機(jī)器碼文件有充分的了解,能正確深入地分析機(jī)器碼文件,了解程序數(shù)據(jù)的存儲(chǔ)和執(zhí)行機(jī)制、芯片復(fù)位啟動(dòng)過程、程序執(zhí)行時(shí)間等芯片底層內(nèi)容。但不同廠家不同內(nèi)核的指令機(jī)器碼存在差異,應(yīng)用工程的機(jī)器碼文件結(jié)構(gòu)和組成也不相同,分析方法也不盡相同,目前有關(guān)ARM Cortex?M0+內(nèi)核機(jī)器碼文件的系統(tǒng)性分析研究很少。機(jī)器碼自身可讀性差、相互關(guān)系不清晰、不符合通常思維習(xí)慣等特點(diǎn)決定了由其組成的機(jī)器碼文件閱讀、理解和分析困難,為此,要有正確實(shí)用的分析機(jī)制和分析方法。

本文在深入剖析機(jī)器碼文件的生成機(jī)制、組織結(jié)構(gòu)的基礎(chǔ)上,結(jié)合機(jī)器碼系列文件,給出了簡(jiǎn)明快捷的分析方法。

1 機(jī)器碼文件的生成

MCU應(yīng)用工程在編譯鏈接工程中會(huì)使用一些文件,并生成若干文件,只有了解這些文件的生成過程、相互關(guān)系、功能作用等內(nèi)容才能全面準(zhǔn)確地分析機(jī)器碼文件。

1.1 MCU程序編譯鏈接過程

KDS集成開發(fā)環(huán)境下,對(duì)任一用C語言開發(fā)的MCU應(yīng)用工程,運(yùn)行Cross ARM GCC編譯器,會(huì)經(jīng)過如圖1所示的編譯、匯編和鏈接等過程。

MCU應(yīng)用工程往往包含若干源代碼文件(.c)(也包含需要快速執(zhí)行的匯編程序.S),每個(gè)源代碼文件在編譯、匯編后都會(huì)生成一個(gè)可重定位的二進(jìn)制目標(biāo)文件(.o)[2](本文稱之為中間文件),再通過ld鏈接器根據(jù)鏈接腳本文件(.ld)的內(nèi)部相關(guān)規(guī)則將這些中間文件鏈接組合成針對(duì)ARM CPU的.elf格式的可執(zhí)行目標(biāo)文件[3]。如果程序調(diào)用了靜態(tài)庫(.a)中的函數(shù)或變量,鏈接時(shí)還會(huì)包括相應(yīng)的庫文件。在編譯鏈接過程中,還可同時(shí)生成機(jī)器碼文件(.hex)、映像文件(.map)、列表文件(.lst)。

1.2 鏈接腳本文件的使用

鏈接腳本文件(.ld)提供給鏈接器控制鏈接過程,用于重定位代碼并提供程序、數(shù)據(jù)在內(nèi)存中的存儲(chǔ)位置[4?5]。它規(guī)定如何將各個(gè)中間文件中的段(稱為輸入段)放入可執(zhí)行目標(biāo)文件中合適的段(稱為輸出段)中,并控制目標(biāo)文件內(nèi)各部分的地址分配。它主要由MEMORY,SECTIONS命令組成[6]。首先通過MEMORY命令劃分FLASH和RAM存儲(chǔ)空間可用資源區(qū)為多個(gè)存儲(chǔ)區(qū),并定義各存儲(chǔ)區(qū)的起始地址及長(zhǎng)度、設(shè)置讀寫或執(zhí)行等屬性。再通過SECTIONS命令定義一些可供應(yīng)用程序使用的符號(hào)并賦值、包含在可執(zhí)行目標(biāo)文件中的各個(gè)輸出段及裝載到哪個(gè)存儲(chǔ)區(qū)。在各個(gè)輸出段中定義一些與該段相關(guān)的一些符號(hào)并賦值,同時(shí)確定該段應(yīng)該由哪些中間文件的哪些輸入段如何鏈接而成。

以 KL25_UART應(yīng)用工程為例,該工程運(yùn)行于本課題組自行設(shè)計(jì)的基于KL25(NXP公司的MKL25Z128VLK4)的開發(fā)板上,用于測(cè)試串口與PC機(jī)間通信情況。KL25[7]包含128 KB FLASH,16 KB SRAM。FLASH分成128扇區(qū),每扇區(qū)1 024 KB。MEMORY和SECTIONS命令所定義的各存儲(chǔ)區(qū)、包含的輸出段及存儲(chǔ)器空間分配情況如圖2所示。共定義4個(gè)存儲(chǔ)區(qū):中斷向量區(qū)“m_interrupts”、FLASH配置區(qū)“m_flash_config”、用戶程序區(qū)“m_text”和數(shù)據(jù)區(qū)“m_text”。前3個(gè)區(qū)在FLASH(本文稱為目標(biāo)FLASH)中,數(shù)據(jù)區(qū)在SRAM中。其中,“m_text”區(qū)中的.text段定義如下:

.text:

{ . = ALIGN(4); /*4 B的邊界對(duì)齊*/

*(.text) /*非函數(shù)代碼*/

*(.text.*) /*函數(shù)代碼*/

*(.rodata) /*字符串等*/

*(.rodata.*) /*數(shù)組常量等*/

} > m_text

鏈接腳本文件可由開發(fā)人員根據(jù)MCU應(yīng)用工程的程序、數(shù)據(jù)所需空間大小及存放要求、鏈接要求等自行編寫或由開發(fā)環(huán)境生成后修改。

1.3 機(jī)器碼系列文件的生成

可執(zhí)行目標(biāo)文件(.elf)的生成依賴于鏈接腳本文件和各個(gè)中間文件。當(dāng)源文件被編譯成中間文件時(shí),其中的各輸入段并沒有具體地址,中間文件中只是記錄了程序中所使用的各個(gè)符號(hào)和各符號(hào)在輸入段中的相對(duì)位置。只有當(dāng)鏈接器根據(jù)鏈接腳本文件鏈接中間文件的各個(gè)輸入段時(shí),各段才會(huì)根據(jù)鏈接腳本文件中所分配的地址獲得加載內(nèi)存地址LMA和虛擬內(nèi)存地址VMA[8],各個(gè)符號(hào)也才有了真實(shí)地址。再根據(jù)每一符號(hào)所對(duì)應(yīng)的真實(shí)地址更新相應(yīng)的指令,從而實(shí)現(xiàn)真正的函數(shù)調(diào)用和符號(hào)引用功能。通過這一重定位過程就可生成可執(zhí)行目標(biāo)文件(.elf)。

因?yàn)榭蓤?zhí)行目標(biāo)文件是二進(jìn)制文件,包含程序開始執(zhí)行地址、程序頭、輸出段頭、符號(hào)表、各個(gè)輸出段、重定位信息以及調(diào)試和說明信息等并需專門工具軟件打開,可讀性差、分析不便,不是本文分析研究的對(duì)象。本文所要分析的機(jī)器碼文件是指由可執(zhí)行目標(biāo)文件在KDS下經(jīng)格式轉(zhuǎn)換而生成的機(jī)器碼文件(.hex)。它是由十六進(jìn)制文本組成的ASCII碼文件,已經(jīng)包含可執(zhí)行目標(biāo)文件中的程序入口地址、各個(gè)輸出段等主要內(nèi)容,可讀性和結(jié)構(gòu)清晰度均較好,分析比較方便。而可執(zhí)行目標(biāo)文件中的其他內(nèi)容也已經(jīng)包含在KDS下生成的列表文件(.lst)和映像文件(.map)中。

映像文件提供了鏈接腳本文件中所定義的各個(gè)符號(hào)的地址值和各個(gè)輸入輸出段的長(zhǎng)度及LMA,VMA地址映射信息。列表文件提供了程序開始執(zhí)行地址、程序頭、輸出段頭、符號(hào)表,以及“C代碼、匯編代碼、機(jī)器碼及存儲(chǔ)地址”的對(duì)應(yīng)關(guān)系及LMA、常量數(shù)據(jù)等內(nèi)容,用于程序分析。

2 機(jī)器碼文件組織結(jié)構(gòu)分析

機(jī)器碼文件(.hex)存放了中斷向量表、FLASH配置域信息、程序機(jī)器碼、常量、初始化了的靜態(tài)變量和全局變量、程序入口地址等內(nèi)容,可直接使用串行線調(diào)試(Serial Wire Debug,SWD)技術(shù)通過下載程序下載到目標(biāo)MCU中運(yùn)行,比通過USBDM外部調(diào)試接口下載.elf文件方便、快捷。

機(jī)器碼文件是由若干行符合Intel HEX文件格式的十六進(jìn)制文本所構(gòu)成的ASCII文本文件,文件每一行均是一條HEX記錄,記錄分成6種不同類型,但記錄格式均相同,如表1所示。

本文以KL25_UART應(yīng)用工程的KL25_UART.hex為例進(jìn)行分析,文件內(nèi)容如圖3所示。記錄中的偏移量表示當(dāng)前記錄中“數(shù)據(jù)/信息區(qū)”的有效數(shù)據(jù)在裝載到目標(biāo)FLASH中時(shí)的偏移地址,也只有這些數(shù)據(jù)才會(huì)被裝載到目標(biāo)FLASH中,它們?cè)贔LASH中以小端方式(KL25 MCU內(nèi)部采用的存儲(chǔ)方式[4],即字的低字節(jié)存儲(chǔ)在低地址中)依次存放。

圖3中“數(shù)據(jù)/信息區(qū)”的內(nèi)容簡(jiǎn)要分析如下:

(1) 中斷向量表。存放于第1~12行的記錄中。KL25有48個(gè)中斷向量,每個(gè)中斷向量占4 B,每條記錄可存放4個(gè)中斷向量,共占用12條記錄。裝載到目標(biāo)FLASH中時(shí),中斷向量表將會(huì)從偏移地址是“0x0000”處開始存放,占用(4×12)×4=192 B。

(2) FLASH配置域。存放于第13行記錄中, 固定長(zhǎng)度為16 B,在目標(biāo)FLASH中的偏移地址是“0x0400”。

(3) 程序和常量。存放于第14~209行中,在目標(biāo)FLASH中的偏移地址是“0x0800”。

(4) 靜態(tài)變量及全局變量。緊接著上述機(jī)器碼程序和常量后是已初始化為非0的靜態(tài)變量及全局變量,數(shù)據(jù)長(zhǎng)度因應(yīng)用工程而異。它們也會(huì)裝載到目標(biāo)FLASH中,斷電后數(shù)據(jù)不會(huì)丟失。復(fù)位啟動(dòng)時(shí)初始化程序會(huì)將它們拷貝到RAM中。

(5) 其他內(nèi)容。機(jī)器碼文件倒數(shù)第2行固定為存放程序開始執(zhí)行地址的記錄,記錄類型為“0x03”,最后一行固定為文件結(jié)束記錄,記錄類型為“0x01”。

3 機(jī)器碼文件內(nèi)容分析

雖然機(jī)器碼文件本身提供的信息量有限,但結(jié)合.ld,.lst、,map等系列文件提供的編譯鏈接和裝載等信息,就可以全面分析該文件,以深入了解中斷向量表、芯片復(fù)位啟動(dòng)過程、FLASH加密解密機(jī)制、代碼及數(shù)據(jù)的鏈接方法、定位、裝載和運(yùn)行地址、空間占用情況、執(zhí)行時(shí)間、符號(hào)的處理等內(nèi)容。

3.1 中斷向量表定位與分析

中斷向量表位于機(jī)器碼文件的開始處,將直接裝載到目標(biāo)FLASH的0x00000000地址處。因?yàn)楦鶕?jù)芯片內(nèi)部工作機(jī)制,中斷向量表應(yīng)存放于目標(biāo)FLASH的0x00000000地址處即第0扇區(qū),當(dāng)MCU上電啟動(dòng)或復(fù)位時(shí),將從該處取出4 B的第一表項(xiàng)內(nèi)容賦給堆棧指針SP,完成堆棧指針初始化工作,取出4 B的第二表項(xiàng)內(nèi)容賦給程序計(jì)數(shù)器PC,以便轉(zhuǎn)到相應(yīng)地址處執(zhí)行芯片復(fù)位處理代碼。中斷向量表占用的空間依賴于具體MCU的中斷源數(shù)量,就目前市場(chǎng)上的MCU而言,最多占用1個(gè)扇區(qū),在扇區(qū)大小是1 024 KB的情況下,1個(gè)扇區(qū)可以存放=256個(gè)中斷向量,即使扇區(qū)大小是512 KB也可以存放128個(gè)中斷向量。

中斷向量表中各個(gè)中斷向量對(duì)應(yīng)的是符號(hào)值、0(表示未用)或中斷處理函數(shù)名或弱函數(shù)名,在編譯鏈接并重定位時(shí),鏈接器會(huì)將這些符號(hào)、函數(shù)名、弱函數(shù)名更新為相應(yīng)的符號(hào)值、函數(shù)、弱函數(shù)或?qū)?yīng)的強(qiáng)函數(shù)的虛擬內(nèi)存地址VMA(即運(yùn)行地址)。

中斷向量表一般在芯片啟動(dòng)文件(.s)中定義,啟動(dòng)文件的內(nèi)容結(jié)構(gòu)[9]如圖4所示。

在KL25芯片啟動(dòng)文件定義的中斷向量表中,序號(hào)為0的中斷向量是__StackTop(棧頂?shù)刂贩?hào)),序號(hào)為1的中斷向量是Reset_Handler(芯片復(fù)位處理函數(shù)),序號(hào)為29的中斷向量是UART1_IRQHandler弱函數(shù),并在中斷處理源文件中定義了對(duì)應(yīng)的強(qiáng)函數(shù)。圖3中序號(hào)為0的中斷向量4字節(jié)組“00 30 00 20”實(shí)際表示的數(shù)據(jù)是“20 00 30 00”,正是_StackTop的值。序號(hào)為1的中斷向量4字節(jié)組“01 08 00 00”→“00 00 08 01”,其內(nèi)容減1后的值正是Reset_Handler函數(shù)的VMA,也是程序開始執(zhí)行地址。內(nèi)容減1是因?yàn)镵L25的Cortex?M0+處理器的指令地址為半字對(duì)齊,即PC寄存器的最低位必須始終為0,但程序在跳轉(zhuǎn)時(shí),PC的最低位必須被置為1,以表明內(nèi)核處于執(zhí)行16位Thumb指令的Thumb狀態(tài),而非執(zhí)行32位指令的ARM狀態(tài)[10]。序號(hào)為29的中斷向量4字節(jié)組“ED 08 00 00”→“00 00 08 ED”,其內(nèi)容減1后的值正是UART1_IRQHandler強(qiáng)函數(shù)的VMA。從KL25_UART.map或intflash.ld文件中可以查到_StackTop和Reset_Handler,UART1_IRQHandler等函數(shù)的VMA正是這些值。

進(jìn)而根據(jù)中斷處理函數(shù)的VMA就可在機(jī)器碼文件中相應(yīng)的偏移地址(=中斷處理函數(shù)的VMA-0x00000000)處查找到其機(jī)器碼。

3.2 FLASH配置域定位與分析

FLASH配置域在機(jī)器碼文件中緊接著中斷向量表后存放,記錄中的偏移量對(duì)應(yīng)的是目標(biāo)FLASH第一扇區(qū)的開始地址。由于FLASH保護(hù)和加解密功能需擦除整個(gè)第一扇區(qū),所以該扇區(qū)剩余的空間保留著,當(dāng)不用FLASH保護(hù)和加解密功能時(shí)可以存放機(jī)器碼數(shù)據(jù)。

FLASH配置域保存了默認(rèn)的FLASH保護(hù)設(shè)定及加密屬性,用于對(duì)FLASH模塊進(jìn)行訪問控制,以防止某些FLASH存儲(chǔ)區(qū)域受意外擦除、寫入,或通過外部調(diào)試接口(如JTAG,SWD和USBDM等)訪問FLASH存儲(chǔ)器,但加密后通過外部調(diào)試接口仍可進(jìn)行大規(guī)模的擦除操作,只是無法執(zhí)行讀取或?qū)懭隖LASH的指令。在芯片復(fù)位時(shí),F(xiàn)LASH模塊讀取FLASH配置域相應(yīng)字段信息對(duì)FLASH保護(hù)寄存器FPROT 和加密寄存器FSEC進(jìn)行初始化。FLASH配置域信息如表2所示,相關(guān)寄存器內(nèi)容可見文獻(xiàn)[7]。

開發(fā)者可直接對(duì)FLASH配置域字段進(jìn)行改寫(先擦除整個(gè)扇區(qū),再?gòu)?fù)位芯片后寫入)以啟用/關(guān)閉加密功能,或使用封裝的加密解密函數(shù)來對(duì)配置域進(jìn)行設(shè)置,但前者操作簡(jiǎn)單直接且更為安全。

3.3 MCU初始化代碼定位與分析

MCU應(yīng)用程序機(jī)器碼區(qū)包括芯片初始化代碼、各個(gè)函數(shù)代碼、常量、初始化為非0的靜態(tài)和全局變量等,位于機(jī)器碼文件中緊接著FLASH配置域后,首條記錄中的偏移量對(duì)應(yīng)的是目標(biāo)FLASH第二扇區(qū)的開始地址。應(yīng)用工程不同,記錄條數(shù)和機(jī)器碼長(zhǎng)度也不相同。由于中斷向量表第二表項(xiàng)存放的是MCU初始化函數(shù)Reset_Handler的VMA,所以只要計(jì)算出偏移地址(=Reset_Handler函數(shù)的VMA-0x00000000),就可方便地在機(jī)器碼文件中查找到Reset_Handler函數(shù)的機(jī)器碼。圖3中Reset_Handler函數(shù)的機(jī)器碼從記錄中偏移量是0x0800處(第14行記錄)開始存放。通過查看KL25_UART.lst文件可知,該處的機(jī)器碼“72 B6 00 F0…”→“B6 72 F0 00…”對(duì)應(yīng)的是芯片啟動(dòng)文件的Reset_Handler函數(shù),共占0x44 B,初始化過程見圖4。弄清MCU初始化過程后,在實(shí)際應(yīng)用中,就可根據(jù)是否要啟動(dòng)看門狗、是否要復(fù)制中斷向量表至RAM、是否要清零未初始化.bss段、啟動(dòng)時(shí)間、是否添加監(jiān)控程序等要求來編寫或修改、優(yōu)化相關(guān)代碼,以提高系統(tǒng)的穩(wěn)定性、可靠性、靈活性。監(jiān)控程序可添加在進(jìn)入main函數(shù)之前的位置處,以判斷是否有要寫入機(jī)器碼到FLASH中的命令,若有則完成寫入,這是更新用戶程序的一種簡(jiǎn)便方法。

3.4 函數(shù)和功能段的定位與分析

在C函數(shù)代碼編譯成匯編指令時(shí),編譯器自動(dòng)在函數(shù)開始處添加push指令以保存函數(shù)被調(diào)用時(shí)的現(xiàn)場(chǎng),如push{r7, lr},函數(shù)結(jié)束處自動(dòng)添加pop指令以恢復(fù)現(xiàn)場(chǎng),如pop{r7, pc}。其機(jī)器碼高位字節(jié)分別為B5,BD,低位字節(jié)與指令中使用的寄存器相關(guān),在存儲(chǔ)時(shí)機(jī)器碼是半字對(duì)齊并采用小端格式。這樣就可根據(jù)B5,BD來定位函數(shù)。

(1) 用戶函數(shù)及ISR的定位。若某一存儲(chǔ)單元的內(nèi)容為“B5”且其偏移地址的最低位為1,則從該存儲(chǔ)單元的上一單元開始表示某個(gè)函數(shù)開始。其后第一個(gè)“BD”所在的存儲(chǔ)單元(其偏移地址的最低位必須為1)表示該函數(shù)結(jié)束。找出函數(shù)機(jī)器碼后就可直接計(jì)算其占用的存儲(chǔ)空間字節(jié)數(shù),更加便捷的方法是查詢.lst文件中的符號(hào)表。

(2) 某個(gè)特定函數(shù)的定位。由于機(jī)器碼文件中沒有函數(shù)名,所以要定位特定名稱的某個(gè)函數(shù)需要借助于.lst文件進(jìn)行,即根據(jù).lst文件中提供的“C代碼、匯編代碼、機(jī)器碼及存儲(chǔ)地址”部分的內(nèi)容,找到該函數(shù)的前幾個(gè)機(jī)器碼字節(jié),從而就可在機(jī)器碼文件中定位到函數(shù)的開始部分。

(3) 相鄰存儲(chǔ)的兩函數(shù)之間的數(shù)據(jù)歸屬。如果函數(shù)中使用了字符串常數(shù)、數(shù)組常量、靜態(tài)和全局變量等數(shù)據(jù),那么它們的VMA地址將會(huì)存放到該函數(shù)最后。函數(shù)中的指令先通過相對(duì)尋址方式,從PC值與指令中給出的偏移量相加后形成的操作數(shù)地址所指向的存儲(chǔ)單元中取出VMA地址,再通過獲得的VMA地址訪問到所需數(shù)據(jù)。其余常量直接轉(zhuǎn)換成指令中的立即數(shù)存放于機(jī)器碼中。

(4) 功能段的定位。特定的C語言功能段代碼對(duì)應(yīng)的機(jī)器碼可以直接在.lst文件中查找到,據(jù)此就可在機(jī)器碼文件中定位,并可很方便地計(jì)算其占用的存儲(chǔ)空間字節(jié)數(shù)。計(jì)算執(zhí)行時(shí)間時(shí)可根據(jù)對(duì)應(yīng)的匯編指令及內(nèi)核參考手冊(cè)上提供的指令執(zhí)行周期進(jìn)行精確計(jì)算[11]。

定位到函數(shù)或功能段后就可修改其代碼,或動(dòng)態(tài)在線更新目標(biāo)FLASH中的相應(yīng)代碼。要實(shí)現(xiàn)動(dòng)態(tài)更新功能,可以在編程時(shí)在main的永久循環(huán)中添加監(jiān)控代碼,以判斷是否有要寫入機(jī)器碼到FLASH中的命令,若有則完成寫入。

3.5 常量、靜態(tài)和全局變量的定位與分析

字符串常數(shù)、數(shù)組常量等在機(jī)器碼文件中的存放位置取決于.ld文件中對(duì).text段的定義,在本文中,它們集中存放于機(jī)器碼的后面,而其余常量將其值以立即數(shù)形式直接存放于指令中。要確定某個(gè)特定常量的存放位置,可從.lst文件的最后內(nèi)容中先查找到該常量的存放地址,再到機(jī)器碼文件中精確定位。

根據(jù)鏈接腳本文件,未初始化或初始化為0的靜態(tài)和全局變量存放于RAM中.data段后的.bss內(nèi)存區(qū)域中,但.bss段不占機(jī)器碼文件空間和目標(biāo)FLASH空間,只占運(yùn)行時(shí)的RAM空間。而.data段中包含的初始化為非0的靜態(tài)和全局變量占用機(jī)器碼文件空間、目標(biāo)FLASH空間和運(yùn)行時(shí)的RAM空間,斷電后初始化數(shù)據(jù)能保存。

在機(jī)器碼文件中,初始化為非0的靜態(tài)和全局變量緊接著機(jī)器碼和常量的后面存放。從.lst文件中可以查看到它們的LMA和占用空間,據(jù)此可在機(jī)器碼文件中精確定位到特定的變量,并可計(jì)算出FLASH剩余空間的起始地址。定位到常量、靜態(tài)和全局變量后,可根據(jù)需要修改其值或通過監(jiān)控程序動(dòng)態(tài)在線更新目標(biāo)FLASH中的相應(yīng)值。FLASH剩余空間可用于存放其他數(shù)據(jù),如系統(tǒng)參數(shù)等,同樣可實(shí)現(xiàn)動(dòng)態(tài)在線更新。

4 結(jié) 語

本文在對(duì)ARM Cortex?M0+機(jī)器碼文件的生成機(jī)制、組織結(jié)構(gòu)和內(nèi)容進(jìn)行深入剖析的基礎(chǔ)上,結(jié)合機(jī)器碼系列文件提供的信息,系統(tǒng)地給出了中斷向量表、FLASH配置域、初始化代碼、函數(shù)和常量、全局或靜態(tài)變量等內(nèi)容在機(jī)器碼文件中的定位與分析方法,使得對(duì)機(jī)器碼文件的分析變得簡(jiǎn)明快捷。開發(fā)人員可以將分析結(jié)果應(yīng)用于MCU深層次應(yīng)用開發(fā)工作中,如編寫或修改鏈接腳本文件及芯片復(fù)位啟動(dòng)程序、精確計(jì)算代碼執(zhí)行時(shí)間和占用的存儲(chǔ)空間、添加監(jiān)控代碼、優(yōu)化及動(dòng)態(tài)更新程序和數(shù)據(jù)、設(shè)計(jì)機(jī)器碼下載軟件等,以充分利用MCU有限的資源,提高系統(tǒng)的可靠性、穩(wěn)定性、健壯性。

參考文獻(xiàn)

[1] 廉玉龍,史崢,李春強(qiáng),等.基于C.SKY CPU的地址立即數(shù)編譯優(yōu)化方法[J].計(jì)算機(jī)工程,2016,42(1):46?50.

[2] 胡宗棠,王宜懷,沈忱.面向MC1321X的低開銷無線重編程機(jī)制的研究與設(shè)計(jì)[J].計(jì)算機(jī)應(yīng)用與軟件,2014,31(12):272?277.

[3] 王宜懷,朱仕浪,郭蕓.嵌入式技術(shù)基礎(chǔ)與實(shí)踐[M].3版.北京:清華大學(xué)出版社,2013:86?87.

[4] STANKIC M, CETIC N, KRNJETIN M, et al. Graphical tool for generating linker configuration files in embedded systems [C]// Proceedings of 2011 19th Telecommunications Forum. [S.l.: s.n.], 2011: 1550?1553.

[5] ARM. Armlink user guide [DB/OL]. (2016?03?31) [2016?05?15]. http://infocenter.arm.com/help/.

[6] Free Software Foundation. Documentation for binutils 2.26 [DB/OL]. (2016?01?25) [2016?05?15]. https://sourceware.org/binutils/docs?2.26/ld/.

[7] NXP. KL25 Sub?family reference manual [DB/OL]. (2014?09?01) [2016?05?15]. http://www.nxp.com/.

[8] 胡敏,盧永江,劉兵.基于CK810處理器的匯編鏈接時(shí)優(yōu)化[J].計(jì)算機(jī)工程,2014,40(11):250?254.

[9] NXP. Kinetis assembler reference manual [DB/OL]. (2014?02?01) [2016?05?15]. http://www.nxp.com/.

[10] JOESEP Yiu.ARM?Cortex?M0權(quán)威指南[M].吳常玉,譯.北京:清華大學(xué)出版社,2013:52?53.

[11] ARM. Cortex?M0+ Processor technical reference manual [DB/OL]. (2012?12?16) [2016?05?15]. http://infocenter.arm.

遂溪县| 金阳县| 肃南| 栾城县| 邻水| 华安县| 尼勒克县| 榕江县| 临猗县| 襄樊市| 惠州市| 安岳县| 商洛市| 高尔夫| 娱乐| 高阳县| 徐水县| 英吉沙县| 满城县| 大石桥市| 乌兰浩特市| 枞阳县| 达拉特旗| 耿马| 吉首市| 饶河县| 台北市| 景德镇市| 盐山县| 新乡市| 闻喜县| 鹰潭市| 昆明市| 富裕县| 萍乡市| 屯昌县| 永嘉县| 鄂州市| 廉江市| 大冶市| 松滋市|