6

我在 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 但我收到一个错误,说“'操作码'中的内联汇编语法错误;找到'数据类型'”

4

1 回答 1

8

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

  1. 指令“outb”输出一个字节,相当于 C/C++ 中的“char”或“unsigned char”类型。要输出 16 位(因为您使用的是“unsigned short”)字,需要使用“outw”
  2. 话虽如此,英特尔(并且 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;
}
于 2009-09-06T12:23:57.627 回答