Page 1 of 1

inline asm question

Posted: Tue Apr 08, 2008 1:07 am
by junkoi
Hi,

I am writing some inline asm with gcc (on Linux), in which I want to call an BIOS interrupt. The code is like below:

Code: Select all

void call_int(unsigned char x)
{
    asm (
    "int %0 \n"                                                                      
    : 
    : "r"  (x)                                                                   
    :
    );      
}
Basically I want to execute an interrupt by calling "call_int" with a given interrupt vector number as its parameter.

But I got an syntax compile error like "expected string literal before ')' token". How can I fix this?

Sorry that I have very little experience with inline asm. After reading a lot, still I cannot figure out where the problem lies.

And BTW, is there any better code for the my inline asm function? (Perhaps I dont need to have "r" like above?)

Thanks,
Jun

Posted: Tue Apr 08, 2008 1:50 am
by JamesM
Hi,

There are several problems here.

- I'm not sure where exactly your syntax error stems from, because you didn't post the error in full, however I do know that the '\n' is not required.

- the "int" instruction takes an immediate operand. That is, one which is known at compile time. You cannot use a register value for it.

- All inline asm statements, as a rule, should be declared volatile.

- You're writing C code and expecting it to emit 16-bit asm, on a linux box. How you've managed it I don't know because a lot of people here have tried and failed (I think borland (?) was the only compiler that worked in 16 bit mode). Be careful. Double check everything with a disassembler.

Cheers,

James

Posted: Tue Apr 08, 2008 7:19 am
by Zenith
What I would do is just put this inline assembly into the same function as the others and put the line in when you need it so that you don't have to deal with the immediate operand issue and the overhead of calling a seperate function.

Something like:

Code: Select all

asm volatile ("int $<number>");
whenever you need it.

But if you're calling the interrupt, you're also setting some registers (like AX) and calling the function will change those registers due to C's calling convention. So also remember to include the register setting stuff in the same piece of inline assembly.

PS: The error was caused because "r" (x) should have been "r"(x)

Posted: Tue Apr 08, 2008 8:13 am
by JamesM
PS: The error was caused because "r" (x) should have been "r"(x)
Uhhh, no - you're allowed spaces between the operand type and the operand name.

Posted: Tue Apr 08, 2008 8:32 am
by devel
Last colon shall be omitted.

Posted: Tue Apr 08, 2008 7:45 pm
by junkoi
karekare0 wrote:What I would do is just put this inline assembly into the same function as the others and put the line in when you need it so that you don't have to deal with the immediate operand issue and the overhead of calling a seperate function.

Something like:

Code: Select all

asm volatile ("int $<number>");
whenever you need it.

But if you're calling the interrupt, you're also setting some registers (like AX) and calling the function will change those registers due to C's calling convention. So also remember to include the register setting stuff in the same piece of inline assembly.

PS: The error was caused because "r" (x) should have been "r"(x)
I turn my code into a macro, so I can use it to execute any interrupt number. Thanks for the ideas.

J

Posted: Tue Apr 08, 2008 7:47 pm
by junkoi
JamesM wrote:,

- You're writing C code and expecting it to emit 16-bit asm, on a linux box. How you've managed it I don't know because a lot of people here have tried and failed (I think borland (?) was the only compiler that worked in 16 bit mode).
The ".code16gcc" directive is the key here. It works perfectly.

The boot code in Linux was rewritten recently using .code16gcc. You might want to take a look.

Thanks,
Jun