宏替换GAS中的常数

发布于 2024-11-05 10:08:37 字数 160 浏览 1 评论 0原文

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

.macro S size=40
\size
.endm

我用它就像

mov %eax, S

What't wrong with that macro on X86 GNU Assembly? It says the symbol S is undefined during linking.

.macro S size=40
\size
.endm

I'm using it like

mov %eax, S

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盛装女皇 2024-11-12 10:08:37

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

.set S, 40
mov %eax, S

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

mov $S, %eax

Macros are used to create templates for code you frequently use, not to input a constant number. As such, I do not believe the assembler does macro expansion within an expression. Since you simply want a number, you could use .set to define a constant.

.set S, 40
mov %eax, S

Also, in case you usually use intel syntax, make sure you realize what this code is doing: It currently stores the value of eax in memory at the address 0x28. If you want to put the number 40 in eax, you need to reverse the operands and use a dollar sign in front of S.

mov $S, %eax
失而复得 2024-11-12 10:08:37

您还可以直接用等号 = 指定符号:

S = 40

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

通过编写一个符号,后跟一个等号=',再跟一个表达式,可以为符号指定任意值(请参阅表达式)。这相当于使用 .set 指令。参见.set。同样,这里使用双等号='`=' 表示与 .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 将包含要写入的字符串的长度。

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

You can also directly assign symbols with the equals sign =:

S = 40

which the GNU as manual says is equivalent to using .set https://sourceware.org/binutils/docs-2.19/as/Setting-Symbols.html#Setting-Symbols

A symbol can be given an arbitrary value by writing a symbol, followed by an equals sign =', 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='`=' here represents an equivalent of the .eqv directive. See .eqv.

.equ is yet another synonym...

 .equ S, 40

One typical use case of such constants, is to calculate the length of static strings, e.g. the Linux x86_64 hello world can be written as:

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

which you can compile and run wth:

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

GitHub upstream.

%rdx will then contain the length of the string to be written.

The $ is required just like for any regular address label, otherwise you would be trying to access that memory address instead of moving an immediate.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文