简单的g ++内联汇编程序出错

时间:2017-01-25 12:49:10

标签: c++ gcc assembly g++ inline-assembly

我正在尝试编写一个“hello world”程序来测试g ++中的内联汇编程序。 (仍然倾向于AT& T语法)

代码是:

#include <stdlib.h>
#include <stdio.h>

# include <iostream> 

using namespace std;

int main() {
    int c,d;

    __asm__ __volatile__ (
        "mov %eax,1;    \n\t"
        "cpuid;         \n\t"
        "mov %edx, $d;  \n\t"
        "mov %ecx, $c;  \n\t"
    );

    cout << c << " " << d << "\n";

    return 0;
}

我收到以下错误:

inline1.cpp: Assembler messages:
inline1.cpp:18: Error: unsupported instruction `mov'
inline1.cpp:19: Error: unsupported instruction `mov'

你能帮助我完成它吗?

韩国社交协会

2 个答案:

答案 0 :(得分:2)

您的汇编代码无效。请仔细阅读Extended Asm。这是另一个good overview。 这是一个CPUID示例代码from here

static inline void cpuid(int code, uint32_t* a, uint32_t* d)
{
    asm volatile ( "cpuid" : "=a"(*a), "=d"(*d) : "0"(code) : "ebx", "ecx" );
}

请注意格式:

  • 首先:后跟输出操作数:: "=a"(*a), "=d"(*d); "=a"eax"=bebx
  • 第二个:后跟输入操作数:: "0"(code); "0"表示code应占据与输出操作数0相同的位置(在这种情况下为eax
  • 第三个:后跟破坏的寄存器列表:: "ebx", "ecx"
  

我收到以下错误:

     

...

     

...错误:不支持的指令`mov&#39;

对于mov指令,因为您没有指定后缀,GAS会尝试推断出一个。看起来GAS无法这样做,因此错误。

This GAS语法指南说:

  

如果未指定后缀,则没有内存操作数   该指令,GAS从大小推断操作数大小   目标寄存器操作数(最后一个操作数)。

答案 1 :(得分:-1)

我保持@AMA答案是公认的,因为它足够完整。但是我已经对它做了一些考虑,并得出结论认为它不是100%正确。

我试图在GCC中实现的代码如下所示(Microsoft Visual Studio版本)。

int c,d;
_asm
{
  mov eax, 1;
  cpuid;
  mov d, edx;
  mov c, ecx;
}

当cpuid在eax设置为1的情况下执行时,将在ecx和edx中返回功能信息。

建议的代码返回eax(&#34; = a&#34;)和edx(=&#34; d&#34;)中的值。 这可以在gdb上看到:

(gdb) disassemble cpuid
Dump of assembler code for function cpuid(int, uint32_t*, uint32_t*):
  0x0000000000000a2a <+0>:  push   %rbp
  0x0000000000000a2b <+1>:  mov    %rsp,%rbp
  0x0000000000000a2e <+4>:  push   %rbx
  0x0000000000000a2f <+5>:  mov    %edi,-0xc(%rbp)
  0x0000000000000a32 <+8>:  mov    %rsi,-0x18(%rbp)
  0x0000000000000a36 <+12>: mov    %rdx,-0x20(%rbp)
  0x0000000000000a3a <+16>: mov    -0xc(%rbp),%eax
  0x0000000000000a3d <+19>: cpuid   
  0x0000000000000a3f <+21>: mov    -0x18(%rbp),%rcx
  0x0000000000000a43 <+25>: mov    %eax,(%rcx)        <== HERE
  0x0000000000000a45 <+27>: mov    -0x20(%rbp),%rax
  0x0000000000000a49 <+31>: mov    %edx,(%rax)        <== HERE
  0x0000000000000a4b <+33>: nop
  0x0000000000000a4c <+34>: pop    %rbx
  0x0000000000000a4d <+35>: pop    %rbp
  0x0000000000000a4e <+36>: retq   
End of assembler dump.

生成更接近我想要的内容的代码(根据评论的反馈进行编辑):

static inline void cpuid2(uint32_t* d, uint32_t* c)
{
   int a = 1;
   asm volatile ( "cpuid" : "=d"(*d), "=c"(*c), "+a"(a) :: "ebx" );
}

结果是:

(gdb) disassemble cpuid2
Dump of assembler code for function cpuid2(uint32_t*, uint32_t*):
   0x00000000000009b0 <+0>:   push   %rbp
   0x00000000000009b1 <+1>:   mov    %rsp,%rbp
   0x00000000000009b4 <+4>:   push   %rbx
   0x00000000000009b5 <+5>:   mov    %rdi,-0x20(%rbp)
   0x00000000000009b9 <+9>:   mov    %rsi,-0x28(%rbp)
   0x00000000000009bd <+13>:  movl   $0x1,-0xc(%rbp)
   0x00000000000009c4 <+20>:  mov    -0xc(%rbp),%eax
   0x00000000000009c7 <+23>:  cpuid  
   0x00000000000009c9 <+25>:  mov    %edx,%esi
   0x00000000000009cb <+27>:  mov    -0x20(%rbp),%rdx
   0x00000000000009cf <+31>:  mov    %esi,(%rdx)
   0x00000000000009d1 <+33>:  mov    -0x28(%rbp),%rdx
   0x00000000000009d5 <+37>:  mov    %ecx,(%rdx)
   0x00000000000009d7 <+39>:  mov    %eax,-0xc(%rbp)
   0x00000000000009da <+42>:  nop
   0x00000000000009db <+43>:  pop    %rbx
   0x00000000000009dc <+44>:  pop    %rbp
   0x00000000000009dd <+45>:  retq   
End of assembler dump.

要明确......我知道有更好的方法可以做到这一点。但这里的目的纯粹是教育性的。只是想了解它是如何工作的; - )

- 编辑(删除个人意见)---