c - 将 0 分配给 gcc 扩展程序集中的变量

标签 c assembly inline-assembly

我有以下代码:

#include <stdio.h>
void main(){
    int x=0, y=0,i=100;
    for (;i<1000; i++,x+=32){
        if (x == 25*32) {
            y+=32;
            asm volatile("pushl %%eax\n\t"
                         "movl $0, %%eax\n\t"
                         "popl %%eax\n\t"
                         :"=a"(x)
                         :"a"(0)
                         );
        }
        printf("%d %d\n", x, y);
    }
}

基本上,我想做的是,将变量 x 设置为 0,但我不太明白汇编代码的作用,它实际上确实将 x 设置为 0,但我不确定发生了什么。有人可以解释发生了什么吗? (只是为了学习汇编和 C)。

最佳答案

这是你的 asm 结构说的:

  • "=a"(x) 中,您告诉编译器程序集将写入 (=) 到 %eax (a) 注册,您希望编译器将该结果分配给 x ((x))。
  • "a"(0) 中,您告诉编译器您希望它在 %eax (a),程序集将读取它。
  • 然后 push %%eax 将 %eax 保存在堆栈上,movl $0, %%eax 将 0 放入 %eax,popl %%eax 将保存的值恢复为 %eax。

那么,发生的事情是:

  • 编译器将 0 放入 %eax。
  • 您的指令将 0 保存在堆栈中,将 0 移入 %eax,然后从堆栈中恢复 0。
  • 编译器使用 %eax 中的 0 作为 x 的值。

所以,这可行,但效率低下。你可以得到同样的效果:

asm volatile("movl $0, %[MyName]"
    : [MyName] "=r" (x)
);

这是什么意思:

  • 没有输入(因为没有第二个“:”)。
  • 和以前一样,= 告诉编译器这些指令将写入结果。
  • r 表示结果将写入寄存器,但编译器会选择寄存器。
  • [MyName] 告诉编译器将出现在汇编代码中的 %[MyName] 更改为编译器选择的寄存器名称。
  • 和以前一样,(x)表示使用汇编代码后寄存器中的值作为x的新值。
  • 最后,指令 movl $0, %[MyName] 表示将 0 移动到 %[MyName] 命名的寄存器。

因为编译器可以选择寄存器,所以您不必在汇编语言中保存和恢复它。编译器负责确保它不需要为其他任何内容注册。

能够像我对 [MyName] 所做的那样命名操作数是 GCC 中的一项新功能。如果您的版本没有,您可以这样做:

asm volatile("movl $0, %0"
    : "=r" (x)
);

没有名称,每个操作数都有一个数字,从 0 开始,并按照操作数在输入/输出说明符中出现的顺序递增。因为我们只有一个操作数,所以它是 %0。

关于c - 将 0 分配给 gcc 扩展程序集中的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12109376/

相关文章:

c - 嵌入式编程。实时时钟.C编程实现

c - 如何停止 c 中 char 的重复无效答案?

c - 是否可以调用驻留在 exe 中的非导出函数?

c - in - gcc 内联汇编的操作数类型不匹配

c# - 用代码模拟窗口拖放?

相互依赖的CMake库

c++ - 当我们将数据从 ax 移动到端口地址时会发生什么

c - 在 MIPS 编程中使用递归调用查找数字的阶乘

iphone - 如何在 Xcode LLVM 中编写关于 LOOP 的内联汇编代码?

c - SSE2值提取问题