Converting problem: __asm__ __volatile__ from GNU C to MSVC for in / out wrappers
Asked Answered
A

1

6

I have been dealing with Nasm and GNU C inline asm 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'"

Andante answered 6/9, 2009 at 11:49 Comment(0)
G
8

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;
}
Gregarine answered 6/9, 2009 at 12:23 Comment(6)
Also: you could use __asm { instructions here } for clearer syntax, and it might be worth mentioning, that inline asm won't work on x64, so for this architecture will have to write asm code in stand alone code.Eyeopening
Ok now it makes sense a bit, least am getting no errors.. so what is equivalent to inportb? I know you write "in" instead of "out" and probably change ax to al right? Or is it more complicated than that?Andante
Try it, it shouldn't hurt. Remember that VS uses {operation} {destination}, {source} order, so for reading the port it would be: __asm in al, dx; and then you need to store the result in your variable: __asm mov data, al; and return it from the function: return data;Gregarine
how about "unsigned char inportb (unsigned short _port)" I tried my luck by just switching "out" to "in" and got an error saying "improper operand type"...Andante
try: unsigned char tmp; __asm { mov dx, port \n in al, dx \n mov tmp, al } return tmp;Eyeopening
Thanks worked... and am presuming to do "unsigned int inportw(unsigned short _port)" we change "al" to "dx"? hmmmm this is interesting...Andante

© 2022 - 2024 — McMap. All rights reserved.