2010-12-12 35 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交互失败功能。

相关问题