1

Couldn't exactly think up the right title for this, but this problem always seems to occur when I'm setting up const data for my program to use. My program here is basically a lightweight assembler as a small part of my custom code compiler.

CAssembler.h

struct sOperand
{
    bool used;
    eOperandType type;
    int size;
};

struct sOpcodeDefinition
{
    bool used;
    BYTE opcode;
    BYTE extended_opcode;
    sOperand operands[5];
};

struct sInstructionDefinition
{
    eMnemonicInstruction instruction;
    sOpcodeDefinition opcodes[16];
};

CAssembler.cpp

#define MNEMONIC(a,b) {a,b}
#define OPCODE(a,b,c) {true,OPCODE_##a,b,c}
#define OPERAND(a,b) {true,(eOperandType)OPERAND_##a,b}

sInstructionDefinition OpcodeDefinitionTable[NUM_X86_OPCODES] = {
    MNEMONIC(INC,
        OPCODE(INC_AX, 0, OPERAND(REGISTER_AX, 4)),
        OPCODE(INC_CX, 0, OPERAND(REGISTER_CX, 4)),
        OPCODE(INC_DX, 0, OPERAND(REGISTER_DX, 4)),
        OPCODE(INC_BX, 0, OPERAND(REGISTER_BX, 4)),
        OPCODE(INC_SP, 0, OPERAND(REGISTER_SP, 4)),
        OPCODE(INC_BP, 0, OPERAND(REGISTER_BP, 4)),
        OPCODE(INC_SI, 0, OPERAND(REGISTER_SI, 4)),
        OPCODE(INC_DI, 0, OPERAND(REGISTER_DI, 4))
        ),
    MNEMONIC(DEC,
        OPCODE(DEC_AX, 0, OPERAND(REGISTER_AX, 4)),
        OPCODE(DEC_CX, 0, OPERAND(REGISTER_CX, 4)),
        OPCODE(DEC_DX, 0, OPERAND(REGISTER_DX, 4)),
        OPCODE(DEC_BX, 0, OPERAND(REGISTER_BX, 4)),
        OPCODE(DEC_SP, 0, OPERAND(REGISTER_SP, 4)),
        OPCODE(DEC_BP, 0, OPERAND(REGISTER_BP, 4)),
        OPCODE(DEC_SI, 0, OPERAND(REGISTER_SI, 4)),
        OPCODE(DEC_DI, 0, OPERAND(REGISTER_DI, 4))
        ),
    MNEMONIC(PUSH,
        OPCODE(PUSH_AX, 0, OPERAND(REGISTER_AX, 4)),
        OPCODE(PUSH_CX, 0, OPERAND(REGISTER_CX, 4)),
        OPCODE(PUSH_DX, 0, OPERAND(REGISTER_DX, 4)),
        OPCODE(PUSH_BX, 0, OPERAND(REGISTER_BX, 4)),
        OPCODE(PUSH_SP, 0, OPERAND(REGISTER_SP, 4)),
        OPCODE(PUSH_BP, 0, OPERAND(REGISTER_BP, 4)),
        OPCODE(PUSH_SI, 0, OPERAND(REGISTER_SI, 4)),
        OPCODE(PUSH_DI, 0, OPERAND(REGISTER_DI, 4))
        ),
    MNEMONIC(POP,
        OPCODE(POP_AX, 0, OPERAND(REGISTER_AX, 4)),
        OPCODE(POP_CX, 0, OPERAND(REGISTER_CX, 4)),
        OPCODE(POP_DX, 0, OPERAND(REGISTER_DX, 4)),
        OPCODE(POP_BX, 0, OPERAND(REGISTER_BX, 4)),
        OPCODE(POP_SP, 0, OPERAND(REGISTER_SP, 4)),
        OPCODE(POP_BP, 0, OPERAND(REGISTER_BP, 4)),
        OPCODE(POP_SI, 0, OPERAND(REGISTER_SI, 4)),
        OPCODE(POP_DI, 0, OPERAND(REGISTER_DI, 4))
        ),
};

Obviouslly my aim is to have an array of sInstructionDefinition and fill their object array members, etc.

Unfortunately, the 2nd sOpcodeDefinition of each sInstructionDefinition is absent in the compiled code. I assume the same may start to happen with the sOperand members too. Any ideas why and what the proper way to initialize this large nested structure?

2 Answers 2

1

your MNEMONIC macro takes 2 arguments, yet you are providing 9. You probably intended to write:

   MNEMONIC(INC,
        {
        OPCODE(INC_AX, 0, {OPERAND(REGISTER_AX, 4)}),
        OPCODE(INC_CX, 0, {OPERAND(REGISTER_CX, 4)}),
        // etc..
        }
     ) // etc

