扩展的ASM和缺少用于命名约束的机器操作数

时间:2014-02-03 20:58:32

标签: assembly syntax x86 inline-assembly

我有struct

typedef struct {
    unsigned int EAX;
    unsigned int EBX;
    unsigned int ECX;
    unsigned int EDX;
} CPUIDinfo;

struct用于函数:

void get_cpuid_info(CPUIDinfo *info, const unsigned int func, const unsigned int subfunc)
{
    __asm__ __volatile__ (
        "push %%rax       ;\n"
        "push %%rcx       ;\n"
        "mov %0, %%eax    ;\n"
        "mov %1, %%ecx    ;\n"
        "cpuid            ;\n"
        "mov %%eax, %2    ;\n"
        "mov %%ebx, %3    ;\n"
        "mov %%ecx, %4    ;\n"
        "mov %%edx, %5    ;\n"
        "pop %%rcx        ;\n"
        "pop %%rax        ;\n"

        : "=m"(info->EAX), "=m"(info->EBX), "=m"(info->ECX), "=m"(info->EDX)
        : "m"(func), "m"(subfunc)
        : "%eax", "%ebx", "%ecx", "%edx"
    );
}

汇编程序正确匹配读取(%0%1),但它与正确的写入不匹配。撰写时,使用{%0%1%2%3}而不是{%2%3%4%5}。这意味着info->EAX被分配funcinfo->EBX被分配subfuncinfo->ECX获得应该被放置在info->EAX等等。

Extended ASM manual开始,我知道汇编程序有名称限制:

"mov %[func],    %%eax    ;\n"
"mov %[subfunc], %%ecx    ;\n"

但是当我尝试使用它时收到错误:

error: undefined named operand 'func'
error: undefined named operand 'subfunc'

我还试图告诉汇编程序在哪里使用:

    : [2]"=m"(info->EAX), [3]"=m"(info->EBX), [4]"=m"(info->ECX), [5]"=m"(info->EDX)
    : [0]"m"(func), [1]"m"(subfunc)
    : "%eax", "%ebx", "%ecx", "%edx"

但这会导致更多错误,例如:

error: expected identifier before numeric constant
error: expected ']' before numeric constant
error: expected string-literal before numeric constant

如何匹配我的操作数,以便写入(例如mov %%eax, %2)按预期执行?

1 个答案:

答案 0 :(得分:2)

使用正确的寄存器约束,您的函数可能如下所示:

void get_cpuid_info(CPUIDinfo *info, const unsigned int func, const unsigned int subfunc)
{
    __asm__ __volatile__ (
        "cpuid"
        : "=a"(info->EAX), "=b"(info->EBX), "=c"(info->ECX), "=d"(info->EDX)
        : "a"(func), "c"(subfunc)
    );
}

但要解决您的特定问题:应在约束中指定要使用的名称。那不是你应该写的[0]"m"(func), [1]"m"(subfunc)[func] "m" (func), [subfunc] "m" (subfunc)和输出约束类似。整个业务的重点是摆脱数字。您应该将符号名称放在方括号内,并将值放在圆括号中。