X86 GNU Assembly上的宏有什么问题?它表示链接期间符号S未定义。
.macro S size=40
\size
.endm
我正在使用它
mov %eax, S
答案 0 :(得分:16)
宏用于为您经常使用的代码创建模板,而不是输入常数。因此,我不相信汇编程序在表达式中进行宏扩展。由于您只需要一个数字,因此可以使用.set
来定义常量。
.set S, 40
mov %eax, S
此外,如果您通常使用intel语法,请确保您了解此代码正在执行的操作:它当前将eax的值存储在地址0x28的内存中。如果要将数字40放在eax中,则需要反转操作数并在S前面使用美元符号。
mov $S, %eax
答案 1 :(得分:1)
您还可以直接分配带有等号=
的符号:
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世界可以写成:
.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
%rdx
将包含要写入的字符串的长度。
$
是必需的,就像任何常规地址标签一样,否则,您将尝试访问该内存地址而不是立即移动。