来自不同制造商的Thumb-2 ARM核心显微镜是否具有相同的代码?

时间:2013-08-02 17:04:33

标签: arm thumb cortex-a8 cortex-m

比较两个不同制造商的两个Thumb-2微型计算机。一个是Cortex M3,一个是A5。他们是否保证将特定代码编译成相同的代码?

1 个答案:

答案 0 :(得分:0)

所以这里

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 generic(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

cortex-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,只要add immediate本身去并且与二进制大小有关,这里没有优化,拇指为32位,thumb2为32位。但这只是一个例子,也许有时候thumb2会产生比拇指更小的二进制文件。

皮质-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构建时,这个对象的机器代码是相同的,大小相同

现在,如果我添加一个bootstrap,一个main,并调用此函数并填写它调用的函数来创建一个完整的,链接的程序

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你必须有一些手臂代码然后切换到拇指,并且可能在与图书馆等连接时你可能会得到手臂和拇指的混合物,所以

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

的hello.c

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

看着一个不自主的手臂构建,对象:

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()是一个手臂到手臂的功能,没有修补,虚拟()手臂到拇指和notmain()拇指到主。

因此你可能有一个cortex-m3对象,以及一个cortex-a5对象,就该对象中的代码而言,它们都是相同的。但是,如果你将它们与它们联系起来,最终在cortex-m3系统和cortex-a5系统之间存在差异,你可能会看到链接器添加或多或少的代码来解释系统差异,库,特定于操作系统等等,甚至在放置对象的二进制文件中,如果它必须具有比单个指令更远的范围,则链接器将添加更多代码。

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