2010-12-12 101 views
13

我正在使用基於ARM Cortex-M3的微控制器(Thumb 2指令集)的彙編程序,使用GNU as。什麼時候GAS ELF需要指令.type,.thumb,.size和.section?

在一些示例代碼中,我發現像.size,.section.type這樣的指令,我知道這些指令是ELF指令。作爲一個例子:

.section .text.Reset_Handler 
    .weak  Reset_Handler 
    .type  Reset_Handler, %function 
Reset_Handler: 
    bl  main 
    b  Infinite_Loop  
    .size Reset_Handler, .-Reset_Handler 



.type指令所述設置一個符號的類型 - 通常要麼%對象(意味着數據?)或%功能。我不知道它有什麼不同。它並不總是包含在內,所以我不確定它何時需要使用。

與此相關的還有.thumb_func指令。從我讀過它看起來像它可能是等價的:

.thumb 
.type Symbol_Name, %function 

或者是完全不同的東西?



.size據說設置與符號關聯的大小。當需要時,我不知道。這是默認計算的,但是可以用這個指令覆蓋嗎?如果是這樣 - 你想要重寫什麼時候?



.section比較容易找到的文檔,我覺得我有什麼 確實一個公平的想法,但我還是有點不確定的使用。按照我的理解,它在不同的ELF部分之間切換(代碼爲 text,可寫入數據爲 data,未初始化數據爲 bss,常量爲 rodata等),並在需要時定義新部分。我想你會根據是否定義代碼,數據,未初始化的數據等來在這些之間切換。但是爲什麼要爲函數創建子部分,如上例所示?


對此有任何幫助表示讚賞。如果你能找到更詳細的教程或文檔鏈接 - 最好能爲新手理解 - 我將非常感激。

到目前爲止,Using as手冊有一些幫助 - 也許你可以從中獲得比我更多,更多的知識。

+2

我已經添加了一個賞金問題,希望得到更詳盡的答案,特別是關於.type和.size指令。 – Oystein 2010-12-14 22:26:11

+0

這應該被拆分成每個指令的問題。建議:理解ELF格式,然後在使用和不使用每個指令的情況下創建最小示例,編譯並在其上使用'readelf -a'。 – 2015-07-15 12:29:13

回答

10

我一直編程臂/拇指多年的許多彙編程序,並需要很少的許多指令。

.thumb_func非常重要,正如其他響應者指出的那樣。

例如

 
.globl _start 
_start: 
    b reset 

reset: 

.arm 

.globl one 
one: 
    add r0,r0,#1 
    bx lr 

.thumb 

.globl two 
two: 
    add r0,r0,#2 
    bx lr 

.thumb_func 
.globl three 
three: 
    add r0,r0,#3 
    bx lr 


.word two 
.word three 

.ARM或曾經是像.code32或.CODE 32告訴它這是ARM代碼不Thumb代碼,這對於你的Cortex-M3的你不會需要使用。

.thumb同樣,曾經是.code 16或者也許仍然有效,同樣的處理使得下面的代碼不是手臂。

如果您正在使用的標籤是不是你需要從其他文件轉移到或間接,那麼不會需要.thumb_func全球標籤。但是爲了正確地計算分支到這些全局標籤之一的地址(lsbit是拇指1和手臂0),您要將其標記爲拇指或手臂標籤,而thumb_func則可以這樣做,否則您有支化增加更多的代碼之前,以設置位和標籤不是可調用從C.

 

00000000 <_start>: 
    0: eaffffff b 4 <one> 

00000004 <one>: 
    4: e2800001 add r0, r0, #1 
    8: e12fff1e bx lr 

0000000c <two>: 
    c: 3002  adds r0, #2 
    e: 4770  bx lr 

00000010 <three>: 
    10: 3003  adds r0, #3 
    12: 4770  bx lr 
    14: 0000000c andeq r0, r0, ip 
    18: 00000011 andeq r0, r0, r1, lsl r0 

截至.thumb彙編是如所期望臂代碼。

這兩個和三個標籤/函數都是所需的拇指代碼,但是兩個標籤有一個偶數地址,而三個標籤具有適當的奇數地址。

最新的codesourcery工具被用來彙編,鏈接和轉儲上面的示例。

