x86程序集:使用#define'd常量作为调用#define宏的参数

时间:2013-01-31 16:29:57

标签: c gcc assembly macros x86

我正在努力在x86程序集中手动构建IDT表。我在.S文件中使用C预处理器定义了以下宏:

// sets up an entry in the idt for a trap type
#define SETUP_IDT_ENTRY( name, num, istrap, segment, dpl ) \
    lea name, %edx; \
    movl $(KCODE << 16), %eax; \
    movw $0x8e00, %dx; \
    lea (idt + (8 * num)), %edi; \
    movl %eax, (%edi); \
    movl %edx, 4(%edi);

// sample set of args to a call to setup_dt_entry
#define M_DIVIDE _t_divide_ep, T_DIVIDE, 0, KCODE, 0

// the call
SETUP_IDT_ENTRY( M_DIVIDE )

然而,gcc抱怨:error: macro "SETUP_IDT_ENTRY" requires 5 arguments, but only 1 given

我认为#define'd函数的#define'd参数在评估函数调用之前已经扩展,在这种情况下M_DIVIDE会扩展为所需的五个参数,SETUP_IDT_ENTRY会很高兴。我尝试了各种括号组合,似乎没有任何工作;有没有办法使这项工作?

注意:我知道在x86程序集中有另外的方法来构建IDT,但这不是我想在这里回答的问题;我只想弄清楚宏是否可以扩展为宏参数。

2 个答案:

答案 0 :(得分:4)

参数本身已扩展,但参数的数量必须与宏定义匹配。你需要一个额外的宏来使它工作:

#define IDT1(x) SETUP_IDT_ENTRY(x)

IDT1(M_DIVIDE)

更多信息herehere

答案 1 :(得分:2)

可以使用另一层间接来完成:

#define PLEASE_SETUP_IDT_ENTRY(...) SETUP_IDT_ENTRY(__VA_ARGS__)
// the delicate, civilized call
PLEASE_SETUP_IDT_ENTRY(M_DIVIDE)

(如果我们想要一个新变量接受一个且只有一个参数,则不需要Variadic宏。上面的定义接受一个多个参数)。