无约束内联汇编的引用变量

reference variables without constraint inline assembly

我想在 C 程序中使用内联汇编,而不使用约束,因为我不想在我足够复杂的学校论文中解释它。我正在尝试用键对某些字符进行异或。这是代码:

#include <stdio.h>
char text[11] = {'H','e','l','l','o'};
int key = 42;
int e;
char z;
int main()
{
    for (e=0; e<12; e++){
    z = text[e];
    asm volatile(
        "movl $z, %ax;" \
        "movl $key, %bx;" \
        "xor $ax, %bx;" \
        "movl $ax, %[z];");
    printf("%c\n", z);
    }
return 0;
}

但我不断收到: main.c:11:13: error: undefined named operand ‘z’ "movl $key, %ax;" \ 我尝试在变量前添加 static,因为它可能是 compiler/linker 优化的东西。我也尝试添加 __attribute__((used)) 但其中的 none 有所帮助。我正在使用 GNU GCC v7.1.1 感谢任何帮助,谢谢。

如果可能,完全避免使用内联汇编。

如果必须使用内联汇编,请尽可能使用扩展内联汇编,并声明正确的操作数和破坏列表。在您的特定情况下,这样的事情会起作用:

#include <stdio.h>
char text[11] = {'H','e','l','l','o'};
int key = 42;
int e;
char z;
int main()
{
    for (e=0; e<12; e++){
        z = text[e];
        asm (
            "movzbl %0, %%eax;" \
            "movl %1, %%ebx;" \
            "xor %%ebx, %%eax;" \
            "movb %%al, %0;"
            : "+m"(z) : "m"(key) : "eax", "ebx");
        printf("%c\n", z);
    }

    return 0;
}

这里,"+m"(z)是一个输出操作数,而"m"(key)是一个输入操作数。 "eax", "ebx"clobber 列表 指示您的代码覆盖了哪些寄存器。由于 asm 语句的所有副作用都通过其输出操作数和 clobbers 显式显示,因此可以省略 volatile 关键字以为编译器提供更大的灵活性。

请注意,除非要求 keyze 是全局变量,否则最好将它们设为自动变量并使用额外的 ri 输入和输出操作数的约束,使编译器更灵活地选择保留变量的位置。

还要注意更正后的操作数大小。 key 是一个 32 位变量,z 是一个 8 位变量。最后,我修复了 xor 指令。您不小心切换了操作数。

注意汇编代码可以做得更好。一种稍微更有效的呈现代码的方法是这样的:

#include <stdio.h>
char text[11] = {'H','e','l','l','o'};
int key = 42;
int e;
char z;
int main()
{
    for (e=0; e<12; e++){
        z = text[e];
        asm (
            "xorb %b1, %0"
            : "+m"(z) : "r"(key));
        printf("%c\n", z);
    }

    return 0;
}

这会将 key 从内存加载到 C 编译器,使其能够就变量的保存位置做出更明智的选择。将 keyz 设为自动变量也可能是个好主意,但我不确定在您可能拥有的某些未命名约束下是否允许这样做。