現在對於一切都是拇指(/ thumb2)的cortex-m3來說,thumb_func可能不是那麼重要,它可能只與命令行開關一起工作(很容易做一個實驗來找出)。儘管如此,如果您將拇指專用處理器轉移到普通的手臂/拇指核心,這是一個好習慣。

彙編通常喜歡添加所有這些指令和其他方式使外觀看起來更像一種高級語言。我只是說你不必使用它們,我將組裝器用於手臂,併爲許多不同的處理器使用許多不同的裝配器,並且更少選擇更多方法,這意味着關注裝配本身並儘可能少使用特定工具。通常情況下,我通常不是規則的例外,所以你可以通過查看編譯器輸出生成的指令(並通過文檔驗證)來找出更常用的指令。

 
unsigned int one (unsigned int x) 
{ 
    return(x+1); 
} 


    .arch armv5te 
    .fpu softvfp 
    .eabi_attribute 20, 1 
    .eabi_attribute 21, 1 
    .eabi_attribute 23, 3 
    .eabi_attribute 24, 1 
    .eabi_attribute 25, 1 
    .eabi_attribute 26, 2 
    .eabi_attribute 30, 2 
    .eabi_attribute 18, 4 
    .file "bob.c" 
    .text 
    .align 2 
    .global one 
    .type one, %function 
one: 
    .fnstart 
.LFB0: 
    @ args = 0, pretend = 0, frame = 0 
    @ frame_needed = 0, uses_anonymous_args = 0 
    @ link register save eliminated. 
    add r0, r0, #1 
    bx lr 
    .fnend 
    .size one, .-one 
    .ident "GCC: (Sourcery G++ Lite 2010.09-50) 4.5.1" 
    .section .note.GNU-stack,"",%progbits 

我與彙編混合ARM和Thumb彙編程序或數據時使用.align僞,你會期望彙編這樣的平臺就知道是在半字邊界和ARM指令爲Thumb指令爲明顯的東西與單詞邊界對齊。這些工具並不總是那麼聰明。灑上.aligns大約不會受傷

.text是默認,所以這是有點多餘的,但不會傷害。 .text和.data是標準屬性(不是arm所特有的),如果你正在編譯目標上的ROM和RAM組合,你可能會關心(取決於你對鏈接描述文件所做的),否則.text將適用於所有的。

.size顯然該函數的大小從該指令開始。彙編程序不能自己弄清楚,所以如果這個函數的大小對於你的代碼,鏈接器腳本,調試器,加載程序很重要,那麼這需要正確,否則你不必費心。一個函數是一個高層次的概念,無論如何,彙編器並不具備聲明其大小的功能。而C編譯器肯定不在意,它只是尋找一個分支到的標籤,而在arm系列的情況下,它是分支到的拇指代碼或者手臂代碼。

如果你在很長時間的代碼中懶惰地使用你的立即數(ldr rx,= 0x12345678),你可能會發現.pool指令(有一個更新的等價物)。再次,這些工具並不總是足夠聰明,可以在無條件分支之後放置這些數據,但有時您會告訴它們。我認爲懶惰的一半是嚴肅認真的,始終做標籤:.word是件痛苦的事情,我相信arm和gcc工具都可以用於這個快捷方式,所以我和其他人一樣使用它。

另請注意llvm會輸出一個額外的.eabi_attribute或兩個由代碼sourcery的版本/ mods支持的binutils,但不受gnu發佈的binutils支持(可能還有)。兩個解決方案可以工作,修改llvm的asm打印函數,不寫入eabi_attributes或至少用註釋(@)編寫它們,或者從源代碼獲取binutils源代碼/ mods,並以這種方式構建binutils。代碼源往往會導致gnu(例如thumb2支持)或者反向運行新功能,所以我認爲這些llvm attrubutes不久將會出現在主線binutils中。通過修剪llvm編譯代碼中的eabi_attributes,我沒有受到任何不良影響。

這裏是上述相同功能的llvm輸出,顯然這是我修改後的註釋掉eabi_attributes的llc。

 
    .syntax unified 
@ .eabi_attribute 20, 1 
@ .eabi_attribute 21, 1 
@ .eabi_attribute 23, 3 
@ .eabi_attribute 24, 1 
@ .eabi_attribute 25, 1 
@ .eabi_attribute 44, 1 
    .file "bob.bc" 
    .text 
    .globl one 
    .align 2 
    .type one,%function 
