【问题标题】:Inline assembler syntax error内联汇编语法错误
【发布时间】:2016-05-19 04:11:16
【问题描述】:

我在开发操作系统时遇到了一些奇怪的错误。我正在使用outbinb 制作一个IO 驱动程序。我的outb函数如下:

static inline void outb(uint16_t port, uint8_t val)
{
    __asm("outb %0, %w1"  //<--Error
        :
        : "a"(val), "Nd"(port));
}

我在 Visual Studio 中收到此错误:

C2400:“操作码”中的内联汇编语法错误;找到'('

有人知道我为什么会收到这个错误吗?如何修复此错误?有什么建议吗?

【问题讨论】:

  • “VS”?就像在 Visual Studio 中一样?您发布的代码没有使用 Microsoft 的内联汇编语法。它看起来像是为 GCC 准备的。
  • 确实是GCC的内联汇编语法,不是 Visual Studio的。对于 Visual Studio,我认为没有将特定变量分配给特定寄存器的好方法,因此您可能只想在汇编源文件中编写整个函数。
  • 我之前帮助您时,您使用的是 GNU 汇编程序,而不是 Microsoft。正如@Michael 指出的那样,VS 中的内联 Visual C++ 的语法与 GNU 汇编程序完全不同。 VC++ 不支持作为 GCC 扩展的汇编器模板,在 MS 产品中不可用。

标签: visual-c++ x86 port inline-assembly osdev


【解决方案1】:

Visual Studio 的 VC++ 不支持 GCC 中提供的 GNU 汇编器模板。由于您将 port 定义为 16 位无符号整数,因此您需要使用采用 16 位端口号的 OUT 形式。您需要将 16 位端口号放在 DX 中。您还必须将内联程序集中的变量名称视为指针,因为您正在为您的函数使用标准的 CDECL 调用约定。示例代码:

static inline void outb(uint16_t port, uint8_t val) {
    __asm
    {
        mov dx, port
        mov al, val
        out dx, al
    } 
}

inb 函数可以通过以下方式完成:

static inline uint8_t inb(uint16_t port)
{
    uint8_t data;
    __asm
    {
        mov dx, port
        in al, dx
        mov data, al
    }
    return data;
}

这可以通过删除变量data 并将读取的字符存储到变量port 然后执行return (uint8_t)port; 来简化。所以这也可以:

static inline uint8_t inb(uint16_t port)
{
    __asm
    {
        mov dx, port
        in al, dx
        mov byte ptr[port], al   // Need to cast since port is 16-bit variable
    }
    return (uint8_t)port;
}

有关使用 VC++ 内联汇编的更多信息,请参阅 Microsoft Developer Network(MSDN)documentation

【讨论】:

  • 我真的不会称之为简化。
  • @immibis 简化是主观的,尽管在这种情况下我们只是重用了一个已经可用的变量。我承认的是,后一个示例的代码可读性较差。
猜你喜欢
  • 2010-10-23
  • 1970-01-01
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-19
相关资源
最近更新 更多