Bloody Beginner 2: __asm volatile

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
hpclutz
Posts: 19
Joined: Tue Jul 08, 2008 11:30 am

Bloody Beginner 2: __asm volatile

Post 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 :?
User avatar
Adek336
Member
Member
Posts: 129
Joined: Thu May 12, 2005 11:00 pm
Location: Kabaty, Warszawa
Contact:

Re: Bloody Beginner 2: __asm volatile

Post 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.
User avatar
cr2
Member
Member
Posts: 162
Joined: Fri Jun 27, 2008 8:05 pm
Location: ND, USA

Re: Bloody Beginner 2: __asm volatile

Post 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
Last edited by cr2 on Wed Jul 09, 2008 4:23 pm, edited 4 times in total.
OS-LUX V0.0
Working on...
Memory management: the Pool
hpclutz
Posts: 19
Joined: Tue Jul 08, 2008 11:30 am

Re: Bloody Beginner 2: __asm volatile

Post 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
User avatar
cr2
Member
Member
Posts: 162
Joined: Fri Jun 27, 2008 8:05 pm
Location: ND, USA

Re: Bloody Beginner 2: __asm volatile

Post 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)
}
OS-LUX V0.0
Working on...
Memory management: the Pool
PatrickV
Member
Member
Posts: 151
Joined: Sun Jul 06, 2008 7:50 pm
Location: New Zealand
Contact:

Re: Bloody Beginner 2: __asm volatile

Post by PatrickV »

yup you are back again. I just bit mind wondering? have you tried a simpler lanaquage first like nasm?
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Bloody Beginner 2: __asm volatile

Post 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.
hpclutz
Posts: 19
Joined: Tue Jul 08, 2008 11:30 am

Re: Bloody Beginner 2: __asm volatile

Post 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!
User avatar
Adek336
Member
Member
Posts: 129
Joined: Thu May 12, 2005 11:00 pm
Location: Kabaty, Warszawa
Contact:

Re: Bloody Beginner 2: __asm volatile

Post by Adek336 »

how about

Code: Select all

char inb(short port) {
 char val;
    __asm { 
       inb port, al
       mov al, val
}
return val;
}
hpclutz
Posts: 19
Joined: Tue Jul 08, 2008 11:30 am

Re: Bloody Beginner 2: __asm volatile

Post 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 (?)
Last edited by hpclutz on Thu Jul 10, 2008 5:50 am, edited 1 time in total.
pcmattman
Member
Member
Posts: 2566
Joined: Sun Jan 14, 2007 9:15 pm
Libera.chat IRC: miselin
Location: Sydney, Australia (I come from a land down under!)
Contact:

Re: Bloody Beginner 2: __asm volatile

Post 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;
}
hpclutz
Posts: 19
Joined: Tue Jul 08, 2008 11:30 am

Re: Bloody Beginner 2: __asm volatile

Post 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" ;)
User avatar
Zenith
Member
Member
Posts: 224
Joined: Tue Apr 10, 2007 4:42 pm

Re: Bloody Beginner 2: __asm volatile

Post 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.
"Sufficiently advanced stupidity is indistinguishable from malice."
User avatar
Adek336
Member
Member
Posts: 129
Joined: Thu May 12, 2005 11:00 pm
Location: Kabaty, Warszawa
Contact:

Re: Bloody Beginner 2: __asm volatile

Post 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;
}
User avatar
cr2
Member
Member
Posts: 162
Joined: Fri Jun 27, 2008 8:05 pm
Location: ND, USA

Re: Bloody Beginner 2: __asm volatile

Post 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;
}
OS-LUX V0.0
Working on...
Memory management: the Pool
Post Reply