在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, .
的简写吗?
非常有趣的问题。我从未见过有人这样做。简而言之,是的,它们有些不同。这是几种情况:
此作品:
// 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: