为什么局部变量不能在 GNU C 基本内联 asm 语句中使用?

2024-01-29

为什么我不能使用局部变量main用于基本 asm 内联?它只允许在扩展汇编中使用,但为什么会这样呢?

(我知道局部变量在返回地址之后位于堆栈上(因此一旦函数返回就不能使用),但这不应成为不使用它们的原因)

以及基本汇编的示例:

int a = 10; //global a
int b = 20; //global b
int result;

int main() {
    asm ( "pusha\n\t"
          "movl a, %eax\n\t"
          "movl b, %ebx\n\t"
          "imull %ebx, %eax\n\t"
          "movl %eax, result\n\t"
          "popa");

    printf("the answer is %d\n", result);
    return 0;
}

扩展的例子:

int main (void) {
    int data1 = 10;  //local var - could be used in extended
    int data2 = 20;
    int result;

    asm ( "imull %%edx, %%ecx\n\t"
          "movl %%ecx, %%eax" 
          : "=a"(result)
          : "d"(data1), "c"(data2));

    printf("The result is %d\n",result);
    return 0;
}

编译为:gcc -m32 somefile.c

平台:uname -a: Linux 5.0.0-32-generic #34-Ubuntu SMP Wed Oct 2 02:06:48 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux


您可以在扩展程序集中使用局部变量,但您需要将它们告知扩展程序集构造。考虑:

#include <stdio.h>


int main (void)
{
    int data1 = 10;
    int data2 = 20;
    int result;

    __asm__(
        "   movl    %[mydata1], %[myresult]\n"
        "   imull   %[mydata2], %[myresult]\n"
        : [myresult] "=&r" (result)
        : [mydata1] "r" (data1), [mydata2] "r" (data2));

    printf("The result is %d\n",result);

    return 0;
}

In this [myresult] "=&r" (result)说选择一个寄存器(r)将用作输出(=) 左值的值result,并且该寄存器将在程序集中被称为%[myresult]并且必须与输入寄存器不同(&)。 (您可以在两个地方使用相同的文本,result代替myresult;我只是为了说明而做了不同的处理。)

相似地[mydata1] "r" (data1)表示输入表达式的值data1到寄存器中,它将在程序集中被称为%[mydata1].

我修改了程序集中的代码,使其仅修改输出寄存器。你原来的代码修改了%ecx但没有告诉编译器它正在这样做。你可以告诉编译器,通过把"ecx"第三次之后:,这就是“破坏”寄存器列表所在的位置。但是,由于我的代码让编译器分配一个寄存器,因此我不会在破坏的寄存器中列出特定的寄存器。可能有一种方法告诉编译器其中一个输入寄存器将被修改但输出不需要,但我不知道。 (文档是here https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Extended-Asm.html.) 对于此任务,更好的解决方案是告诉编译器对输入之一使用与输出相同的寄存器:

    __asm__(
        "   imull   %[mydata1], %[myresult]\n"
        : [myresult] "=r" (result)
        : [mydata1] "r" (data1), [mydata2] "0" (data2));

在此,0 with data2表示使其与操作数 0 相同。操作数按其出现的顺序编号,从第一个输出操作数 0 开始,一直到输入操作数。所以,当汇编代码开始时,%[myresult]将引用一些寄存器的值data2已被放置,编译器将期望新值result组装完成后将出现在该寄存器中。

执行此操作时,您必须将约束与事物在装配中的使用方式相匹配。为了r约束,编译器提供一些可以在接受通用处理器寄存器的汇编语言中使用的文本。其他包括m作为内存参考,以及i为立即数操作数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么局部变量不能在 GNU C 基本内联 asm 语句中使用? 的相关文章

随机推荐