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

?

ARM Cortex-M0+機(jī)器碼系列文件分析及應(yīng)用研究

2019-01-10 00:56:22蔡伯峰王宜懷
關(guān)鍵詞:靜態(tài)程序函數(shù)

蔡伯峰, 王宜懷

(1. 蘇州大學(xué)計(jì)算機(jī)科學(xué)與技術(shù)學(xué)院, 江蘇 蘇州 215006; 2. 泰州職業(yè)技術(shù)學(xué)院信息技術(shù)學(xué)院, 江蘇 泰州 225300)

0 引言

MCU應(yīng)用工程經(jīng)編譯鏈接后會(huì)生成機(jī)器碼文件等系列文件, 其中機(jī)器碼文件須下載到開(kāi)發(fā)板MCU的Flash存儲(chǔ)區(qū)中投入運(yùn)行. 與通用計(jì)算機(jī)系統(tǒng)相比, 嵌入式系統(tǒng)的存儲(chǔ)資源較匱乏且速度低, 但對(duì)實(shí)時(shí)性、 可靠性的要求卻較高[1-2], 所以在MCU程序數(shù)據(jù)占用空間和執(zhí)行時(shí)間上要精心設(shè)計(jì)、 盡量?jī)?yōu)化, 尤其對(duì)功能復(fù)雜耗費(fèi)較多資源的MCU應(yīng)用工程更是如此. 為此就要充分了解程序和數(shù)據(jù)存儲(chǔ)機(jī)制與空間分配情況、 MCU啟動(dòng)和程序執(zhí)行過(guò)程、 程序執(zhí)行時(shí)間等信息, 并有比較方便實(shí)用的計(jì)算空間占用和執(zhí)行時(shí)間的方法, 以便修改或優(yōu)化相關(guān)配置文件、 程序和數(shù)據(jù)等. 但目前有關(guān)機(jī)器碼系列文件分析及應(yīng)用的系統(tǒng)性研究較少. 本研究全面地分析機(jī)器碼系列文件并綜合運(yùn)用所得的信息來(lái)分析MCU啟動(dòng)過(guò)程, 提出計(jì)算程序數(shù)據(jù)占用空間和執(zhí)行時(shí)間的簡(jiǎn)明快捷的方法.

1 MCU應(yīng)用工程編譯鏈接后的系列生成文件

任一MCU應(yīng)用工程往往都包含.c、 .S等多個(gè)源代碼文件, 它們由KDS(kinetis design studio)開(kāi)發(fā)環(huán)境中集成的Cross ARM GCC編譯器, 依次通過(guò)預(yù)編譯、 編譯、 匯編等一系列過(guò)程, 生成相應(yīng)的多個(gè)中間文件——可重定位目標(biāo)文件.o. 再由集成的鏈接器根據(jù)開(kāi)發(fā)人員編寫的鏈接腳本文件.ld中的相關(guān)規(guī)則, 將這些.o文件和所調(diào)用的函數(shù)或變量所在的靜態(tài)鏈接庫(kù)一起鏈接組合成針對(duì)ARM 內(nèi)核的格式為.elf的可執(zhí)行目標(biāo)文件, 以及機(jī)器碼文件.hex、 列表文件.lst、 映像文件.map. 其中格式為.elf的文件可通過(guò)USBDM等方式下載到目標(biāo)MCU中運(yùn)行.

2 機(jī)器碼系列文件分析

本研究所要分析的機(jī)器碼系列文件包括.hex、 .lst、 .map文件. .elf文件是二進(jìn)制文件且包含大量調(diào)試和說(shuō)明信息, 需要專門工具軟件打開(kāi), 可讀性差、 分析困難. .hex文件是在KDS下由.elf文件經(jīng)格式轉(zhuǎn)換而成的文件, 它是十六進(jìn)制文本組成的ASCII碼文件, 并包含.elf文件中的主要內(nèi)容如程序入口地址和各個(gè)輸出段等, 結(jié)構(gòu)較清晰且可讀性好, 分析方便, 而.elf文件中的其他內(nèi)容已包含在.lst和.map文件中, 因此本研究所稱的機(jī)器碼文件指.hex文件. 為了能對(duì)機(jī)器碼系列文件進(jìn)行方便、 準(zhǔn)確的分析, 還須借助于鏈接腳本文件.

