.set标签,。 VS.标签:GNU AS

时间:2019-07-04 00:21:45

标签: assembly x86 gas

在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, .的简写吗?

1 个答案:

答案 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