首页 > 解决方案 > 使用 char 数组块作为内存输出操作数的内联汇编

问题描述

我正在执行cpuid(leaf 0)这给了我供应商字符串。代码(在 下block1)工作正常,GenuineIntel并按我的预期显示。在下面的 asmblock2中,我想直接将ebx, edx, ecx值映射到vendor数组,而不是使用显式 mov 指令。

目前我正在尝试将结果ebx值(四个字节)移动到vendor数组的前四个字节中。这会在屏幕上显示 的值,G它是 的第一个字节ebx

我尝试转换为uint32_t*,这给出了构建错误lvalue required in asm statement

我想了解应该对代码进行哪些更改才能将前四个字节写入供应商数组?有没有办法在不使用明确mov说明的情况下做到这一点?任何帮助表示赞赏。谢谢你。

#include <iostream>
#include <cstdint>
using namespace std;

const int VENDORSIZE = 12;
int main(int argc, char **argv)
{
    char vendor[VENDORSIZE +1]{};
    uint32_t leaf = 0;
    vendor[VENDORSIZE] = '\0';
    // Block 1
    /*asm volatile(
        "cpuid\n"
        "mov %%ebx, %0\n"
        "mov %%edx, %1\n"
        "mov %%ecx, %2\n"
        :"=m"(vendor[0]),"=m"(vendor[4]),"=m"(vendor[8])
        :"a"(leaf)
        :
    );*/

    // Block 2
    asm volatile(
    "cpuid\n"
    :"=b"(*vendor)
    :"a"(leaf)
    :
   );
    
    cout << vendor<< endl;
    return 0;
}

我对演员的尝试:

// Block 2
    asm volatile(
    "cpuid\n"
    :"=b"((uint32_t*) vendor)
    :"a"(leaf)
    :
   );

这会产生一个错误:

cpuid.cpp:28:5: error: invalid lvalue in asm output 0

基于下面 Peter Corde 的链接 - 我添加了缺少的dereference. 下面的代码现在输出GenuineIntel. 我真诚地感谢您的帮助。

// Block 2
    asm volatile(
    "cpuid\n"
    :"=b"(*(uint32_t*)vendor),"=d"(*(uint32_t*)(vendor+4)),"=c"(*(uint32_t*)(vendor+8))
    :"a"(leaf)
    :
   );

标签: c++assemblyx86inline-assemblycpuid

解决方案


我对这种内联汇编语法不太熟悉,但您可以尝试两件事。

  1. 不要在内联汇编器中使用旧式强制转换

    :"=b"(* static_cast<uint32_t*>(vendor))

  2. 在 C++ 代码中添加一个uint32_t*变量并在汇编程序中使用它

    uint32_t* pVendor = static_cast<uint32_t*>(&vendor[0]);

    :"=b"(*pVendor)


推荐阅读