2.1 鏈接腳本文件

控制鏈接過(guò)程用的鏈接腳本文件.ld主要用于鏈接時(shí)重定位代碼和提供數(shù)據(jù)在內(nèi)存中的存儲(chǔ)位置, 它規(guī)定如何將來(lái)自中間文件的輸入段放入最終.elf文件的匹配輸出段中, 并控制各部分地址分配. 以NXP公司的KL25Z128為例, 它包含F(xiàn)LASH128KB、 SRAM16KB, 其鏈接腳本文件intflash.ld包含的與程序、 數(shù)據(jù)安排相關(guān)內(nèi)容及分析列于表1.

表1 鏈接腳本文件簡(jiǎn)明分析

MEMORY命令定義并劃分Flash和RAM存儲(chǔ)空間可用資源區(qū), 設(shè)置其讀寫、 執(zhí)行等屬性. SECTIONS命令包括符號(hào)量賦值語(yǔ)句和輸出段描述語(yǔ)句, 前者定義供各個(gè)文件使用的符號(hào)量, 后者定義包含在各個(gè)區(qū)中的所有輸出段, 并確定每個(gè)輸出段在最終目標(biāo)文件中應(yīng)該由哪些中間文件的哪些輸入段構(gòu)成.

.ld文件可由開(kāi)發(fā)人員根據(jù)實(shí)際MCU應(yīng)用工程程序和數(shù)據(jù)對(duì)空間的需求情況、 鏈接的具體要求等進(jìn)行編寫或先由KDS開(kāi)發(fā)環(huán)境生成后再行修改.

2.2 映像文件分析

映像文件.map提供了查看代碼、 常量、 靜態(tài)變量、 全局變量、 堆棧等存放的起始地址和空間占用信息, 但指定的地址是動(dòng)態(tài)分配的, 隨應(yīng)用工程改動(dòng)而發(fā)生相應(yīng)變化.

文件內(nèi)容主要包括: 1)應(yīng)用工程未使用的各中間文件中的輸入段和函數(shù)、 常量、 靜態(tài)變量、 全局變量的空間占用信息, 形如“.group 0x00000000 0x8 gpio.o”. 2)Flash和RAM存儲(chǔ)空間可用資源區(qū)配置信息, 包括m_interrupts、 m_flash_config、 m_text、 m_data及默認(rèn)存儲(chǔ)區(qū)起始地址、 空間大小和讀寫屬性, 形如“m_text 0x00000800 0x0001f7ff xr”. 3)鏈接腳本, 包括鏈接的各中間文件和靜態(tài)庫(kù)文件名, 形如“LOAD main.o”. 4)應(yīng)用工程實(shí)際使用的各中間文件中的輸入段和函數(shù)、 常量、 靜態(tài)變量、 全局變量的存儲(chǔ)空間分配信息, 包括在鏈接腳本文件各SECTIONS命令所定義的符號(hào)量的值和輸出段描述語(yǔ)句所涉及到的各中間文件中各輸入段、 函數(shù)、 常量、 靜態(tài)變量、 全局變量等占用的存儲(chǔ)空間起始地址及長(zhǎng)度, 形如“.text.UART0_IRQHandler 0x0000084c 0x8 isr.o”. 對(duì)于數(shù)據(jù)段、 堆和棧, 存儲(chǔ)空間起始地址指運(yùn)行時(shí)的虛擬內(nèi)存地址VMA在裝載時(shí), 數(shù)據(jù)段、 堆和棧被裝載到Flash存放代碼段之后的空間中, 裝載地址是LMA. 5)輸出到.elf中來(lái)自各中間文件的調(diào)試段存放的起始地址和占用空間信息, 形如“.debug_info 0x000000b1 0xf6 main.o”.

2.3 列表文件分析

列表文件.lst提供了存儲(chǔ)空間分配情況、 所有符號(hào)信息及機(jī)器碼、 匯編代碼、 源代碼之間的對(duì)應(yīng)關(guān)系, 用于程序分析.

