Сначала - компилятор с языка ассемблера (мнемокода) Y86, yas.
В отличие от авторов книги, которые совершенствуют свой курс в университете Карнеги-Мелона на протяжении 20 лет, у нас не было столько времени ... ассемблер нужно было сделать в 3-4 дня.
в C++.
Код: Выделить всё
static struct comnd { // общее для всех программ описание набора команд
string mnemo;
int cod, length, ops;
string pattern; // регулярное выражение синтаксиса
const void* func;
} comnds[] = {
{ "nop" , 0x00, 1, 0, // nop
R"(^\s*(nop)\s*(#.*)?$)" },
{ "halt" , 0x10, 1, 0, // halt
R"(^\s*(halt)\s*(#.*)?$)" },
{ "rrmovl", 0x20, 2, 1, // rrmovl rA, rB
R"(^\s*(rrmovl)\s+%e(ax|cx|dx|bx|sp|bp|si|di)\s*,\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" },
{ "irmovl", 0x30, 6, 2, // irmovl D, rB
R"(^\s*(irmovl)\s+(\w+|\$[\+|\-]?[0-9]+|\$0x[0-9|a-f]+)\s*,\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" },
{ "rmmovl", 0x40, 6, 2, // rmmovl rA, D(rB)
R"(^\s*(rmmovl)\s+%e(ax|cx|dx|bx|sp|bp|si|di)\s*,\s*([\+|\-]?[0-9]+|0x[0-9|a-f]+)*\s*\(\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*\)\s*(#.*)?$)" },
{ "mrmovl", 0x50, 6, 2, // mrmovl D(rB), rA
R"(^\s*(mrmovl)\s+([\+|\-]?[0-9]+|0x[0-9|a-f]+)*\s*\(\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*\)\s*,\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" },
{ "addl" , 0x60, 2, 2, // addl rA, rB
R"(^\s*(addl)\s+%e(ax|cx|dx|bx|sp|bp|si|di)\s*,\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" },
{ "subl" , 0x61, 2, 2, // subl rA, rB
R"(^\s*(subl)\s+%e(ax|cx|dx|bx|sp|bp|si|di)\s*,\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" },
{ "andl" , 0x62, 2, 2, // andl rA, rB
R"(^\s*(andl)\s+%e(ax|cx|dx|bx|sp|bp|si|di)\s*,\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" },
{ "xorl" , 0x63, 2, 2, // xorl rA, rB
R"(^\s*(xorl)\s+%e(ax|cx|dx|bx|sp|bp|si|di)\s*,\s*%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" },
{ "jmp" , 0x70, 5, 1, // jmp A
R"(^\s*(jmp)\s+(\w+)\s*(#.*)?$)" },
{ "jle" , 0x71, 5, 1, // jle A
R"(^\s*(jle)\s+(\w+)\s*(#.*)?$)" },
{ "jl" , 0x72, 5, 1, // jl A
R"(^\s*(jl)\s+(\w+)\s*(#.*)?$)" },
{ "je" , 0x73, 5, 1, // je A
R"(^\s*(je)\s+(\w+)\s*(#.*)?$)" },
{ "jne" , 0x74, 5, 1, // jne A
R"(^\s*(jne)\s+(\w+)\s*(#.*)?$)" },
{ "jge" , 0x75, 5, 1, // jge A
R"(^\s*(jge)\s+(\w+)\s*(#.*)?$)" },
{ "jg" , 0x76, 5, 1, // jg" A
R"(^\s*(jg)\s+(\w+)\s*(#.*)?$)" },
{ "call" , 0x80, 5, 1, // call A
R"(^\s*(call)\s+(\w+)\s*(#.*)?$)" },
{ "ret" , 0x90, 1, 0, // ret
R"(^\s*(ret)\s*(#.*)?$)" },
{ "pushl" , 0xA0, 2, 1, // pushl ra
R"(^\s*(pushl)\s+%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" },
{ "popl" , 0xB0, 2, 1, // popl ra
R"(^\s*(popl)\s+%e(ax|cx|dx|bx|sp|bp|si|di)\s*(#.*)?$)" }
};
const int ncomnd = sizeof( comnds ) / sizeof( struct comnd );
- этот файл будет include и в ассемблер yas и в симулятор yis в неизменном виде, за счёт этого при дополнении набора команд не возникнет несоответствие их версий;
- растипизированное (void*) поле func будет в одном случае (yas.cc) содержать функцию генерации компилированного кода, а в другом (yis.cc) - ссылку на объект класса функтора выполнения (производного от абстрактного класса command, содержащего переопределённый оператор () ).