• ### Announcements

#### Archived

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

# _asm {} with gcc

## 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 on other sites
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, 0013Hint 10H}}

##### 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 on other sites
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 on other sites
DOS does not own interrupts except its own software loadable ones. I think INT 10H is pretty much hard-wired into your system BIOS.

##### 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 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 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 on other sites
Okay, that last post must be a joke, or else he just hadn''t seen the instances of the name "Linux" sprinkled around in this thread.

##### 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 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 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 on other sites
I will eventually finish that article on using inline ASM in GCC ...

This is a reasonably good reference on the topic: http://www-106.ibm.com/developerworks/linux/library/l-ia.html?dwzone=linux

• ### Forum Statistics

• Total Topics
627701
• Total Posts
2978700

• 21
• 14
• 12
• 10
• 12