文件內(nèi)容主要包括: 1)存儲(chǔ)在Flash中的MCU程序執(zhí)行開(kāi)始地址, 形如“start address 0x00000801”; 2)程序頭(形如“LOAD off 0x000000b4 vaddr 0x00000000 paddr 0x00000000 align 2**2”和“filesz 0x000000c0 memsz 0x000000c0 flags r--”)及輸出段信息(形如“interrupts 000000c0 00000000 00000000 000000b4 2**2 CONTENTS, ALLOC, LOAD, READONLY, DATA”), 包括各輸出段在最終目標(biāo)文件中存放的偏移地址和占用空間、 輸出段VMA和LMA、 輸出段占用的存儲(chǔ)器空間和讀寫等屬性、 地址對(duì)齊方式; 3)符號(hào)表, 包含目標(biāo)文件中所有符號(hào)信息: 符號(hào)名、 使用范圍(指全局、 局部、 弱函數(shù))、 符號(hào)類型(指段名d、 文件名df、 函數(shù)名F、 常量/靜態(tài)變量/全局變量O、 符號(hào)量)、 所屬段、 鏈接地址(指鏈接器給符號(hào)編排的VMA地址)和占用空間, 形如“1ffff000 g .text 00000000 __data_start__”; 4)MCU程序?qū)嶋H使用或調(diào)用的各函數(shù)源代碼對(duì)應(yīng)的匯編代碼、 機(jī)器碼及在m_text區(qū)中的存儲(chǔ)地址, 形如“86c:2314 movs r3, #20”; 5)常量存儲(chǔ)地址及值, 形如“d40: 40049000 4004a000 4004b000 4004c000”.

2.4 機(jī)器碼文件分析

機(jī)器碼文件.hex提供了中斷向量表、 機(jī)器碼及常量, 以及初始化了的靜態(tài)變量和全局變量, 通過(guò)SWD等方式下載到目標(biāo)MCU中運(yùn)行, 用于代替通過(guò)USBDM方式下載的.elf文件. .hex是十六進(jìn)制文本文件, 由多行符合Intel HEX文件格式的文本構(gòu)成, 其中每一行為一條HEX記錄. 記錄分成6種類型, 但記錄格式相同, 每個(gè)記錄格式均包括1B的開(kāi)始標(biāo)記“:”、 1B的數(shù)據(jù)區(qū)長(zhǎng)度、 2B的偏移量(裝載到存儲(chǔ)空間的偏移地址, 對(duì)非數(shù)據(jù)記錄為0000)、 1B的記錄類型(00-數(shù)據(jù)記錄, 01-文件結(jié)束記錄, 02-擴(kuò)展段地址, 03-開(kāi)始段地址, 04-擴(kuò)展線性地址, 05-鏈接開(kāi)始地址)、nB的數(shù)據(jù)/信息區(qū)(機(jī)器碼、 常量、 靜態(tài)變量和全局變量初始值、 地址等)、 1B的校驗(yàn)和.

圖1 KL25_UART工程生成的.hex文件部分記錄Fig.1 Partial records of KL25_UART.hex file

現(xiàn)以KL25_UART應(yīng)用工程生成的.hex文件為例分析, 該應(yīng)用工程用于測(cè)試KL25 開(kāi)發(fā)板串口與PC機(jī)間通信情況, 其.hex文件的部分內(nèi)容見(jiàn)圖1.

根據(jù)鏈接腳本文件對(duì)存儲(chǔ)區(qū)的劃分, 中斷向量表存放在Flash存儲(chǔ)區(qū)的開(kāi)始區(qū)域, 起始地址為“00000000”, 每個(gè)向量占4字節(jié). 根據(jù)芯片啟動(dòng)文件startup_MKL25Z4.S對(duì)中斷向量表的定義, 序號(hào)0中斷向量是__StackTop(即棧頂?shù)刂罚?符號(hào)量), 序號(hào)1中斷向量是Reset_Handler(即芯片復(fù)位處理函數(shù)), 序號(hào)29中斷向量是UART1_IRQHandler(即UART1模塊中斷處理函數(shù))等等. 在Flash存儲(chǔ)區(qū)的中斷向量區(qū)中存儲(chǔ)的是這些符號(hào)量或函數(shù)的鏈接地址即起始地址, 從.ld和.map文件中可以查到__StackTop、 Reset_Handler、 UART1_IRQHandler的值或函數(shù)的鏈接地址, 在本研究中分別為0x20003000、 0x00000800、 0x000008EC.

