ARM 程序集本地标签
ARM Assembly Local Labels
我目前正在阅读关于 Raspberry Pi OS 开发的 tutorial 并且想知道在这个代码片段(GCC ARM 程序集)中使用本地标签的方式:
...
b 2f
1:
stmia r4!, {r5-r8}
2:
cmp r4, r9
blo 1b
...
如果你使用1:
作为标签,你必须在跳转指令后指定f
或b
,以使汇编程序知道跳转的目标方向。据我所知你也可以使用这个:
...
b .2
.1:
stmia r4!, {r5-r8}
.2:
cmp r4, r9
blo .1
...
我认为这个选项不那么容易混淆(本地标签在x86汇编中也用一个点标记),因为在标签引用之后没有额外的字母。我已经测试了生成的机器代码,它是一样的。所以我的问题:
你为什么要用一个变体而不是另一个变体?
为什么要用f
或b
指定跳转方向?
重要的区别在于编号的局部标签可以放心地重复使用,这就是为什么您也需要指定方向。您可以跳到前一个或后一个,但不能跳到它们之后的那些。
1: foo
...
1: bar
...
jmp 1b # jumps to bar
...
jmp 1f # jumps to baz
...
1: baz
...
1: qux
...
jmp 1b # jumps to qux
只要您只在一个块中使用它们,您就可以确定它们会按预期工作并且不会与其他任何东西冲突。
局部标签的主要好处之一是,由于同一标识符可以出现多次,因此可以在宏中使用它们。不过,请考虑像这样的一些假设的本地标签用法:
.macro dothething rega regb ptr
ldrex \regb, [\ptr]
cmp \rega, \regb
beq 1
2: <more instructions>
...
strex \regb, \rega, [ptr]
cmp \regb, #0
bne 2
1:
.endm
myfunction:
dothething r0 r1 r2
dothething r0 r1 r3
bx lr
这在 armasm 中实际上是允许的(尽管语法略有不同),其中在没有指定方向的情况下的行为是 "search backwards, then forwards",但在任何合理的默认行为下至少有一个上面代码中的跳转最终会指向错误的标签实例。在宏中使用 beq 1f
和 bne 2b
明确指出方向解决了歧义并在宏的两次调用中生成正确的跳转。
如果您选择使用不是真正的本地标签的东西,那么您不仅可能会用垃圾弄乱您的符号 table,而且您还会剥夺自己使用循环或宏中的条件分支,因为您会生成非唯一符号。我的示例可能看起来有点做作,但是从汇编程序宏切换到 C 函数中的内联 asm 块,这些块在整个复杂代码库中内联,并且 things get a lot more real.
我目前正在阅读关于 Raspberry Pi OS 开发的 tutorial 并且想知道在这个代码片段(GCC ARM 程序集)中使用本地标签的方式:
...
b 2f
1:
stmia r4!, {r5-r8}
2:
cmp r4, r9
blo 1b
...
如果你使用1:
作为标签,你必须在跳转指令后指定f
或b
,以使汇编程序知道跳转的目标方向。据我所知你也可以使用这个:
...
b .2
.1:
stmia r4!, {r5-r8}
.2:
cmp r4, r9
blo .1
...
我认为这个选项不那么容易混淆(本地标签在x86汇编中也用一个点标记),因为在标签引用之后没有额外的字母。我已经测试了生成的机器代码,它是一样的。所以我的问题:
你为什么要用一个变体而不是另一个变体?
为什么要用
f
或b
指定跳转方向?
重要的区别在于编号的局部标签可以放心地重复使用,这就是为什么您也需要指定方向。您可以跳到前一个或后一个,但不能跳到它们之后的那些。
1: foo
...
1: bar
...
jmp 1b # jumps to bar
...
jmp 1f # jumps to baz
...
1: baz
...
1: qux
...
jmp 1b # jumps to qux
只要您只在一个块中使用它们,您就可以确定它们会按预期工作并且不会与其他任何东西冲突。
局部标签的主要好处之一是,由于同一标识符可以出现多次,因此可以在宏中使用它们。不过,请考虑像这样的一些假设的本地标签用法:
.macro dothething rega regb ptr
ldrex \regb, [\ptr]
cmp \rega, \regb
beq 1
2: <more instructions>
...
strex \regb, \rega, [ptr]
cmp \regb, #0
bne 2
1:
.endm
myfunction:
dothething r0 r1 r2
dothething r0 r1 r3
bx lr
这在 armasm 中实际上是允许的(尽管语法略有不同),其中在没有指定方向的情况下的行为是 "search backwards, then forwards",但在任何合理的默认行为下至少有一个上面代码中的跳转最终会指向错误的标签实例。在宏中使用 beq 1f
和 bne 2b
明确指出方向解决了歧义并在宏的两次调用中生成正确的跳转。
如果您选择使用不是真正的本地标签的东西,那么您不仅可能会用垃圾弄乱您的符号 table,而且您还会剥夺自己使用循环或宏中的条件分支,因为您会生成非唯一符号。我的示例可能看起来有点做作,但是从汇编程序宏切换到 C 函数中的内联 asm 块,这些块在整个复杂代码库中内联,并且 things get a lot more real.