Компилятор я написал всего за 2 часа. PDP-11 действительно простой ассемблер. И написал простую демку.
(Надпись двигается вверх-вниз)

Под катом моя программа и кусок компилятора (самый важный).
Программ для БК
ORG 01000
START: MOV #040000, R3
LOOP0: MOV #185, R4
LOOP1: JSR R5, @#DRAW
ADD #64, R3
SOB R4, LOOP1
MOV #185, R4
LOOP2: SUB #64, R3
JSR R5, @#DRAW
SOB R4, LOOP2
BR LOOP0
;-----------------------------------------------
DRAW: MOV #BMP, R0
MOV R3, R1
MOV #568, R2
LOOP3: MOV (R0)+, (R1)+
MOV (R0)+, (R1)+
MOV (R0)+, (R1)+
MOV (R0)+, (R1)+
SOB R2, LOOP3
RTS R5
;-----------------------------------------------
BMP: insert_file "img.bin", 0, 4544
;-----------------------------------------------
END: make_bk0010_rom "test.bin", START, END
Стянуть бинарник http://rghost.ru/36818139
Кусок компилятора:
struct Arg {
int ext, code;
bool needExt;
};
struct SimpleCommand {
const char* name;
int code;
};
struct ImmCommand {
const char* name;
int code, max;
};
int readReg() {
static const char* regs[] = { "R0","R1","R2","R3","R4","R5","SP","PC",0 };
return p.needToken(regs);
}
bool readAddr() {
int n;
if(p.ifToken(labelName, n)) { p.bufInt=labelOff[n]; return true; }
if(p.ifToken(ttString1)) { p.bufInt = p.buf[0]; return true; }
return p.ifToken(ttInteger);
}
void readArg(Arg& a) {
int mode, reg;
bool x = p.ifToken("@");
bool n = p.ifToken("#");
if(readAddr()) {
a.ext = p.bufInt;
a.needExt = true;
if(!n && p.ifToken("(")) {
mode = 6;
reg = readReg();
p.needToken(")");
} else {
reg = 7;
mode = n ? 2 : 6;
}
if(x) mode++;
a.code = (mode<<3) | reg;
return;
}
if(n) p.syntaxError();
bool d = p.ifToken("-");
a.needExt = false;
if(!d) {
if(readAddr())
a.needExt=true, a.ext=p.bufInt;
}
bool o = p.ifToken("("); if((x || d || a.needExt) && !o) p.needToken("(");
reg = readReg();
if(o) p.needToken(")");
bool i = false;
if(o && (!d && !a.needExt)) i = p.ifToken("+");
if(x && !d && !i && !a.needExt) { a.needExt=true; a.ext=0; }
mode = !o ? 0 : i ? 2 : d ? 4 : a.needExt ? 6 : 1;
if(x) mode++;
a.code = (mode<<3) | reg;
}
void compileCpuCommand() {
// Комманды без аргументов
static SimpleCommand simpleCommands[] = {
"halt", 0, "wait", 1, "rti", 2, "bpt", 3, "iot", 4, "reset", 5, "rtt", 6, "nop", 0240,
"clc", 0241, "clv", 0242, "clz", 0244, "cln", 0250, "sec", 0261, "sev", 0262,
"sez", 0264, "sen", 0270, "scc", 0277, "ccc", 0257, 0
};
if(p.ifToken(simpleCommands, n)) {
write(simpleCommands[n].code);
return;
}
// Комманды с одним регистром
static SimpleCommand oneCommands[] = {
"jmp", 00001, "swab", 00003,
"clr", 00050, "clrb", 01050, "com", 00051, "comb", 01051,
"inc", 00052, "incb", 01052, "dec", 00053, "decb", 01053,
"neg", 00054, "negb", 01054, "adc", 00055, "adcb", 01055,
"sbc", 00056, "sbcb", 01056, "tst", 00057, "tstb", 01057,
"ror", 00060, "rorb", 01060, "rol", 00061, "rolb", 01061,
"asr", 00062, "asrb", 01062, "asl", 00063, "aslb", 01063,
"sxt", 00067, "mtps", 01064, "mfps", 01067, 0
};
if(p.ifToken(oneCommands, n)) {
Arg a;
readArg(a);
write((oneCommands[n].code<<6)|a.code);
if(a.needExt) write(a.ext);
return;
}
// Комманды перехода
static SimpleCommand jmpCommands[] = {
"br", 00004, "bne", 00010, "beq", 00014, "bge", 00020, "blt", 00024,
"bgt", 00030, "ble", 00034, "bpl", 01000, "bmi", 01004, "bhi", 01010,
"bvc", 01024, "bhis", 01030, "bcc", 01030, "blo", 01034, "bcs", 01034,
"blos", 01014,
0
};
if(p.ifToken(jmpCommands, n)) {
int i = needAddr();
i-=writePos+2;
if(i&1) p.syntaxError("unaligned");
i/=2;
if(step2 && (i<-128 || i>127)) p.syntaxError();
write((jmpCommands[n].code<<6) | (i&0xFF));
return;
}
// Комманды с константой
static ImmCommand immCommands[] = {
"emt", 0104000, 0377, "trap", 104400, 0377, "mark", 0006400, 077, 0
};
if(p.ifToken(immCommands, n)) {
int i = p.needInteger();
if(i<0 || i>immCommands[n].max) p.syntaxError();
write(immCommands[n].code | i);
return;
}
// Комманды с двумя регистрами
static const char* twoCommands[] = {
"", "mov", "cmp", "bit", "bic", "bis", "add", "", "",
"movb", "cmpb", "bitb", "bicb", "bisb", "sub", 0
};
if(p.ifToken(twoCommands, n)) {
Arg src, dest;
readArg(src);
p.needToken(",");
readArg(dest);
write((n<<12)|(src.code<<6)|dest.code);
if(src.needExt) write(src.ext);
if(dest.needExt) write(dest.ext);
return;
}
// Остальные команды
if(p.ifToken("jsr")) {
int r = readReg();
p.needToken(",");
Arg a;
readArg(a);
write(004000 | (r<<6) | a.code);
if(a.needExt) write(a.ext);
return;
}
if(p.ifToken("sob")) {
int r = readReg();
p.needToken(",");
int n = (writePos + 2) - needAddr();
if(n&1) p.syntaxError();
n/=2;
if(n<0 || n>63) p.syntaxError();
write(0077000 | (r<<6) | (n&077));
return;
}
if(p.ifToken("rts")) {
int r = readReg();
write(0000200 | r);
return;
}
p.syntaxError();
}
(В этом коде обязаны быть ошибки. В некоторые моменты PDD11 я еще не въехал.)