圖1從第1行到12行是中斷向量表記錄, 數(shù)據(jù)/信息區(qū)中每4字節(jié)代表一個(gè)中斷向量. 第1行記錄中的“:10”表示記錄以“:”開(kāi)始, 長(zhǎng)度為“0x10”; 接下來(lái)的“0000”是偏移地址, 表示數(shù)據(jù)在裝載到Flash中時(shí)將從偏移地址為“0000”處開(kāi)始存放; 緊接著的“00”代表該記錄為“數(shù)據(jù)記錄”類型; 接著是具體機(jī)器碼數(shù)據(jù)“0030002001080000 4508000045080000”, 該數(shù)據(jù)裝載到Flash中以小端方式(KL25 MCU內(nèi)部采用的存儲(chǔ)方式, 即字的低字節(jié)存儲(chǔ)在低地址中)依次存放, 記錄中只有這些數(shù)據(jù)才會(huì)被裝載到Flash存儲(chǔ)區(qū)中. 其中, 第1個(gè)4字節(jié)組“00 30 00 20”實(shí)際表示的數(shù)據(jù)是“20 00 30 00”, 即__StackTop. 第2個(gè)“01 08 00 00”→“00 00 08 01”, 其內(nèi)容減1的值就是Reset_Handler鏈接地址, 也是程序開(kāi)始執(zhí)行地址. 在MCU啟動(dòng)時(shí)會(huì)被裝入PC寄存器中, 內(nèi)容減1是因?yàn)镵L25的Cortex-M0+處理器的指令地址為半字對(duì)齊, 即PC寄存器的最低位必須始終為0, 但程序在跳轉(zhuǎn)時(shí), PC的最低位必須被置為1, 以表明內(nèi)核仍處于thumb狀態(tài), 而非ARM狀態(tài). 最后的“FD”為校驗(yàn)和. 其余4字節(jié)組減1后的值為對(duì)應(yīng)中斷向量號(hào)的中斷處理函數(shù)的鏈接地址.

第13行是Flash配置域. 從第14行到第208行是程序?qū)?yīng)的機(jī)器碼(含常量), 因?yàn)楦鶕?jù).lst文件, .text段的LMA=0x00000800, 再根據(jù).ld文件對(duì).text段的定義, 在.text中將依次存放非函數(shù)代碼、 函數(shù)代碼、 字符串和數(shù)組常量等. 根據(jù).lst文件中的.data段的LMA=0x00001428可知, 第209行裝載的是初始化過(guò)的靜態(tài)變量及全局變量值. 第210行是程序開(kāi)始執(zhí)行的地址“00 00 08 00”(減1后). 第211行(最后一行)為文件結(jié)束記錄, 記錄類型為“0x01”.

由上述分析可知, 常量、 已初始化的靜態(tài)變量和全局變量的值集中存放在機(jī)器碼的后面, 這樣將會(huì)與機(jī)器碼一起裝載到MCU的Flash中, 掉電后不會(huì)丟失. 而根據(jù)鏈接腳本文件.ld, 未初始化的靜態(tài)變量和全局變量將存放在RAM中.data段后的.bss區(qū)域, 但.bss段不占用機(jī)器碼文件和目標(biāo)Flash空間, 只占用運(yùn)行時(shí)的RAM. 當(dāng)上電啟動(dòng)后, 在Reset_Handler函數(shù)(見(jiàn)后文分析)中將靜態(tài)變量和全局變量的值拷貝到RAM的VMA處, 而在RAM中操作數(shù)據(jù)讀寫速度很快, 同時(shí)清零.bss段. 這也使得程序和數(shù)據(jù)占用的空間不能超過(guò)Flash容量, 數(shù)據(jù)和堆棧占用的空間不能超過(guò)RAM容量, 堆棧用于中斷處理函數(shù)及其他函數(shù)調(diào)用時(shí)的現(xiàn)場(chǎng)保存、 局部變量存放、 程序中間結(jié)果存放等, 在設(shè)置堆棧大小時(shí)要予以考慮.

