Search code examples
cassemblygccx86inline-assembly

How use INT %0 in inline asm with the interrupt number coming from a C variable?


I want to call the bios inline my c code. I tried asm("int %%al"::"a" (interrupt)); but gcc write Error: operand size mismatch for 'int'. I wonder that code work.


Solution

  • The int instruction must take its vector as an immediate; it has no form that takes the number from a register. See the instruction description; note that the second form is INT imm8 and there is nothing like INT r8 or INT r/m8 that would allow a register or memory operand.

    If interrupt can be evaluated as a compile-time constant then you may be able to do

    asm volatile("int %0" : : "i" (interrupt));
    

    Note that in order for the interrupt to do something useful, you probably have to load various values into registers beforehand, and retrieve the values returned. Those will need to be done as part of the same asm block, requiring more operands and constraints. You cannot put something like asm("mov $0x1a, %%ah"); in a preceding block; the compiler need not preserve register contents between blocks.

    If you truly don't know the interrupt number until runtime, your options are either to assemble all 256 possible int instructions and jump to the right one, or else use self-modifying code.