inline asm question

Programming, for all ages and all languages.
Post Reply
junkoi
Member
Member
Posts: 63
Joined: Wed Jan 23, 2008 8:55 pm

inline asm question

Post 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
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

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

Post 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)
"Sufficiently advanced stupidity is indistinguishable from malice."
User avatar
JamesM
Member
Member
Posts: 2935
Joined: Tue Jul 10, 2007 5:27 am
Location: York, United Kingdom
Contact:

Post 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.
User avatar
devel
Member
Member
Posts: 62
Joined: Wed Nov 28, 2007 4:15 am
Contact:

Post by devel »

Last colon shall be omitted.
junkoi
Member
Member
Posts: 63
Joined: Wed Jan 23, 2008 8:55 pm

Post 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
junkoi
Member
Member
Posts: 63
Joined: Wed Jan 23, 2008 8:55 pm

Post 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
Post Reply