【问题标题】:Converting problem: __asm__ __volatile__ from GNU C to MSVC for in / out wrappers转换问题:__asm__ __volatile__ 从 GNU C 到 MSVC 用于输入/输出包装器
【发布时间】:2010-11-26 00:13:12
【问题描述】:

我在 Linux 环境中处理 Nasm 和 GNU C 内联 asm 已经有一段时间了,这个功能效果很好……但现在我正在切换到 Windows 环境,我想使用 Masm(带有 VS2008)我不能似乎让这个工作......

void outportb (unsigned short _port, unsigned short _data)
{
  __asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}

当我写出这样的东西时......

void outportb (unsigned short _port, unsigned short _data)
{
  asm volatile ("outb %1, %0" : : "dN" (_port), "a" (_data));
}

asm 不再被识别,并且 volatile 抛出一个错误,说“字符串”,我也尝试写 _asm volatile 但我收到一个错误,说“'操作码'中的内联汇编语法错误;找到'数据类型'”

【问题讨论】:

    标签: c assembly visual-c++ masm inline-assembly


    【解决方案1】:

    假设您谈论的是 x86 命令集,请记住以下几点:

    1. 指令“outb”输出一个字节,相当于 C/C++ 中的“char”或“unsigned char”类型。要输出 16 位(因为您使用的是“unsigned short”)字,需要使用“outw”
    2. 话虽如此,Intel 建议(并且 VS 要求)您使用指令助记符“out”,并且从操作数大小识别端口大小。例如,“out dx, ax”等价于“outw”,而“out dx, al”等价于“outb”
    3. 在 x86 上,“out”指令要求将端口和输出值分别放入 (e)dx 和 {eax/ax/al} 寄存器。虽然 Nasm 可能会为您执行此操作(我手边没有编译器,因此无法确认),但在 VS 中您必须按照 CPU 级别的方式执行此操作。
    4. 没有理由用 __asm 指定“volatile”关键字。任何内联汇编指令都会导致 VS 编译器禁用读取缓存(volatile 关键字的用途)

    这是代码(假设您正在写入 16 位端口):

    void outportw(unsigned short port, unsigned short data)
    {
        __asm  mov ax, data; 
        __asm  mov dx, port; 
        __asm  out dx, ax;
    }
    

    如果您正在写入 8 位端口,代码应如下所示:

    void outportb(unsigned short port, unsigned char data)
    {
        __asm  mov al, data; 
        __asm  mov dx, port; 
        __asm  out dx, al;
    }
    

    【讨论】:

    • 另外:您可以使用 __asm { instructions here } 来获得更清晰的语法,并且可能值得一提的是,内联 asm 不适用于 x64,因此对于此架构,必须在其中编写 asm 代码独立代码。
    • 好吧,现在有点意思了,至少我没有收到任何错误。那么什么相当于 inportb?我知道你写的是“in”而不是“out”,可能把 ax 改成好吗?还是比这更复杂?
    • 试试吧,应该不会疼的。请记住,VS 使用 {operation} {destination}, {source} 顺序,因此读取端口应该是:__asm in al, dx;然后你需要将结果存储在你的变量中: __asm mov data, al;并从函数中返回:return data;
    • “unsigned char inportb (unsigned short _port)”怎么样?我只是将“out”切换为“in”来试试运气,但出现“操作数类型不正确”的错误...
    • 尝试:无符号字符 tmp; __asm { mov dx, al 中的端口 \n, dx \n mov tmp, al } return tmp;
    猜你喜欢
    • 2012-01-26
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-24
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多