为什么不能在多个函数中定义相同的局部标签?

why cannot define same local label in multiple functions?

想在多个函数中定义相同的局部标签:

    .text
    .globl main
func:
    push %rbp
    mov %rsp, %rbp
.a:
    leave
    ret

main:
    push %rbp
    mov %rsp, %rbp
.a:
    leave
    ret

奇怪的报错:

$ clang -c main.s
main.s:13:1: error: invalid symbol redefinition
.a:
^

当我使用 yasm 时,它允许在多个函数中使用相同的本地标签。 你有什么线索吗?

与 NASM 不同,.label 在 gas 语法中不是函数的局部(实际上在非 . 标签之前)。

.Llabel 是一个 "local" 符号名称,这意味着它不会出现在符号 table 中。它在整个文件中仍然可见,因此 the GNU as manual 不会将其称为本地标签。


gas 语法中有 个局部标签,但它们不是函数范围的。 (见上文link)。您 必须 使用 forward/back 注释来引用它们,否则它们是数字常量而不是标签。 (例如 mov , %eax 将文字 1 放入 eax,而不是最近 1: 的地址)。

更重要的是,你不能给它们起有意义的名字,比如.Lcopy_loop.Linput_non_zero。它们在宏定义中很有用,或者在可能被内联到多个地方或被优化器复制的内联 asm 中很有用。否则,应该首选有意义的名称

func1:
    test
    jcc 1f    # you need the forward/back annotation, otherwise it's an absolute address to jump to.
    ...
1:
    ...
    ret

func2:
    test
    # jcc 1b    # BAD!!! jumps to 1: in func1, which is still in scope.  This could bite you after moving some blocks around but missing the f/b annotations.
    jcc 1f      # good: will jump forward to the next definition of 1:
    ...
1:
    ...
    ret

最好只写func1.afunc2.a


在某些目标上(不包括 x86-64 和 i386),有限制范围的本地标签可以让你避免不小心跳到标签的错误定义,但你仍然不能使用有意义的标签名称:请参阅手册同一页上的 美元本地标签(上文 link)。

对于 x86 目标,

1$: 是 gas 和 clang 中的语法错误。

这很不幸,因为它将是函数范围的,除非您在函数中使用任何具有有意义名称的标签(例如 .Lmain_loop:)。