在GNU汇编器中,当前地址由.
这使得可以设置常量/符号并像使用标签一样使用它,例如:
.set offset, .
.long 0x10
.globl _start
_start:
# %eax should be 0x10
movl offset, %eax
# %ebx should be address of offset
movl $offset, %ebx
# Value at the address of offset should contain 0x20
movl $0x20, offset
以上代码的行为与offset
是标签而不是符号的行为完全相同。
在任何情况下上述说法都不成立,或者label:
确实只是.set label, .
的简写吗?
答案 0 :(得分:3)
非常有趣的问题。我从未见过有人这样做。简而言之,是的,它们有些不同。这有几种情况:
这有效:
// 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。