3 機(jī)器碼系列文件分析的實(shí)際應(yīng)用

通過(guò)綜合運(yùn)用.ld、 .lst、 .map及 .hex等機(jī)器碼系列文件, 除可了解程序數(shù)據(jù)鏈接方法與過(guò)程、 函數(shù)的機(jī)器碼及存放地址、 常變量的裝載內(nèi)存地址、 虛擬內(nèi)存地址、 符號(hào)的處理方法外, 還可分析芯片上電啟動(dòng)過(guò)程并理解程序的執(zhí)行過(guò)程、 計(jì)算程序占用空間和執(zhí)行時(shí)間等.

3.1 在分析MCU上電或復(fù)位過(guò)程中的應(yīng)用

根據(jù)機(jī)器碼系列文件內(nèi)容和MCU內(nèi)部工作機(jī)制, 可以分析出從MCU復(fù)位到main函數(shù)之前的程序執(zhí)行過(guò)程.

1) MCU上電或復(fù)位后, 其內(nèi)部機(jī)制會(huì)從Flash的0x00000000地址處, 取出中斷向量表第一表項(xiàng)內(nèi)容賦給堆棧指針SP, 完成堆棧指針初始化工作. 第一表項(xiàng)內(nèi)容正是.hex文件中第1行的第1個(gè)中斷向量, 為棧頂?shù)刂?

2) MCU內(nèi)部機(jī)制將第二表項(xiàng)內(nèi)容, 賦給程序計(jì)數(shù)器PC. 第二表項(xiàng)內(nèi)容正是.hex文件中第1行的第2個(gè)中斷向量, 為Reset_Handler函數(shù)的鏈接地址, 本研究是0x00000800, 因而執(zhí)行.hex的第14行中的機(jī)器碼, 機(jī)器碼存儲(chǔ)在Flash的偏移地址是0x0800而實(shí)際地址是0x00000000+0x0800開(kāi)始的存儲(chǔ)區(qū), 通過(guò)查看.lst可知. 該機(jī)器碼對(duì)應(yīng)于startup_MKL25Z4.S文件中的Reset_Handler函數(shù): 關(guān)總中斷、 調(diào)用SystemInit()函數(shù)關(guān)閉看門狗并初始化系統(tǒng)時(shí)鐘、 開(kāi)總中斷、 將ROM中的已初始化的靜態(tài)變量和全局變量的值拷貝到RAM中、 清零未初始化.bss段、 進(jìn)入用戶主函數(shù)main.

弄清啟動(dòng)執(zhí)行過(guò)程后, 實(shí)際應(yīng)用中, 就可根據(jù)是否要開(kāi)啟看門狗、 復(fù)制中斷向量表至RAM、 清零未初始化BSS數(shù)據(jù)段等要求修改優(yōu)化相關(guān)代碼, 以進(jìn)一步提高系統(tǒng)的擴(kuò)展性、 穩(wěn)定性、 可靠性. 例如, 可在main函數(shù)執(zhí)行前添加監(jiān)控代碼以判斷是否有命令要執(zhí)行, 以便將機(jī)器碼寫入到Flash中, 若有則進(jìn)行寫入, 用這種方法可以快捷地更新用戶程序.

3.2 在計(jì)算程序和數(shù)據(jù)占用空間上的應(yīng)用

因.hex文件中的程序和數(shù)據(jù)直接裝載到Flash中, 其相關(guān)文件也提供了程序、 數(shù)據(jù)分配和占用空間的輔助信息, 可據(jù)此計(jì)算出程序、 數(shù)據(jù)占用的存儲(chǔ)空間, 以便決定是否要優(yōu)化程序和數(shù)據(jù).