one:         @ @one 
@ BB#0:         @ %entry 
    add r0, r0, #1 
    bx lr 
.Ltmp0: 
    .size one, .Ltmp0-one 

ELF文件格式是有據可查的,很容易解析,如果你想真正看到什麼精靈特定指令(如果有的話)都在做。許多這些指令都是爲了幫助鏈接器。例如.thumb_func,.text,.data。

+0

謝謝,這當然有幫助。因此,除非我們討論特殊情況,否則尺寸和類型都不應該是必要的。 – Oystein 2010-12-15 06:55:37

+0

我從來沒有使用過.size或.type,我的大部分工作都在手臂上,彙編程序總是涉及到。我假設你的鏈接器腳本或者loader/elf解析器想要尋找這樣的東西,那麼你需要它們,我使用非常簡單的鏈接器腳本,它們只關心.text和.data,基本上是ROM和RAM。 – 2010-12-16 02:47:44

+0

關於.size指令:在用於仿生的android git樹中,提交fb723c87490b76d1d2fe521886f7cb6c96ed40b7說:'使用 BEGIN(x)和END(x)宏更新ARM系統調用,以提供系統調用代碼的大小信息。用於valgrind.' – 2012-03-12 17:21:11

5

程序的各個部分與ELF格式緊密相關,ELF格式中大多數系統(Linux,BSD,...)存儲其對象和可執行文件。 This article應該給你一個關於ELF如何工作的良好見解,這將有助於你理解章節的原因。

簡單地說,部分可讓您將程序組織到具有不同屬性(包括地址,執行和寫入權限等)的不同存儲區中。鏈接器在最後一個鏈接階段使用特定的linker script, (例如來自所有編譯單元的所有代碼一起,...),並將它們分配給內存中的最終地址。

對於嵌入式系統,其用途尤其明顯:首先,引導代碼(通常包含在.text部分中)必須加載到固定地址才能執行。然後,只讀數據可以分組到一個專用只讀部分,該部分將被映射到設備的ROM區域。最後一個例子:操作系統具有初始化函數,它們只被調用一次,然後從未使用過,浪費了寶貴的內存空間。如果所有這些初始化函數都組合在一個稱爲.initcode的專用段中,並且如果此段設置爲程序的最後一段,那麼一旦完成初始化,操作系統就可以輕鬆地回收該內存限制自己的記憶。例如Linux是已知使用技巧,以及GCC可以讓你的變量或方法放到特定的部分用__attribute__ ((section ("MYSECTION")))

.type.size加上後綴它其實還是挺我不清楚了。我將它們視爲鏈接器的助手,從來沒有在彙編程序生成的代碼之外看到它們。

.thumb_func似乎只需要對舊OABI接口,以便能與ARM代碼互通。除非你使用舊的工具鏈,否則你可能不必擔心。

+0

我想,至少清理部分部分。是否有特殊的理由來定義你自己的部分? – Oystein 2010-12-14 10:53:40

+5

。如果您獲取函數的地址,.thumb_func是必需的。對於Thumb函數,其地址必須具有位0設置(與數據項地址不同)。這個指令使彙編器標記符號,因此鏈接器知道何時設置位0. – 2010-12-14 11:17:18

+0

@Igor:太棒了!謝謝 – Oystein 2010-12-14 11:32:34

5

我試圖弄清楚爲什麼ARM和Thumb與最近的binutils打交道(用2.21.53(MacPorts)驗證,也是2.22(Yagarto 4.7.1))。

根據我的經驗,.thumb_func與較早的binutils一起工作良好,可以生成正確的交互工作表面貼面。但是,隨着更新版本的發佈,需要指令 .type *name*, %function以確保適當的膠合板生成。

binutils mailing list post

我懶得挖的binutils的舊版本,以檢查是否.type指令到位的.thumb_func較早的binutils足夠了。我猜在你的代碼中包含兩個指令都沒有什麼壞處。

編輯:在代碼使用.thumb_func更新的評論,顯然它適用於掰> Thumb交互,以標誌Thumb例程來生成中間代碼,但是除非.type指令用於標誌的ARM拇指> ARM交互失敗功能。

相關問題