Converting problem: __asm__ __volatile__

Fredrick picture Fredrick · Sep 6, 2009 · Viewed 7.7k times · Source

I have been dealing with Nasm on a linux environment for some time and this function worked great... but now I am switching to a windows environment and I want to use Masm (with VS2008) I cant seem to get this to work...

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

When I write something like this...

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

asm is no more recognised and volatile throws an error saying "string", I also tried writing _asm volatile but I get an error saying "inline assembler syntax error in 'opcode'; found 'data type'"

Answer

Rom picture Rom · Sep 6, 2009

Assuming you're talking about x86 command set, here are few things to remember:

  1. the instruction "outb" outputs one byte, which would be equivalent to type "char" or "unsigned char" in C/C++. For outputting a 16-bit (since you're using "unsigned short") word one needs to use "outw"
  2. having said that, it is recommended by Intel (and required by VS) that you use the instruction mnemonic "out" and the port size is recognized from the operand size. For example "out dx, ax" would be equivalent for "outw", while "out dx, al" is equivalent for "outb"
  3. on x86 the "out" instruction requires the port and the outputting value to be placed into (e)dx and {eax/ax/al} registers respectively. While Nasm might do it for you (I don't have the compiler handy, so I can't confirm that), in VS you have to do it the way it is done on the CPU level.
  4. there is no reason to specify "volatile" keyword with __asm. Any inline assembly instructions cause VS compiler to disable read caching (what volatile keyword is for)

Here is the code (assuming you're writing into 16-bit port):

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

in case you're writing into 8-bit port, the code should look like that:

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