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