views:

195

answers:

2

We are working on a toy operating system as a assignment for a class. I'm having some trouble with writing of the kernel panic function.

It should save all registers, call some printf-like function, then print the saved registers and halt the cpu. Right now it's defined as a macro:

#define panic(...) \
    do{ \
        asm volatile("SAVE_REGISTERS %1\n\t" : "m="(_panic_context)); \
        _panic_printk(&_panic_context, __VA_ARGS__); \
    while(0)

_panic_context is a global variable that contains saved registers of a thread and some more stuff. The problem is with SAVE_REGISTERS. It is a macro defined somewhere in an assembler header file, but I don't know how to include it. Simple #include in the file obviously doesn't work. I've tried googling and writing funny and desperate stuff (like #include in the assembler strings :-) ) but nothing helped. Do you have any ideas how to solve this?

We're using GCC and compile for MIPS (running in a simulator :-) )

edit: SAVE_REGISTERS is defined with .macro SAVE_REGISTERS... . It can't be in a C macro, because it's used in other assembly modules. I can't make a .S file with it, because panic has to be variadic. Or at least I couldn't come up with any other way to do it.

A: 

I don't have a MIPS system lying around, but on my x86 loonix box I tried #include and discovered that # is the comment character, so I tried .include and that worked as soon as I quoted the file name: .include "something.i".

Now, if you have header files and an organized infrastructure for assembler code, I have to wonder why you want to do this with inline asm in the first place, though. Why not just make a real .s or .S file, include the assembler header file, and make it a first-class module in your system?

I've seen small masterpieces done with asm even in projects that already had a locore.S in their Makefile, go figure...

DigitalRoss
+2  A: 

I think you're misunderstanding how macros work. They get expanded before any other compiling happens. You can't use asm to emit some code which contains a macro because that macro will never be expanded.

Instead you might try defining SAVE_REGISTERS as a C macro which uses the asm statement to build your assembly code:

#define SAVE_REGISTERS(x) \
   asm volatile ("movx ax, %1", ...);

then you can do

#define panic(...) \
do { \
    SAVE_REGISTERS(_panic_context); \
    _panic_printk(&_panic_context, __VA_ARGS__); \
} while(0);
Mark Pim
The dummy do-loop is to make sure there's a semicolon after the macro, methinks.
Michael Myers
The dummy do-loop is a common technique in multi-statement macros that makes them behave well when used in `if` statements, for example. It should be left in the macro (but the closing brace should be added). See http://stackoverflow.com/questions/154136/why-are-there-sometimes-meaningless-do-while-and-if-else-statements-in-c-c-macr
Michael Burr
Ah OK, I wasn't aware of that convention. Edited the answer. Thanks.
Mark Pim