Archived

This topic is now archived and is closed to further replies.

_asm {} with gcc

This topic is 5814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am trying to use the following function with gcc in RH linux. It works in DOS, but won''t compile with gcc. void Mode13H(void) { _asm { mov AX, 0013H int 10H } } Can anyone tell me how to properly insert inline assembly into my linux programs when compiling with gcc? Thanks.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
i didn''t think you were supposed to use an underscore (although I haven''t used inline assembly much, so I dunno for sure)
try:
  
void Mode13H(void) {
asm {
mov AX, 0013H
int 10H
}
}

Share this post


Link to post
Share on other sites
GCC has a different asm-syntax than most other x86 compilers/assemblers. It uses the AT&T syntax as opposed to the Intel syntax. You should write something like:

__asm__
(
"movw $0x13,%%ax\n"
"int $0x10\n"
);

My AT&T syntax is a bit rusty, but I think it should work. (You can use simply 'asm' instead of '__asm__' if you prefer.)

Edited by - Dactylos on January 9, 2002 3:27:56 PM

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Well, aside from not using AT&T syntax, the most obvious thing to me is you cannot use DOS interrupts in linux. In order to go that low level, you either have to use libc functions or write your own kernel module.

Share this post


Link to post
Share on other sites
libc is just another piece of user level software, so it can''t execute interrupts, either.
Yes, int 10h is a BIOS interrupt, although it''s probably routed through by many TSRs (including DOS itself, though I''m not sure). Still, there''s no accessing real mode interrupts from a proper protected mode OS like Linux.

Anyway, gcc inline assembly is horrible. The code above would have to look like this:

  
asm(
"movw $0x13,%%ax\n" /* actual assembly */
"int $0x10\n"
: /* output registers */
: /* input registers */
: "ax" /* modified registers */

);


The actual assembly isn''t touched by gcc at all: It''s just inlined into gcc''s assembly output. This is one of the more ugly aspects of inlining in gcc, as you''ll only get useless assembler messages if your assembly is wrong (i.e. line numbers are wrong, etc...)

Because gcc doesn''t touch the actual assembly, you need to tell it about the registers used in the assembly - otherwise the optimizer will screw up the code.
I can never remember the exact syntax of those out/in register parts though: Normally, I just look into the linux/arch/i386 tree of the kernel source whenever I need to write inline assembly

Oh, and the AT&T syntax is another problem. Arguments are the other way round, mnemonics have an added size indicator (e.g. movl for 4byte ops, movw for short ops and movb for byte ops). Also, constants are prefixed by a $, and registers are prefixed by a %.

Oh, and gcc does some kind of formatting to the assembly string: If you put %0 somewhere, it''ll be replaced by the register which is first named in the out/in/mod sections. You could rewrite the code above as:

  
asm(
"movw $0x13,%0\n" /* actual assembly */
"int $0x10\n"
: /* output registers */
: /* input registers */
: "ax" /* modified registers */

);


Obviously, you can use %1, %2 etc... for additional registers.

Have fun *grins*

cu,
Prefect

One line of sourcecode says more than a thousand words.

Share this post


Link to post
Share on other sites
OK, well I can officially say that my days of incoporating inline assembly directly into my linux C programs are over before they even started.

So the next question would be this:
What would be the easiest way to enter mode 13H from linux?

I wasn''t using the assembly for speed of course, I was just using it because its the only way I know how to enter mode 13H.

Share this post


Link to post
Share on other sites
there probably is a "int86" function that allows you to call MS-DOS interrupts from your "c" program. check for a "dos.h" in the include files.

To the vast majority of mankind, nothing is more agreeable than to escape the need for mental exertion... To most people, nothing is more troublesome than the effort of thinking.

Share this post


Link to post
Share on other sites
If memory servies me correctly, int 10h is the video interrupt. If you get it to work without completely screwing up the system, you''ll need to chown the program to root.

Low-level stuff on any UNIX type system is generally a Bad Thing (tm).

I''m guessing you''re trying to set the video mode? If so, use SVGAlib for it. It offers pretty much everything you''ll need to do, without having to get your hands icky with the screwed up AT&T asm syntax.

Share this post


Link to post
Share on other sites
SVGALib is dead. Of course you could use it just to play around, but seriously using it is a bad idea. You''d better use something like SDL ( http://www.libsdl.org/ ), which is even cross-platform.

cu,
Prefect

Share this post


Link to post
Share on other sites
(This also serves as notice that I''ve returned from an unexpected and forced absence - no access while I was in MD)

In addition to Prefect''s excellent suggestions, you might want to look into framebuffer work under Linux. Generally, though, SDL is a much less painful way to obtain high-res graphics in a variety of modes.

Could Mode 13H just die ?

As for assembly/inline assembly under unices in general, I have no experience with it but there are many who do. Search Google.com/linux for references. You might also want to learn GAS syntax so you can develop pure assembly modules and link to your C applications. The skills are worth the effort.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!

Share this post


Link to post
Share on other sites