要計(jì)算常量、 靜態(tài)和全局變量以及單個(gè)函數(shù)占用的空間, 可根據(jù).lst、 .map文件中提供的關(guān)于函數(shù)、 常量、 靜態(tài)變量和全局變量等占用的空間信息來(lái)進(jìn)行. 要計(jì)算特定的一行或多行程序占用的空間, 可根據(jù).lst文件提供的源代碼、 匯編代碼、 機(jī)器碼的對(duì)應(yīng)關(guān)系進(jìn)行, 即計(jì)算程序語(yǔ)句對(duì)應(yīng)的所有機(jī)器碼占用的總字節(jié)數(shù). 要計(jì)算整個(gè)MCU應(yīng)用工程占用的空間, 可直接對(duì).hex文件中除最后2行入口地址記錄和結(jié)束記錄外每條記錄的數(shù)據(jù)區(qū)字節(jié)數(shù)求和, 或根據(jù).lst文件中“程序頭及輸出段的信息”中的size字段值計(jì)算.

例如, 通過(guò)計(jì)算后決定要修改某個(gè)函數(shù)或功能段, 可以先根據(jù).lst文件中提供的關(guān)于其前幾個(gè)機(jī)器碼及存儲(chǔ)地址, 在.hex中定位到該函數(shù)或功能段. 然后進(jìn)行修改, 也可在main永久循環(huán)中添加監(jiān)控代碼, 以動(dòng)態(tài)在線更新Flash中相應(yīng)代碼. 如要修改常量、 靜態(tài)和全局變量, 先根據(jù).lst文件提供的LMA在.hex中進(jìn)行定位, 再根據(jù)需要修改, 或用監(jiān)控程序在線更新Flash中相應(yīng)值.

3.3 在計(jì)算程序執(zhí)行時(shí)間上的應(yīng)用

在嵌入式系統(tǒng)設(shè)計(jì)中, 當(dāng)延時(shí)時(shí)間短且重復(fù)次數(shù)較少時(shí)可以用完全軟件方式實(shí)現(xiàn)計(jì)數(shù)或定時(shí), 即利用計(jì)算機(jī)執(zhí)行指令的耗時(shí)實(shí)現(xiàn). 對(duì)于用C語(yǔ)言編寫的延時(shí)程序, 關(guān)鍵在于要精確測(cè)算出C語(yǔ)句的執(zhí)行耗時(shí), 為此, 可根據(jù).lst文件提供的C語(yǔ)句生成的匯編指令和機(jī)器碼及內(nèi)核參考手冊(cè)上提供的相關(guān)匯編指令的指令周期進(jìn)行精確計(jì)算, 進(jìn)而方便地設(shè)計(jì)循環(huán)次數(shù)或選擇循環(huán)體語(yǔ)句.

4 結(jié)語(yǔ)

開(kāi)發(fā)人員可以根據(jù)本研究, 在開(kāi)發(fā)MCU應(yīng)用工程時(shí)自行編寫或修改鏈接腳本文件、 修改啟動(dòng)程序、 優(yōu)化程序和數(shù)據(jù)等, 以便充分利用有限資源, 提高系統(tǒng)可靠性、 穩(wěn)定性. 在后續(xù)研究中, 將開(kāi)展對(duì)機(jī)器碼相關(guān)文件中有關(guān)調(diào)試信息的研究, 提升其應(yīng)用性.

猜你喜歡
靜態(tài)程序函數(shù)
二次函數(shù)
第3講 “函數(shù)”復(fù)習(xí)精講
靜態(tài)隨機(jī)存儲(chǔ)器在軌自檢算法
二次函數(shù)
函數(shù)備考精講
試論我國(guó)未決羈押程序的立法完善
“程序猿”的生活什么樣
英國(guó)與歐盟正式啟動(dòng)“離婚”程序程序
創(chuàng)衛(wèi)暗訪程序有待改進(jìn)
機(jī)床靜態(tài)及動(dòng)態(tài)分析
繁昌县| 长岭县| 岳西县| 青浦区| 利津县| 惠州市| 依兰县| 巴林右旗| 莫力| 河源市| 浮山县| 茂名市| 太仆寺旗| 柳江县| 琼中| 靖宇县| 日喀则市| 葫芦岛市| 长治市| 汉沽区| 永登县| 绥阳县| 崇州市| 惠州市| 济宁市| 朝阳区| 青川县| 赣榆县| 措勤县| 呼玛县| 玉林市| 顺平县| 什邡市| 台北市| 莲花县| 当雄县| 阜平县| 齐齐哈尔市| 策勒县| 墨江| 财经|