9

X86 GNU 程序集上的那个宏有什么问题?它表示符号 S 在链接期间未定义。

.macro S size=40
\size
.endm

我像这样使用它

mov %eax, S
4

2 回答 2

21

宏用于为您经常使用的代码创建模板,而不是输入常数。因此,我不相信汇编程序会在表达式中进行宏扩展。由于您只需要一个数字,您可以使用它.set来定义一个常量。

.set S, 40
mov %eax, S

此外,如果您通常使用 intel 语法,请确保您了解这段代码在做什么:它当前将 eax 的值存储在内存中的地址 0x28 处。如果要将数字 40 放入 eax 中,则需要将操作数反转并在 S 前面使用美元符号。

mov $S, %eax
于 2011-05-05T16:42:09.370 回答
3

您也可以直接使用等号分配符号=

S = 40

GNU 手册中所说的相当于使用.set https://sourceware.org/binutils/docs-2.19/as/Setting-Symbols.html#Setting-Symbols

可以通过写一个符号来给一个符号一个任意值,后面跟一个等号=', followed by an expression (see Expressions). This is equivalent to using the .set directive. See .set. In the same way, using a double equals sign='`=' 这里代表 .eqv 指令的等价物。见.eqv。

.equ又是一个同义词……

 .equ S, 40

这种常量的一个典型用例是计算静态字符串的长度,例如 Linux x86_64 hello world 可以写成:

hello_world.S

    .data
hello_world:
    .ascii "hello world\n"
    hello_world_len = . - hello_world
.text
.global _start
_start:
    /* write */
    mov $1, %rax
    mov $1, %rdi
    mov $hello_world, %rsi
    mov $hello_world_len, %rdx
    syscall

    /* exit */
    mov $60, %rax
    mov $0, %rdi
    syscall

您可以编译和运行它:

as -o hello_world.o hello_world.S
ld -o hello_world.out hello_world.o
./hello_world.out

GitHub 上游.

%rdx然后将包含要写入的字符串的长度。

$就像任何常规地址标签一样,这是必需的,否则您将尝试访问该内存地址而不是移动立即数。

于 2019-01-08T18:04:33.303 回答