gcc 行为不端(或我有)

t1qtbnec  于 2022-11-13  发布在  其他
关注(0)|答案(2)|浏览(86)

有时候我不得不涉猎一点汇编程序,并且不太确定指令的正确使用。在研究什么应该是最简单的延迟循环时,我得到了一个意想不到的结果,我的问题是:我是否误用了指令,或者下面的代码实际上是一个编译器错误。
如果答案是“编译器错误”:请注意,我知道有更新版本的arm-none-eabi-as。问题不是“让这段代码工作”,而是正确使用汇编指令的问题。目标系统是普通的Cortex-m3处理器STM32 F1 xx系列。
下面的代码:

.syntax unified
        .cpu  cortex-m3
        .thumb
    
        .align 1
        .global myDelayWorks       
        .thumb_func
myDelayWorks:   
.FileLocalLabel:
        subs  r0,#1
        bne.n .FileLocalLabel
        bx    lr
            
        .align 1
        .global myDelayFails       
        .thumb_func
myDelayFails:
        subs  r0,#1
        bne.n myDelayFails
        bx    lr

编译为以下内容(使用arm-none-eabi-as --版本GNU汇编程序(用于ARM嵌入式处理器的GNU工具)2.24.0.20150604):

8                myDelayWorks:   
   9                .FileLocalLabel:
  10 0000 0138              subs  r0,#1
  11 0002 FDD1              bne.n .FileLocalLabel
  12 0004 7047              bx    lr
  13                        
  14                        .align 1
  15                        .global myDelayFails       
  16                        .thumb_func
  17                myDelayFails:
  18 0006 0138              subs  r0,#1
  19 0008 FED1              bne.n myDelayFails
  20 000a 7047              bx    lr

由于myDelayFails被声明为.global,因此可能会出现分支偏移量不正确得问题.

2g32fytz

2g32fytz1#

我想您担心的是机器码FED1中编码的位移(这是错误的字节序,应该是D1FE以匹配通常的表示法)看起来是-4,而实际上应该是-6?这是因为它最终是由链接器计算的,而不是由汇编器计算的。
汇编器在该字段中留下的内容并没有直接的意义(有时链接器在地址计算中会包含一个偏移量),但是在目标文件中会有一个重定位条目,告诉链接器在那里插入正确的位移到标签myDelayFails
所以这一切都是正常的。如果你反汇编链接器产生的实际可执行文件,你应该会看到正确的置换。
全局标签和非全局标签在这方面的行为不同也是正常的。(即使它不知道它们的绝对地址),因此它可以自己计算和插入位移。对于全局标签,它可能在汇编程序不知道其最终位置的另一个部分中,或者在完全不同的源文件中定义,因此汇编程序将其留给链接程序。
在这种情况下,全局标签是在当前文件中定义的,所以汇编器原则上可以自己计算位移。我不太清楚为什么他们选择把它留给链接器。可能是因为链接器可以重新定义符号myDelayFails,如果出于某种原因这样做是有用的话。

s71maibg

s71maibg2#

正如已接受的答案中所建议的,链接汇编结果将修复全局引用,并确定偏移量足够小,可以使用16位相对条件分支。偏移量看起来偏离是汇编程序生成列表的一个人工产物。
使用原始代码,执行以下代码以获得二进制映像:

arm-none-eabi-as -ahls=myDelay.lst -o myDelay.o myDelay.s
arm-none-eabi-ld -o myDelay.out myDelay.o
arm-none-eabi-ld: warning: cannot find entry symbol _start; defaulting to 00008000
arm-none-eabi-objcopy -Obinary myDelay.out myDelay.bin

然后对生成的二进制文件进行十六进制转储:

00000000: 0138 fdd1 7047 0138 fdd1 7047            .8..pG.8..pG

显示两个例程的结果实际上是相同的。

相关问题