2012-03-03 05:04 am (UTC)
2012-03-03 11:27 am (UTC)
2012-03-04 06:06 am (UTC)
2012-03-03 02:00 pm (UTC)
Тяжело мне давались только процедурки на прерывании IM2. А на 128k ОЗУ впервые понял как работает страничная адресация (после 49152 адреса были страницы, если не ошибаюсь).
Edited at 2012-03-03 02:02 pm (UTC)
2012-03-03 04:54 pm (UTC)
2012-03-03 05:33 pm (UTC)
2012-03-03 06:06 am (UTC)
Edited at 2012-03-03 06:13 am (UTC)
2012-03-03 02:39 pm (UTC)
2012-03-03 06:53 am (UTC)
PS заведите себе для расшаривания и хранения файлов dropbox. рекомендую.
2012-03-03 02:36 pm (UTC)
2012-03-03 02:54 pm (UTC)
Получите на 250Мб больше.
2012-03-03 11:26 am (UTC)
2012-03-03 02:36 pm (UTC)
2012-03-03 02:48 pm (UTC)
2012-03-03 11:38 am (UTC)
2012-03-03 12:55 pm (UTC)
2012-03-03 01:09 pm (UTC)
2012-03-03 02:35 pm (UTC)
Но самое необычное, что можно записывать данные к константы.
MOV #12, R0 // Записать число 12 в регистр R0
MOV #12, #4 // Записать число 12 в число 4
2012-03-03 02:51 pm (UTC)
это и есть теория ограниченного применения
Edited at 2012-03-03 02:53 pm (UTC)
2012-03-03 02:56 pm (UTC)
2012-03-03 03:00 pm (UTC)
что унаших коопий амереканских чипов врали и они
хотя такого даже я не встречал
2012-03-03 04:28 pm (UTC)
2012-03-05 10:46 am (UTC)
таким образом вместо разработки наших моделей начели повальное капирование западных аналогов,
Я не знаю правда это или нет ,Но легенда красивая
2012-04-15 03:38 pm (UTC)
2012-04-17 09:38 am (UTC)
2012-03-03 02:54 pm (UTC)
2012-04-15 03:45 pm (UTC)
MOV #12, #4
фактически представляется как
MOV (R7)+, (R7)+
.#12
.#4
команда возьмет число из ячейки с адресом в R7 (это будет 12), инкрементировав R7 и положит в ячейку с адресом R7 (ячейка со значением 4) и снова инкрементирует R7. Фактически - пример самомодифицирующегося кода.
2012-03-03 02:49 pm (UTC)
2014-02-26 05:22 am (UTC)
Меня очень интересует этот ваш компилятор, он есть в каком нибудь "релизном" варианте?