【问题标题】:Would Thumb-2 ARM-Core Micros From Different Manufacturers Have Same Codesize?来自不同制造商的 Thumb-2 ARM-Core Micros 是否具有相同的代码大小?
【发布时间】:2013-08-02 17:04:32
【问题描述】:

比较来自两个不同制造商的两个 Thumb-2 微控制器。一个是 Cortex M3,一个是 A5。他们是否保证将特定代码段编译为相同的代码大小?

【问题讨论】:

  • 这一切都取决于编译器。 thumb2 扩展有不同的变体,取决于您是否告诉编译器使用什么变体以及它将使用什么变体。编译器可能在其代码生成中具有特定于体系结构的 if-then-elses。简单的答案是“试一试”,然后询问堆栈溢出,“为什么不一样”或“为什么不一样”
  • 芯片厂商从arm获取内核,注意arm有同一个内核的不同版本,所以此时可能有两三个cortex-m3内核。并且如果它们之间需要更改代码(某些指令不起作用或某些指令序列)并且如果编译器知道,等等。
  • 此外,您永远无法保证不同的编译器将从相同的输入为相同的目标生成相同的输出。如果构建具有不同的选项,即使同一编译器的不同版本也不会有这种保证,同一编译器的不同构建也不会具有相同的版本。在你的问题中使用保证这个词几乎会自动导致否定,没有保证。
  • 所以如果我使用相同的编译器,我可以预期任何差异都会很小(如果不是不存在的话)?
  • 取决于您使用的命令行。如果希望在两个平台上拥有相同的编译代码,那么只需编译一次该对象并将其链接到任一项目(如果它允许您这样做的话)。否则,您需要以某种方式检查两个编译器输出以验证是否生成了相同的代码。链接可以对该代码之外的项目进行一些修改,因此另一个文件/对象中的任何函数都会在链接时解析,因此最终链接的输出可能因平台而异,但会很微妙。

标签: arm thumb cortex-a8 cortex-m


【解决方案1】:

就这样

fun.c

unsigned int fun ( unsigned int x )
{
    return(x);
}

addimm.c

extern unsigned int fun ( unsigned int );
unsigned int addimm ( unsigned int x )
{
    return(fun(x)+0x123);
}

出于演示目的,为裸机构建,并不是真正的功能程序,但它编译干净并演示了我打算演示的内容。

布防指令

arm-none-eabi-gcc -Wall  -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-a5 -march=armv7-a -c addimm.c -o addimma.o

对象的反汇编,未链接

00000000 <addimm>:
   0:   e92d4008    push    {r3, lr}
   4:   ebfffffe    bl  0 <fun>
   8:   e2800e12    add r0, r0, #288    ; 0x120
   c:   e2800003    add r0, r0, #3
  10:   e8bd8008    pop {r3, pc}

thumb 通用(armv4 或 v5,无论此编译器构建的默认值是什么)

arm-none-eabi-gcc -Wall  -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -c addimm.c -o addimmt.o

00000000 <addimm>:
   0:   b508        push    {r3, lr}
   2:   f7ff fffe   bl  0 <fun>
   6:   3024        adds    r0, #36 ; 0x24
   8:   30ff        adds    r0, #255    ; 0xff
   a:   bc08        pop {r3}
   c:   bc02        pop {r1}
   e:   4708        bx  r1

皮质-a5 特异性

arm-none-eabi-gcc -Wall  -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-a5 -march=armv7-a -c addimm.c -o addimma5.o

00000000 <addimm>:
   0:   b508        push    {r3, lr}
   2:   f7ff fffe   bl  0 <fun>
   6:   f200 1023   addw    r0, r0, #291    ; 0x123
   a:   bd08        pop {r3, pc}

cortex-a5 是 armv7-a,就添加立即数本身而言,它支持 thumb-2,并且与二进制大小相关,这里没有优化,拇指为 32 位,拇指 2 为 32 位。但这只是一个例子,有时 thumb2 会生成比 thumb 更小的二进制文件。

皮质-m3

arm-none-eabi-gcc -Wall  -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m3 -march=armv7-m -c addimm.c -o addimmm3.o

00000000 <addimm>:
   0:   b508        push    {r3, lr}
   2:   f7ff fffe   bl  0 <fun>
   6:   f200 1023   addw    r0, r0, #291    ; 0x123
   a:   bd08        pop {r3, pc}

产生与 cortex-a5 相同的结果。对于这个简单的示例,当为 cortex-a5 和 cortex-m3 构建时,该对象的机器代码相同,大小相同

现在,如果我添加一个引导程序、一个主程序并调用此函数并填写它调用的函数以创建一个完整的链接程序

00000000 <_start>:
   0:   f000 f802   bl  8 <notmain>
   4:   e7fe        b.n 4 <_start+0x4>
    ...

00000008 <notmain>:
   8:   2005        movs    r0, #5
   a:   f000 b801   b.w 10 <addimm>
   e:   bf00        nop

