非常有趣的问题。我以前从未见过有人这样做。简而言之,是的,它们有点不同。以下是几个案例:
本地标签
这行得通:
// Local label:
movq $2, %rax
1:
decq %rax
// Branch to preceding local label 1
jg 1b
但这不是:
// Test the same thing with set:
movq $2, %rax
.set 1, .
decq %rax
// Branch to preceding local label 1
jg 1b
gcc 发出:Error: expected symbol name,因为符号名称不能以数字开头。有关符号名称的更多信息,请参阅binutils docs。
多重定义
当您有两个或多个定义使用相同的符号名称时,标签的行为会有所不同。文档说第一个标签会覆盖所有其他标签,但实际上,即使稍后使用 .set 伪操作,您的编译器也不会让您这样做。另一方面,.set 将允许您多次分配相同的符号,但是当使用同名标签时,此后符号的值将无法再更改。标签似乎使符号“只读”。
当多次使用.set 时,它始终是最新的值,或者,如果尚未设置,则为下一个可用值。
假设我们要在某处插入以下行:
remote: jmp retval
jmp remote
//// If inserted here, the program returns -1
// Return -1
.set retval, .
movq $-1, %rax
jmp exit
//// If inserted here, the program returns -1
// Return 1 (also works as a label since we don't try to set it again after this)
.set retval, .
movq $1, %rax
jmp exit
//// If inserted here, the program returns 1
exit:
如果您想确保不重复使用之前定义的符号,请使用 .eqv 或 .equiv。
说到速记:赋值运算符
= 和 == 运算符也可用于设置符号值。见Setting Symbols。
// This...
a=.
// ... is equivalent to
.set a, .
// ... or this (since .set and .equ are synonymous)...
.equ a, .
// And this...
a==.
// ... is equivalent to...
.eqv a, .
如需ab使用的示例,请参阅code golf challenge。