Page 1 of 2

Bloody Beginner 2: __asm volatile

Posted: Wed Jul 09, 2008 3:23 pm
by hpclutz
I new I would be back again soon, I just hoped it wouldn't be so soon ;)

Since you all obviously know more than I do, can somebody please explain to me what the __asm volatile (or __asm__ __volatile__ for some compilers) actually is good for and how it can be used?

In all the example kernels I constantly come across something like

Code: Select all

unsigned inportb(unsigned port)
{
	unsigned ret_val;
	__asm volatile("inb %w1,%b0" : "=a"(ret_val) : "d"(port));
	return ret_val;
}
but all it does for me is producing an "error C2400: inline assembler syntax error in 'opcode'; found 'data type'" and now I'm confused :?

Re: Bloody Beginner 2: __asm volatile

Posted: Wed Jul 09, 2008 3:57 pm
by Adek336
asm volatile is for inline assembly code, obviously, the volatile tells the compiler to not relocate or optimize the code in any way - without volatile an inline assembly might be discarded or changed by the compiler during optimizations.
it is also worth noting that when you write more asm volatiles

Code: Select all

asm volatile("opcode-a");
asm volatile("opcode-b");
they may be relocated so it's better to write asm volatile("opcode-a \n opcode-b").

as for the example code I believe it would work better as
__asm volatile("inb %1,%0" : "=a"(ret_val) : "d"(port));
at least in gcc it would do so.
There are a few good online resources on inline assembly and what the %1 mean, worth reading.

Re: Bloody Beginner 2: __asm volatile

Posted: Wed Jul 09, 2008 4:00 pm
by cr2
__asm volatile is inline assembly in gcc.

usage:

__asm volatile (command : output : input : registers to save/push);

your example (__asm volatile("inb %w1,%b0" : "=a"(ret_val) : "d"(port));) would translate as...

Code: Select all

mov port, edx
inb edx, eax
mov eax, ret_val
or in intel syntax:

Code: Select all

mov edx, port
in  eax, edx
mov ret_val, eax
NOTE: I am not familiar with __asm volatile (I am using visual c++), so I may be off a little bit.)

EDIT: added NOTE, and cleaned up some errors...
...and adek336 beat me to posting. :(
EDIT 2: [EDITED OUT]
EDIT 3: Edited out EDIT 2.
EDIT 4: changed post according to hpclutz's observations

Re: Bloody Beginner 2: __asm volatile

Posted: Wed Jul 09, 2008 4:07 pm
by hpclutz
Aaaah, that
__asm volatile (command : output : input : registers to save/push);
was very helpful indeed, thanks a lot :)

And, yes, I know assembly code, so I can understand what's going on ;) Wouldn't it be
mov edx, port
in eax, edx
mov ret_val, eax
though?

Finally, got any idea, why I get the error message?
(PS I use Visual C++ too)

Cheers

Re: Bloody Beginner 2: __asm volatile

Posted: Wed Jul 09, 2008 4:19 pm
by cr2
hpclutz wrote:
And, yes, I know assembly code, so I can understand what's going on Wouldn't it be
mov edx, port
in eax, edx
mov ret_val, eax
though?
Thanks. :D
hpclutz wrote:(PS I use Visual C++ too)
in that case, you shouldn't be using __asm volatile (it's used in gcc), but instead use(this should solve your error):

Code: Select all

_asm
{
(INTEL SYNTAX assembly code)
}

Re: Bloody Beginner 2: __asm volatile

Posted: Wed Jul 09, 2008 8:31 pm
by PatrickV
yup you are back again. I just bit mind wondering? have you tried a simpler lanaquage first like nasm?

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 1:58 am
by pcmattman
have you tried a simpler lanaquage first like nasm?
NASM isn't a language! It's an assembler! Visual C++ isn't a language either - and yes, it's compiler can compile C code, and you can create a kernel with it.

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 4:00 am
by hpclutz
:lol: I like the discussion about what's a language and what's a compiler ;) I think the question really was why do you use assembly code instead of C? Some things have to be done in assembly code, I'm afraid (at least as far as I understand (which is not a lot ;) ))

With respect to assembly code, can somebody help me with the inb / outb syntax - it seems my compiler always throws an error and I couldn't find a good description on the web. http://maven.smith.edu/~thiebaut/ArtOfA ... ofasm.html is a good book, but it's very difficult to browse ;)

Thanks for all your answers so far - very helpful!

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 4:59 am
by Adek336
how about

Code: Select all

char inb(short port) {
 char val;
    __asm { 
       inb port, al
       mov al, val
}
return val;
}

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 5:37 am
by hpclutz
Thanks, I tried something like that, but it only gives me a "syntax error in 'opcode' found 'port'", respectively 'al'. I also read somewhere that inb takes register edx as port - but
inb al
only gives me syntax error in opcode found al...

I tried different combinations, but it seems "inb" will not accept any of my opcodes and assuming that it will automatically load ax just leads to complaint that an opcode is missing :?

That's why I wondered whether anybody knows the correct syntax (and, just for kicks: in Visual C++ of course ;) )

Update: "in ax, dx" seems to work (?)

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 5:43 am
by pcmattman
Not 100% sure, but try this:

Code: Select all

char inb(short port) {
    char val;
    __asm {
       inb dx
       mov val, dx
    }
    return val;
}

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 5:58 am
by hpclutz
Cheers, but this way I would not assign the port to a register. Given that "in" at least compiles (see above) as opposed to "inb" I assume that the assembly compiler of Visual simply doesn't know "inb" ;)

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 7:37 am
by Zenith
That's because 'inb' with the b prefix only occurs in AT&T syntax. (You'll notice that 'inb', 'inw', and co. don't appear in the Intel manuals, just the base operand 'in') Visual Studio's assembly compiler is MASM (IIRC), so it uses MASM (Intel) Syntax. which doesn't require these suffixes.

Replace pcmattman's 'inb' with 'in' and the code should work.

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 9:38 am
by Adek336
That code still need a tweak because it would do an inw - read 2 bytes from the port and discard one of them so how about

Code: Select all

char inb(short port) {
    char val;
    __asm {
       mov dx, port
       in al
       mov val, al
    }
    return val;
}

Re: Bloody Beginner 2: __asm volatile

Posted: Thu Jul 10, 2008 1:13 pm
by cr2
adek336 wrote: That code still need a tweak because it would do an inw - read 2 bytes from the port and discard one of them so how about

Code: Select all

char inb(short port) {
    char val;
    __asm {
       mov dx, port
       in al
       mov val, al
    }
    return val;
}
wouldn't it be:

Code: Select all

char inb (short port) {
     char val;
     __asm {
          mov dx, port
          in  eax, dx
          mov val, al
     }
     return val;
}