00000010 <addimm>:
  10:   b508        push    {r3, lr}
  12:   f000 f803   bl  1c <fun>
  16:   f200 1023   addw    r0, r0, #291    ; 0x123
  1a:   bd08        pop {r3, pc}

0000001c <fun>:
  1c:   4770        bx  lr
  1e:   46c0        nop         ; (mov r8, r8)

我们得到一个结果。 addimm 函数本身的大小没有变化。使用 cortex-a5,您必须有一些 arm 代码然后切换到 thumb,并且可能在与库等链接时,您可能会得到 arm 和 thumb 的混合,所以

00000000 <_start>:
   0:   eb000000    bl  8 <notmain>
   4:   eafffffe    b   4 <_start+0x4>

00000008 <notmain>:
   8:   e92d4008    push    {r3, lr}
   c:   e3a00005    mov r0, #5
  10:   fa000001    blx 1c <addimm>
  14:   e8bd4008    pop {r3, lr}
  18:   e12fff1e    bx  lr

0000001c <addimm>:
  1c:   b508        push    {r3, lr}
  1e:   f000 e804   blx 28 <fun>
  22:   f200 1023   addw    r0, r0, #291    ; 0x123
  26:   bd08        pop {r3, pc}

00000028 <fun>:
  28:   e12fff1e    bx  lr

整体较大的二进制文件,但 addimm 部分本身的大小没有变化。

至于链接改变对象的大小,看这个例子

bootstrap.s

.thumb

.thumb_func
.globl _start
_start:
    bl notmain
hang: b hang

.thumb_func
.globl dummy
dummy:
    bx lr

.code 32
.globl bounce
bounce:
    bx lr

你好.c

void dummy ( void  );
void bounce ( void  );
void notmain ( void )
{
    dummy();
    bounce();
}

查看 notmain 本身的 arm 构建,对象:

00000000 <notmain>:
   0:   e92d4800    push    {fp, lr}
   4:   e28db004    add fp, sp, #4
   8:   ebfffffe    bl  0 <dummy>
   c:   ebfffffe    bl  0 <bounce>
  10:   e24bd004    sub sp, fp, #4
  14:   e8bd4800    pop {fp, lr}
  18:   e12fff1e    bx  lr

根据调用它的对象和调用的对象,链接器可能需要添加更多代码来处理在对象外部定义的项目,从全局变量到外部函数

00008000 <_start>:
    8000:   f000 f818   bl  8034 <__notmain_from_thumb>

00008004 <hang>:
    8004:   e7fe        b.n 8004 <hang>

00008006 <dummy>:
    8006:   4770        bx  lr

00008008 <bounce>:
    8008:   e12fff1e    bx  lr

0000800c <notmain>:
    800c:   e92d4800    push    {fp, lr}
    8010:   e28db004    add fp, sp, #4
    8014:   eb000003    bl  8028 <__dummy_from_arm>
    8018:   ebfffffa    bl  8008 <bounce>
    801c:   e24bd004    sub sp, fp, #4
    8020:   e8bd4800    pop {fp, lr}
    8024:   e12fff1e    bx  lr

00008028 <__dummy_from_arm>:
    8028:   e59fc000    ldr ip, [pc]    ; 8030 <__dummy_from_arm+0x8>
    802c:   e12fff1c    bx  ip
    8030:   00008007    andeq   r8, r0, r7

00008034 <__notmain_from_thumb>:
    8034:   4778        bx  pc
    8036:   46c0        nop         ; (mov r8, r8)
    8038:   eafffff3    b   800c <notmain>
    803c:   00000000    andeq   r0, r0, r0

dummy_from_arm 和 notmain_from_thumb 都被添加,增加了二进制文件的大小。每个对象的大小没有变化,但整个二进制文件却发生了变化。 bounce() 是一个手臂到手臂的函数,没有补丁,dummy() 手臂到拇指,notmain() 拇指到主。

所以你可能有一个 cortex-m3 对象和一个 cortex-a5 对象,就该对象中的代码而言,它们都是相同的。但是取决于您将它们链接到的内容,最终在 cortex-m3 系统和 cortex-a5 系统之间有所不同,您可能会看到链接器添加或多或少的代码来解释系统差异、库、操作系统特定等等,甚至与您在二进制文件中放置对象的位置一样多,如果它必须比单条指令更远,那么链接器将添加更多代码。

这都是 gcc 特定的东西,每个工具链都将以自己的方式处理这些问题。当您使用对象和链接器模型时,这就是野兽的本性,这是一个非常好的模型,但编译器、汇编器和链接器必须协同工作以确保在链接时可以正确访问全局资源。与ARM无关,这个问题存在于许多/大多数处理器架构中,并且工具链处理每个工具链,每个版本,每个目标架构的这些问题。当我说更改对象的大小时,我真正的意思是链接器可能会向最终的二进制文件添加更多代码,以便处理该对象以及它如何与其他对象交互。

【讨论】:

  • 感谢您的回复!
猜你喜欢
  • 2011-05-05
  • 2012-02-08
  • 2016-05-15
  • 2017-01-22
  • 2018-05-19
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 2010-11-15
相关资源
最近更新 更多