我一直编程臂/拇指多年的许多汇编程序,并需要很少的许多指令。
.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。
我已经添加了一个赏金问题,希望得到更详尽的答案,特别是关于.type和.size指令。 – Oystein 2010-12-14 22:26:11
这应该被拆分成每个指令的问题。建议:理解ELF格式,然后在使用和不使用每个指令的情况下创建最小示例,编译并在其上使用'readelf -a'。 – 2015-07-15 12:29:13