有时候我不得不涉猎一点汇编程序,并且不太确定指令的正确使用。在研究什么应该是最简单的延迟循环时,我得到了一个意想不到的结果,我的问题是:我是否误用了指令,或者下面的代码实际上是一个编译器错误。
如果答案是“编译器错误”:请注意,我知道有更新版本的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
,因此可能会出现分支偏移量不正确得问题.
2条答案
按热度按时间2g32fytz1#
我想您担心的是机器码
FED1
中编码的位移(这是错误的字节序,应该是D1FE
以匹配通常的表示法)看起来是-4,而实际上应该是-6?这是因为它最终是由链接器计算的,而不是由汇编器计算的。汇编器在该字段中留下的内容并没有直接的意义(有时链接器在地址计算中会包含一个偏移量),但是在目标文件中会有一个重定位条目,告诉链接器在那里插入正确的位移到标签
myDelayFails
。所以这一切都是正常的。如果你反汇编链接器产生的实际可执行文件,你应该会看到正确的置换。
全局标签和非全局标签在这方面的行为不同也是正常的。(即使它不知道它们的绝对地址),因此它可以自己计算和插入位移。对于全局标签,它可能在汇编程序不知道其最终位置的另一个部分中,或者在完全不同的源文件中定义,因此汇编程序将其留给链接程序。
在这种情况下,全局标签是在当前文件中定义的,所以汇编器原则上可以自己计算位移。我不太清楚为什么他们选择把它留给链接器。可能是因为链接器可以重新定义符号
myDelayFails
,如果出于某种原因这样做是有用的话。s71maibg2#
正如已接受的答案中所建议的,链接汇编结果将修复全局引用,并确定偏移量足够小,可以使用16位相对条件分支。偏移量看起来偏离是汇编程序生成列表的一个人工产物。
使用原始代码,执行以下代码以获得二进制映像:
然后对生成的二进制文件进行十六进制转储:
显示两个例程的结果实际上是相同的。