Note that the curly braces in your opcode macro initialize the struct, while the extra braces in the code above are used to initialize the arrays.

Edit: note that the code above still does not work, since the preprocessor will still see the commas as argument delimiters.

Sign up to request clarification or add additional context in comments.

4 Comments

Ohh of course. Some overlooked stuff about the macros there. {} should be around the 2nd param of MNEMONIC. Big thanks, will test in a few mins...
Okay well that seemed like it would be right but I get actual errors/warnings now: Warning 1 warning C4002: too many actual parameters for macro 'MNEMONIC' error C2078: too many initializers
yep, the preprocessor sees the commas as argument separators. It gives no special meaning to {. I should have seen that. This means you would 1) have to resort to variadic macros or 2) use boost.preprocessor lists or 3) if there are always 8 opcodes create a 9-argument macro.
So any solution? Would I also have to initialize the members that aren't going to be used?
1

Found a nice solution using variadic macros... Odd how manually wrapping the OPCODE usages in { } didn't work, though. But now, the 2nd, 3rd, 4th, etc. sOpcodeDefinition definitions are compiled properly now.

#define MNEMONIC(a,...) {a,{__VA_ARGS__}}
#define OPCODE(a,b,...) {true,OPCODE_##a,b,{__VA_ARGS__}}
#define OPERAND(a,b) {true,(eOperandType)OPERAND_##a,b}
#define NULL_OPERAND {false,BAD_OPERAND,0}

sInstructionDefinition OpcodeDefinitionTable[NUM_MNEMONICS] = {
    MNEMONIC(INC,
        OPCODE(INC_AX, 0, OPERAND(REGISTER_AX, 4)),
        OPCODE(INC_CX, 0, OPERAND(REGISTER_CX, 4)),
        OPCODE(INC_DX, 0, OPERAND(REGISTER_DX, 4)),
        OPCODE(INC_BX, 0, OPERAND(REGISTER_BX, 4)),
        OPCODE(INC_SP, 0, OPERAND(REGISTER_SP, 4)),
        OPCODE(INC_BP, 0, OPERAND(REGISTER_BP, 4)),
        OPCODE(INC_SI, 0, OPERAND(REGISTER_SI, 4)),
        OPCODE(INC_DI, 0, OPERAND(REGISTER_DI, 4))
    ),
    MNEMONIC(DEC,
        OPCODE(DEC_AX, 0, OPERAND(REGISTER_AX, 4)),
        OPCODE(DEC_CX, 0, OPERAND(REGISTER_CX, 4)),
        OPCODE(DEC_DX, 0, OPERAND(REGISTER_DX, 4)),
        OPCODE(DEC_BX, 0, OPERAND(REGISTER_BX, 4)),
        OPCODE(DEC_SP, 0, OPERAND(REGISTER_SP, 4)),
        OPCODE(DEC_BP, 0, OPERAND(REGISTER_BP, 4)),
        OPCODE(DEC_SI, 0, OPERAND(REGISTER_SI, 4)),
        OPCODE(DEC_DI, 0, OPERAND(REGISTER_DI, 4))
    ),
    MNEMONIC(PUSH,
        OPCODE(PUSH_AX, 0, OPERAND(REGISTER_AX, 4)),
        OPCODE(PUSH_CX, 0, OPERAND(REGISTER_CX, 4)),
        OPCODE(PUSH_DX, 0, OPERAND(REGISTER_DX, 4)),
        OPCODE(PUSH_BX, 0, OPERAND(REGISTER_BX, 4)),
        OPCODE(PUSH_SP, 0, OPERAND(REGISTER_SP, 4)),
        OPCODE(PUSH_BP, 0, OPERAND(REGISTER_BP, 4)),
        OPCODE(PUSH_SI, 0, OPERAND(REGISTER_SI, 4)),
        OPCODE(PUSH_DI, 0, OPERAND(REGISTER_DI, 4))
    ),
    MNEMONIC(POP,
        OPCODE(POP_AX, 0, OPERAND(REGISTER_AX, 4)),
        OPCODE(POP_CX, 0, OPERAND(REGISTER_CX, 4)),
        OPCODE(POP_DX, 0, OPERAND(REGISTER_DX, 4)),
        OPCODE(POP_BX, 0, OPERAND(REGISTER_BX, 4)),
        OPCODE(POP_SP, 0, OPERAND(REGISTER_SP, 4)),
        OPCODE(POP_BP, 0, OPERAND(REGISTER_BP, 4)),
        OPCODE(POP_SI, 0, OPERAND(REGISTER_SI, 4)),
        OPCODE(POP_DI, 0, OPERAND(REGISTER_DI, 4))
    ),
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.