Главная » Процессор x86 » Портативный эмулятор 8086
§ portable86.cpp
Портативный код для запуска X86 везде.#define AX_ regs[0] #define CX_ regs[1] #define DX_ regs[2] #define BX_ regs[3] #define SP_ regs[4] #define BP_ regs[5] #define SI_ regs[6] #define DI_ regs[7] #define AL_ (regs[0]&255) #define CL_ (regs[1]&255) #define DL_ (regs[2]&255) #define BL_ (regs[3]&255) #define AH_ (regs[0]>>8) #define CH_ (regs[1]>>8) #define DH_ (regs[2]>>8) #define BH_ (regs[3]>>8) #define REPINC(a,b) { if (flags & D_FLAG) a-=b; else a+=b; } #define REPINIT { if (rep && CX_ == 0) break; } uint16_t flags; uint32_t rdtsc; enum FlagBit { C_FLAG = 0x0001, P_FLAG = 0x0004, A_FLAG = 0x0010, Z_FLAG = 0x0040, N_FLAG = 0x0080, T_FLAG = 0x0100, I_FLAG = 0x0200, D_FLAG = 0x0400, V_FLAG = 0x0800 }; enum RegsALL { REG_AX = 0, REG_AL = 0, REG_CX = 1, REG_CL = 1, REG_DX = 2, REG_DL = 2, REG_BX = 3, REG_BL = 3, REG_SP = 4, REG_AH = 4, REG_BP = 5, REG_CH = 5, REG_SI = 6, REG_DH = 6, REG_DI = 7, REG_BH = 7, }; enum SegID { SEG_ES = 0, SEG_CS = 1, SEG_SS = 2, SEG_DS = 3, SEG_FS = 4, SEG_GS = 5 }; enum Prefixes { REPNZ = 1, REPZ = 2 }; class portable86 { protected: uint8_t opcode, rmdat, cpu_reg, cpu_mod, cpu_rm, inhlt; uint8_t sel_seg, rep; uint16_t eaaddr; uint32_t segment; uint8_t znptable8[256]; // Специальная таблица с Z,S,P public: // 0 AX=AH:AL | 4 SP // 1 CX=CH:CL | 5 BP // 2 DX=DH:DL | 6 SI // 3 BX=BH:BL | 7 DI uint16_t regs[8]; uint16_t segs[6]; uint32_t seg_cs, seg_ss, seg_es, seg_ds, seg_fs, seg_gs; uint16_t ip, ip_start; uint32_t tstates; virtual uint8_t ioread(uint16_t a) { return 0; }; virtual void iowrite(uint16_t a, uint8_t b) { }; virtual uint8_t readmemb(uint32_t a) { return 0; }; virtual void writememb(uint32_t a, uint8_t b) { }; // Конструктор инициализирует данные portable86() { initcpu(); } // --------------------------------------------------------------------- // ПРОЦЕДУРЫ ДЛЯ АЛУ // --------------------------------------------------------------------- // Заполнение данными void initcpu() { unsigned char d, c = 0; do { d = (c>>4) ^ c; d = (d>>2) ^ d; d = (d>>1) ^ d; znptable8[c] = (d&1) ? 0 : P_FLAG; if (c == 0) znptable8[c] |= Z_FLAG; if (c&0x80) znptable8[c] |= N_FLAG; c++; } while (c != 0); loadcs(0xf000); loadds(0x0000); loades(0x0000); loadss(0x0000); ip = 0x0000; SP_ = 0x0000; AX_ = 0x0000; inhlt = 0; tstates = 0; } // Базовые флаги N,Z,P после 8-битных инструкции void setznp8(uint8_t val) { flags &= ~0xC4; flags |= znptable8[val]; } // Базовые флаги N,Z,P после 16-битных инструкции void setznp16(uint16_t val) { flags &= ~0xC4; if (val & 0x8000) flags |= N_FLAG; if (val == 0) flags |= Z_FLAG; flags |= (znptable8[val&0xff] & P_FLAG); } uint8_t setadd8(uint8_t a, uint8_t b) { uint16_t c = (uint16_t)a + (uint16_t)b; flags &= ~0x8D5; flags |= znptable8[c & 0xFF]; if (c & 0x100) flags |= C_FLAG; if (!((a^b)&0x80)&&((a^c)&0x80)) flags |= V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags |= A_FLAG; return c; } uint8_t setadd8nc(uint8_t a, uint8_t b) { uint16_t c = (uint16_t)a + (uint16_t)b; flags &= ~0x8D4; flags |= znptable8[c&0xFF]; if (!((a^b)&0x80)&&((a^c)&0x80)) flags |= V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags |= A_FLAG; return c; } uint8_t setadc8(uint8_t a, uint8_t b, uint8_t tempc) { uint16_t c = (uint16_t)a + (uint16_t)b + tempc; flags &= ~0x8D5; flags |= znptable8[c&0xFF]; if (c & 0x100) flags |= C_FLAG; if (!((a^b)&0x80)&&((a^c)&0x80)) flags |= V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags |= A_FLAG; return c; } uint16_t setadd16(uint16_t a, uint16_t b) { uint32_t c = (uint32_t)a + (uint32_t)b; flags &= ~0x8D5; setznp16(c & 0xffff); if (c & 0x10000) flags |= C_FLAG; if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags |= V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags |= A_FLAG; return c; } uint16_t setadd16nc(uint16_t a, uint16_t b) { uint32_t c = (uint32_t)a + (uint32_t)b; flags &= ~0x8D4; setznp16(c & 0xffff); if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags |= V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags |= A_FLAG; return c; } uint16_t setadc16(uint16_t a, uint16_t b, uint8_t tempc) { uint32_t c = (uint32_t)a + (uint32_t)b + tempc; flags &= ~0x8D5; setznp16(c & 0xffff); if (c & 0x10000) flags |= C_FLAG; if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags |= V_FLAG; if (((a&0xF)+(b&0xF))&0x10) flags |= A_FLAG; return c; } uint8_t setsub8(uint8_t a, uint8_t b) { uint16_t c = (uint16_t)a - (uint16_t)b; flags &= ~0x8D5; flags |= znptable8[c&0xFF]; if (c&0x100) flags|=C_FLAG; if ((a^b)&(a^c)&0x80) flags|=V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG; return c; } uint8_t setsub8nc(uint8_t a, uint8_t b) { uint16_t c=(uint16_t)a - (uint16_t)b; flags &= ~0x8D4; flags |= znptable8[c&0xFF]; if ((a^b)&(a^c)&0x80) flags |= V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags |= A_FLAG; return c; } uint8_t setsbc8(uint8_t a, uint8_t b, uint8_t tempc) { uint16_t c = (uint16_t)a - (((uint16_t)b) + tempc); flags &= ~0x8D5; flags |= znptable8[c&0xFF]; if (c&0x100) flags |= C_FLAG; if ((a^b)&(a^c)&0x80) flags |= V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags |= A_FLAG; return c; } uint16_t setsub16(uint16_t a, uint16_t b) { uint32_t c = (uint32_t)a - (uint32_t)b; flags &= ~0x8D5; setznp16(c & 0xffff); if (c&0x10000) flags |= C_FLAG; if ((a^b)&(a^c)&0x8000) flags |= V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags |= A_FLAG; return c; } uint16_t setsub16nc(uint16_t a, uint16_t b) { uint32_t c = (uint32_t)a - (uint32_t)b; flags &= ~0x8D4; setznp16(c & 0xffff); flags &= ~0x4; flags |= (znptable8[c&0xFF]&4); if ((a^b)&(a^c)&0x8000) flags |= V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags |= A_FLAG; return c; } uint16_t setsbc16(uint16_t a, uint16_t b, uint8_t tempc) { uint32_t c = (uint32_t)a - (((uint32_t)b) + tempc); flags &= ~0x8D5; setznp16(c & 0xffff); flags &= ~0x4; flags |= (znptable8[c&0xFF]&4); if (c&0x10000) flags |= C_FLAG; if ((a^b)&(a^c)&0x8000) flags |= V_FLAG; if (((a&0xF)-(b&0xF))&0x10) flags |= A_FLAG; return c; } uint8_t setor8(uint8_t a, uint8_t b) { uint8_t c = a | b; setznp8(c); flags &=~ (C_FLAG | V_FLAG | A_FLAG); return c; } uint16_t setor16(uint16_t a, uint16_t b) { uint16_t c = a | b; setznp16(c); flags &=~ (C_FLAG | V_FLAG | A_FLAG); return c; } uint8_t setand8(uint8_t a, uint8_t b) { uint8_t c = a & b; setznp8(c); flags &=~ (C_FLAG | V_FLAG | A_FLAG); return c; } uint16_t setand16(uint16_t a, uint16_t b) { uint16_t c = a & b; setznp16(c); flags &=~ (C_FLAG | V_FLAG | A_FLAG); return c; } uint8_t setxor8(uint8_t a, uint8_t b) { uint8_t c = a ^ b; setznp8(c); flags &=~ (C_FLAG | V_FLAG | A_FLAG); return c; } uint16_t setxor16(uint16_t a, uint16_t b) { uint16_t c = a ^ b; setznp16(c); flags &=~ (C_FLAG | V_FLAG | A_FLAG); return c; } // --------------------------------------------------------------------- // СЧИТЫВАНИЕ И ДЕКОДИРОВАНИЕ // --------------------------------------------------------------------- // Читать слово из памяти uint16_t readmemw(uint32_t s, uint16_t a) { uint8_t l = readmemb(s + a); uint8_t h = readmemb(s + ((a+1) & 0xffff)); return (h<<8) | l; } // Писать слово в память void writememw(uint32_t s, uint16_t a, uint16_t v) { writememb(s + a, v); writememb(s + ((a+1) & 0xffff), v >> 8); } // Загрузка нового значения CS void loadcs(uint16_t s) { segs[SEG_CS] = s; seg_cs = (uint32_t)s << 4; } void loadss(uint16_t s) { segs[SEG_SS] = s; seg_ss = (uint32_t)s << 4; } void loades(uint16_t s) { segs[SEG_ES] = s; seg_es = (uint32_t)s << 4; } void loadds(uint16_t s) { segs[SEG_DS] = s; seg_ds = (uint32_t)s << 4; } void loadfs(uint16_t s) { segs[SEG_FS] = s; seg_fs = (uint32_t)s << 4; } void loadgs(uint16_t s) { segs[SEG_GS] = s; seg_gs = (uint32_t)s << 4; } // Считывание следующего кода из CS:IP inline uint8_t getbyte() { return readmemb(seg_cs + (ip++)); } // Считывание WORD из потока CS:IP uint16_t getword() { uint8_t l = getbyte(); return ((uint16_t)getbyte() << 8) | l; } // Прочитать эффективный адрес void fetchea() { rmdat = getbyte(); cpu_mod = (rmdat >> 6) & 3; cpu_reg = (rmdat >> 3) & 7; cpu_rm = rmdat & 7; eaaddr = 0; // Расчет эффективного адреса switch (cpu_rm) { case 0: eaaddr = (BX_ + SI_); break; case 1: eaaddr = (BX_ + DI_); break; case 2: eaaddr = (BP_ + SI_); break; case 3: eaaddr = (BP_ + DI_); break; case 4: eaaddr = SI_; break; case 5: eaaddr = DI_; break; case 6: eaaddr = BP_; break; case 7: eaaddr = BX_; break; } // Выбор сегмента if (sel_seg == 0 && ((cpu_rm == 6 && cpu_mod) || (cpu_rm == 2) || (cpu_rm == 3))) segment = seg_ss; // Модифицирующие биты modrm switch (cpu_mod) { case 0: if (cpu_rm == 6) eaaddr = getword(); break; case 1: eaaddr += (signed char) getbyte(); break; case 2: eaaddr += getword(); break; case 3: eaaddr = 0; break; } } // Чтение из 8-битного регистра uint8_t getr8(uint8_t id) { return id & 4 ? regs[id&3] >> 8 : regs[id&3]; } // Запись в 8-битный регистр void setr8(uint8_t id, uint8_t v) { if (id & 4) { regs[id&3] = (regs[id&3] & 0x00ff) | ((uint16_t)v << 8); } else { regs[id&3] = (regs[id&3] & 0xff00) | v; } } // Чтение и запись в 16-битные регистры inline uint16_t getr16(uint8_t id) { return regs[id]; } inline void setr16(uint8_t id, uint16_t v) { regs[id] = v; } // Прочитать byte из r/m uint8_t geteab() { if (cpu_mod == 3) return getr8(cpu_rm); else return readmemb(segment + eaaddr); } // Прочитать word из r/m uint16_t geteaw() { if (cpu_mod == 3) return getr16(cpu_rm); return readmemw(segment, eaaddr); } // Записать byte в r/m void seteab(uint8_t v) { if (cpu_mod == 3) { setr8(cpu_rm, v); } else { writememb(segment + eaaddr, v); } } // Записать word в r/m void seteaw(uint16_t v) { if (cpu_mod == 3) { regs[cpu_rm] = v; } else { writememw(segment, eaaddr, v); } } // Запись в стек void push(uint16_t v) { writememw(seg_ss, ((SP_ - 2) & 0xffff), v); SP_ -= 2; } // Извлечение из стека uint16_t pop() { uint16_t r = readmemw(seg_ss, SP_); SP_ += 2; return r; } // Вызов прерывания void interrupt(uint8_t int_id) { uint16_t a = (int_id<<2); uint16_t l = readmemw(0, a); uint16_t h = readmemw(0, a+2); push(flags | 0xF000); push(segs[SEG_CS]); push(ip); flags &= ~(I_FLAG | T_FLAG); loadcs(h); ip = l; } // Десятичная коррекция после сложения void daa() { uint8_t AL = AL_; uint16_t tempi; if ((flags & A_FLAG) || ((AL & 0xF) > 9)) { tempi = ((uint16_t) AL) + 6; AL += 6; flags |= A_FLAG; if (tempi & 0x100) flags |= C_FLAG; } if ((flags & C_FLAG) || (AL > 0x9F)) { AL += 0x60; flags |= C_FLAG; } setznp8(AL); setr8(REG_AL, AL); } // Десятичная коррекция после вычитания void das() { uint8_t AL = regs[REG_AL]; uint16_t tempi; if ((flags & A_FLAG) || ((AL & 0xF)>9)) { tempi = ((uint16_t)AL) - 6; AL -= 6; flags |= A_FLAG; if (tempi & 0x100) flags |= C_FLAG; } if ((flags & C_FLAG) || (AL>0x9F)) { AL -= 0x60; flags |= C_FLAG; } setznp8(AL); setr8(REG_AL, AL); } // ASCII-коррекция после сложения void aaa() { uint8_t AL = regs[REG_AL]; uint8_t AH = regs[REG_AX] >> 8; if ((flags & A_FLAG) || ((AL & 0xF) > 9)) { AL+=6; AH++; flags |= (A_FLAG|C_FLAG); } else { flags &= ~(A_FLAG|C_FLAG); } setr16(REG_AX, (AL&15) + ((uint16_t)AH << 8)); } // ASCII-коррекция после вычитания void aas() { uint8_t AL = regs[REG_AL]; uint8_t AH = regs[REG_AX] >> 8; if ((flags & A_FLAG) || ((AL & 0xF) > 9)) { AL-=6; AH--; flags |= (A_FLAG|C_FLAG); } else flags &= ~(A_FLAG|C_FLAG); setr16(REG_AX, (AL&15) + ((uint16_t)AH<<8)); } // Коррекция после умножения inline void aam() { uint8_t tb = getbyte(); setr8(REG_AH, AL_ / tb); setr8(REG_AL, AL_ % tb); setznp16(AX_); } // Коррекция после деления inline void aad() { uint8_t tb = getbyte(); AX_ = (AH_*tb + AL_) & 0x00FF; setznp16(AX_); } // Дальний вызов void callfar(uint16_t _cs, uint16_t _ip) { uint16_t cs_ = segs[SEG_CS], ip_ = ip; ip = _ip; loadcs(_cs); push(cs_); push(ip_); } // Групповые операции АЛУ 8 бит uint8_t groupalu8(uint8_t mode, uint8_t a, uint8_t b) { switch (mode) { case 0: return setadd8(a, b); case 1: return setor8 (a, b); case 2: return setadc8(a, b, flags & C_FLAG); case 3: return setsbc8(a, b, flags & C_FLAG); case 4: return setand8(a, b); case 5: case 7: return setsub8(a, b); case 6: return setxor8(a, b); } return 0; } // Групповые операции АЛУ 16 бит uint16_t groupalu16(uint8_t mode, uint16_t a, uint16_t b) { switch (mode) { case 0: return setadd16(a, b); case 1: return setor16 (a, b); case 2: return setadc16(a, b, flags & C_FLAG); case 3: return setsbc16(a, b, flags & C_FLAG); case 4: return setand16(a, b); case 5: case 7: return setsub16(a, b); case 6: return setxor16(a, b); } return 0; } // Сдвиговые операции // * mode = 0..7 // * bit = 0/1 (8/16) // * temp = значение // * n = кол-во сдвигов uint16_t groupshift(uint8_t mode, uint8_t bit, uint16_t temp, uint8_t n) { uint8_t tmpc = 0; uint16_t temp2; uint16_t sign_bit = bit ? 0x8000 : 0x80; uint16_t prev_bit = sign_bit >> 1; if (n == 0) return temp; switch (mode) { // ROL case 0: { flags &= ~(C_FLAG | V_FLAG); while (n > 0) { tmpc = !!(temp & sign_bit); temp = (temp << 1) | tmpc; n--; } if (tmpc) flags |= C_FLAG; if (!!(flags & C_FLAG) != !!(temp & sign_bit)) flags |= V_FLAG; break; } // ROR case 1: { flags &= ~(C_FLAG | V_FLAG); while (n > 0) { tmpc = temp & 1; temp >>= 1; if (tmpc) temp |= sign_bit; n--; } if (tmpc) flags |= C_FLAG; if ((temp ^ (temp >> 1)) & prev_bit) flags |= V_FLAG; break; } // RCL case 2: { flags &= ~(V_FLAG); while (n > 0) { tmpc = flags & C_FLAG; if (temp & sign_bit) flags |= C_FLAG; else flags &= ~C_FLAG; temp = (temp << 1) | tmpc; n--; } // Установить флаги после обновления if (!!(flags & C_FLAG) != !!(temp & sign_bit)) flags |= V_FLAG; break; } // RCR case 3: { flags &= ~(V_FLAG); while (n > 0) { tmpc = flags&C_FLAG; temp2 = temp&1; temp >>= 1; if (temp2) flags |= C_FLAG; else flags &= ~C_FLAG; if (tmpc) temp |= sign_bit; n--; } if ((temp ^ (temp >> 1)) & prev_bit) flags |= V_FLAG; break; } // SHL case 4: case 6: { flags &= ~(C_FLAG); if (n > (bit ? 16 : 8)) { temp = 0; } else { if ((temp << (n-1)) & sign_bit) flags |= C_FLAG; temp <<= n; } if (bit) setznp16(temp); else setznp8(temp); flags |= A_FLAG; break; } // SHR case 5: { flags &= ~(C_FLAG); if (n > (bit ? 16 : 8)) { temp = 0; } else { if ((temp >> (n-1)) & 1) flags |= C_FLAG; temp >>= n; } if (bit) setznp16(temp); else setznp8(temp); flags |= A_FLAG; break; } // SAR case 7: { flags &= ~(C_FLAG); if ((temp >> (n-1)) & 1) flags |= C_FLAG; while (n > 0) { temp >>= 1; if (temp & prev_bit) temp |= sign_bit; n--; } if (bit) setznp16(temp); else setznp8(temp); flags |= A_FLAG; break; } } return temp; } // --------------------------------------------------------------------- // ЦИКЛ ВЫПОЛНЕНИЯ ОДНОЙ ИНСТРУКЦИИ // --------------------------------------------------------------------- // Автоинкремент для строковых инструкции void autorep(uint8_t flag_test) { // Есть префикс <REP | REPNZ | REPZ> if (rep) { CX_--; // Проверка на REPNZ, REPZ if (flag_test) { // Если REPZ, но не ZERO, переход к следующей инструкции if ((rep == REPZ) && !(flags & Z_FLAG)) return; // Если REPNZ, но ZERO, переход к следующей инструкции if ((rep == REPNZ) && (flags & Z_FLAG)) return; } // Повтор инструкции if (CX_) ip = ip_start; } } // Undefined void ud(int type) { ip--; // printf("[%04x:%04x] %02x UNDEFINED %02x\n", seg_cs, ip, readmemb(seg_cs + ip), type); // printf("fs=%04x\n", seg_fs); // exit(1); } // Расширенная инструкция void extended() { opcode = getbyte(); int16_t offset; switch (opcode) { // RDTSC case 0x31: AX_ = rdtsc&0xffff; DX_ = 0; break; // JO, JNO case 0x80: offset = (int16_t)getword(); if (flags&V_FLAG) ip += offset; break; case 0x81: offset = (int16_t)getword(); if (!(flags&V_FLAG)) ip += offset; break; // JB, JNB case 0x82: offset = (int16_t)getword(); if (flags&C_FLAG) ip += offset; break; case 0x83: offset = (int16_t)getword(); if (!(flags&C_FLAG)) ip += offset; break; // JZ, JNZ case 0x84: offset = (int16_t)getword(); if (flags&Z_FLAG) ip += offset; break; case 0x85: offset = (int16_t)getword(); if (!(flags&Z_FLAG)) ip += offset; break; // JBE, JNBE case 0x86: offset = (int16_t)getword(); if (flags&(C_FLAG|Z_FLAG)) ip += offset; break; case 0x87: offset = (int16_t)getword(); if (!(flags&(C_FLAG|Z_FLAG))) ip += offset; break; // JS, JNS case 0x88: offset = (int16_t)getword(); if (flags&N_FLAG) ip += offset; break; case 0x89: offset = (int16_t)getword(); if (!(flags&N_FLAG)) ip += offset; break; // JP, JNP case 0x8A: offset = (int16_t)getword(); if (flags&P_FLAG) ip += offset; break; case 0x8B: offset = (int16_t)getword(); if (!(flags&P_FLAG)) ip += offset; break; // JL, JNL case 0x8C: offset = (int16_t)getword(); if (!!(flags&N_FLAG) != !!(flags&V_FLAG)) ip += offset; break; case 0x8D: offset = (int16_t)getword(); if (!!(flags&N_FLAG) == !!(flags&V_FLAG)) ip += offset; break; // JLE, JNLE: ZF=1 OR (SF!=OF); ZF=0 AND (SF=OF) case 0x8E: offset = (int16_t)getword(); if ( (flags&Z_FLAG) || !!(flags&N_FLAG) != !!(flags&V_FLAG)) ip += offset; break; case 0x8F: offset = (int16_t)getword(); if (!(flags&Z_FLAG) && (!!(flags&N_FLAG) == !!(flags&V_FLAG))) ip += offset; break; // MOVZX r16, rm8/16 case 0xB6: fetchea(); setr16(cpu_reg, geteab()); break; case 0xB7: fetchea(); setr16(cpu_reg, geteaw()); break; default: ud(7); break; } } // Запуск в работу int x86run(int32_t instr_cnt) { int8_t offset; int16_t tempws; uint8_t cont, tempc, noint; uint8_t tempb, tempb2; uint16_t tempw, tempw2; uint32_t templ; int32_t templs; int8_t trap; int8_t p66, p67; while (instr_cnt-- >= 0) { // Остановка процессора if (inhlt) return 1; rep = 0; trap = flags & T_FLAG; sel_seg = 0; noint = 0; p66 = 0; p67 = 0; segment = seg_ds; tempc = flags & C_FLAG; tstates++; ip_start = ip; do { rdtsc++; cont = 0; opcode = getbyte(); switch (opcode) { // ADD case 0x00: fetchea(); seteab(setadd8 (geteab(), getr8 (cpu_reg))); break; case 0x01: fetchea(); seteaw(setadd16(geteaw(), getr16(cpu_reg))); break; case 0x02: fetchea(); setr8 (cpu_reg, setadd8 (getr8 (cpu_reg), geteab())); break; case 0x03: fetchea(); setr16(cpu_reg, setadd16(getr16(cpu_reg), geteaw())); break; case 0x04: setr8 (REG_AL, setadd8 (regs[REG_AL], getbyte())); break; case 0x05: setr16(REG_AX, setadd16(regs[REG_AX], getword())); break; case 0x06: push(segs[SEG_ES]); break; case 0x07: loades(pop()); break; // OR case 0x08: fetchea(); seteab(setor8 (geteab(), getr8 (cpu_reg))); break; case 0x09: fetchea(); seteaw(setor16(geteaw(), getr16(cpu_reg))); break; case 0x0A: fetchea(); setr8 (cpu_reg, setor8 (getr8 (cpu_reg), geteab())); break; case 0x0B: fetchea(); setr16(cpu_reg, setor16(getr16(cpu_reg), geteaw())); break; case 0x0C: setr8 (REG_AL, setor8 (regs[REG_AL], getbyte())); break; case 0x0D: setr16(REG_AX, setor16(regs[REG_AX], getword())); break; case 0x0E: push(segs[SEG_CS]); break; case 0x0F: extended(); break; // ADС case 0x10: fetchea(); seteab(setadc8 (geteab(), getr8 (cpu_reg), tempc)); break; case 0x11: fetchea(); seteaw(setadc16(geteaw(), getr16(cpu_reg), tempc)); break; case 0x12: fetchea(); setr8 (cpu_reg, setadc8 (getr8 (cpu_reg), geteab(), tempc)); break; case 0x13: fetchea(); setr16(cpu_reg, setadc16(getr16(cpu_reg), geteaw(), tempc)); break; case 0x14: setr8 (REG_AL, setadc8 (regs[REG_AL], getbyte(), tempc)); break; case 0x15: setr16(REG_AX, setadc16(regs[REG_AX], getword(), tempc)); break; case 0x16: push(segs[SEG_SS]); break; case 0x17: loadss(pop()); noint = 1; break; // SBB case 0x18: fetchea(); seteab(setsbc8 (geteab(), getr8 (cpu_reg), tempc)); break; case 0x19: fetchea(); seteaw(setsbc16(geteaw(), getr16(cpu_reg), tempc)); break; case 0x1A: fetchea(); setr8 (cpu_reg, setsbc8 (getr8 (cpu_reg), geteab(), tempc)); break; case 0x1B: fetchea(); setr16(cpu_reg, setsbc16(getr16(cpu_reg), geteaw(), tempc)); break; case 0x1C: setr8 (REG_AL, setsbc8 (regs[REG_AL], getbyte(), tempc)); break; case 0x1D: setr16(REG_AX, setsbc16(regs[REG_AX], getword(), tempc)); break; case 0x1E: push(segs[SEG_DS]); break; case 0x1F: loadds(pop()); break; // AND case 0x20: fetchea(); seteab(setand8 (geteab(), getr8 (cpu_reg))); break; case 0x21: fetchea(); seteaw(setand16(geteaw(), getr16(cpu_reg))); break; case 0x22: fetchea(); setr8 (cpu_reg, setand8 (getr8 (cpu_reg), geteab())); break; case 0x23: fetchea(); setr16(cpu_reg, setand16(getr16(cpu_reg), geteaw())); break; case 0x24: setr8 (REG_AL, setand8 (regs[REG_AL], getbyte())); break; case 0x25: setr16(REG_AX, setand16(regs[REG_AX], getword())); break; case 0x26: sel_seg = 1; segment = seg_es; cont = 1; break; case 0x27: daa(); break; // SUB case 0x28: fetchea(); seteab(setsub8 (geteab(), getr8 (cpu_reg))); break; case 0x29: fetchea(); seteaw(setsub16(geteaw(), getr16(cpu_reg))); break; case 0x2A: fetchea(); setr8 (cpu_reg, setsub8 (getr8 (cpu_reg), geteab())); break; case 0x2B: fetchea(); setr16(cpu_reg, setsub16(getr16(cpu_reg), geteaw())); break; case 0x2C: setr8 (REG_AL, setsub8 (regs[REG_AL], getbyte())); break; case 0x2D: setr16(REG_AX, setsub16(regs[REG_AX], getword())); break; case 0x2E: sel_seg = 1; segment = seg_cs; cont = 1; break; case 0x2F: das(); break; // XOR case 0x30: fetchea(); seteab(setxor8 (geteab(), getr8 (cpu_reg))); break; case 0x31: fetchea(); seteaw(setxor16(geteaw(), getr16(cpu_reg))); break; case 0x32: fetchea(); setr8 (cpu_reg, setxor8 (getr8 (cpu_reg), geteab())); break; case 0x33: fetchea(); setr16(cpu_reg, setxor16(getr16(cpu_reg), geteaw())); break; case 0x34: setr8 (REG_AL, setxor8 (regs[REG_AL], getbyte())); break; case 0x35: setr16(REG_AX, setxor16(regs[REG_AX], getword())); break; case 0x36: sel_seg = 1; segment = seg_ss; cont = 1; break; case 0x37: aaa(); break; // CMP case 0x38: fetchea(); setsub8 (geteab(), getr8 (cpu_reg)); break; case 0x39: fetchea(); setsub16(geteaw(), getr16(cpu_reg)); break; case 0x3A: fetchea(); setsub8 (getr8 (cpu_reg), geteab()); break; case 0x3B: fetchea(); setsub16(getr16(cpu_reg), geteaw()); break; case 0x3C: setsub8 (regs[REG_AL], getbyte()); break; case 0x3D: setsub16(regs[REG_AX], getword()); break; case 0x3E: sel_seg = 1; segment = seg_ds; cont = 1; break; case 0x3F: aas(); break; // INC r16 case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: { regs[opcode&7] = setadd16nc(regs[opcode&7], 1); break; } // DEC r16 case 0x48: case 0x49: case 0x4A: case 0x4B: case 0x4C: case 0x4D: case 0x4E: case 0x4F: { regs[opcode&7] = setsub16nc(regs[opcode&7], 1); break; } // PUSH r16 case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x55: case 0x56: case 0x57: { push(regs[opcode&7]); break; } // POP r16 case 0x58: case 0x59: case 0x5A: case 0x5B: case 0x5C: case 0x5D: case 0x5E: case 0x5F: { regs[opcode&7] = pop(); break; } // PUSHA case 0x60: { tempw = regs[REG_SP]; for (int i = 0; i < 8; i++) push(i == REG_SP ? tempw : regs[i]); break; } // POPA case 0x61: { tempw = 0; for (int i = 7; i >= 0; i--) { if (i == REG_SP) tempw = pop(); else regs[i] = pop(); } regs[REG_SP] = tempw; break; } // FS: GS: case 0x64: sel_seg = 1; segment = seg_fs; cont = 1; break; case 0x65: sel_seg = 1; segment = seg_gs; cont = 1; break; // opsize, adsize case 0x66: p66 = ~p66; cont = 1; break; case 0x67: p67 = ~p67; cont = 1; break; // PUSH imm16 case 0x68: push(getword()); break; case 0x6a: tempw = getbyte(); tempw = (tempw & 0x80 ? 0xff00 : 0) | tempw; push(tempw); break; // IMUL r16,rm,i16 case 0x69: { fetchea(); tempw = getword(); templ = (long)((int16_t)geteaw()) * (long)((int16_t)tempw); setr16(cpu_reg, templ); if (templ & 0xffff0000) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); break; } // IMUL r16,rm,i8 case 0x6B: { fetchea(); tempw = getbyte(); tempw = tempw & 0x80 ? (0xff00 | tempw) : tempw; templ = (long)((int16_t)geteaw()) * (long)((int16_t)tempw); setr16(cpu_reg, templ); if (templ & 0xffff0000) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); break; } // JO, JNO case 0x70: offset = (int8_t)getbyte(); if (flags&V_FLAG) ip += offset; break; case 0x71: offset = (int8_t)getbyte(); if (!(flags&V_FLAG)) ip += offset; break; // JB, JNB case 0x72: offset = (int8_t)getbyte(); if (flags&C_FLAG) ip += offset; break; case 0x73: offset = (int8_t)getbyte(); if (!(flags&C_FLAG)) ip += offset; break; // JZ, JNZ case 0x74: offset = (int8_t)getbyte(); if (flags&Z_FLAG) ip += offset; break; case 0x75: offset = (int8_t)getbyte(); if (!(flags&Z_FLAG)) ip += offset; break; // JBE, JNBE case 0x76: offset = (int8_t)getbyte(); if (flags&(C_FLAG|Z_FLAG)) ip += offset; break; case 0x77: offset = (int8_t)getbyte(); if (!(flags&(C_FLAG|Z_FLAG))) ip += offset; break; // JS, JNS case 0x78: offset = (int8_t)getbyte(); if (flags&N_FLAG) ip += offset; break; case 0x79: offset = (int8_t)getbyte(); if (!(flags&N_FLAG)) ip += offset; break; // JP, JNP case 0x7A: offset = (int8_t)getbyte(); if (flags&P_FLAG) ip += offset; break; case 0x7B: offset = (int8_t)getbyte(); if (!(flags&P_FLAG)) ip += offset; break; // JL, JNL case 0x7C: offset = (int8_t)getbyte(); if (!!(flags&N_FLAG) != !!(flags&V_FLAG)) ip += offset; break; case 0x7D: offset = (int8_t)getbyte(); if (!!(flags&N_FLAG) == !!(flags&V_FLAG)) ip += offset; break; // JLE, JNLE: ZF=1 OR (SF!=OF); ZF=0 AND (SF=OF) case 0x7E: offset = (int8_t)getbyte(); if ( (flags&Z_FLAG) || !!(flags&N_FLAG) != !!(flags&V_FLAG)) ip += offset; break; case 0x7F: offset = (int8_t)getbyte(); if (!(flags&Z_FLAG) && (!!(flags&N_FLAG) == !!(flags&V_FLAG))) ip += offset; break; // GRP#1 e,#8 case 0x80: case 0x82: { fetchea(); tempb = geteab(); tempb2 = getbyte(); tempb = groupalu8(cpu_reg, tempb, tempb2); if (cpu_reg < 7) seteab(tempb); break; } // GRP#1 e,#16 case 0x81: { fetchea(); tempw = geteaw(); tempw2 = getword(); tempw = groupalu16(cpu_reg, tempw, tempw2); if (cpu_reg < 7) seteaw(tempw); break; } // GRP#1 e16,#8 case 0x83: { fetchea(); tempw = geteaw(); tempb = getbyte(); tempw = groupalu16(cpu_reg, tempw, tempb | (tempb&0x80 ? 0xFF00 : 0)); if (cpu_reg < 7) seteaw(tempw); break; } // TEST 8/16,r case 0x84: fetchea(); setand8 (geteab(), getr8 (cpu_reg)); break; case 0x85: fetchea(); setand16(geteaw(), getr16(cpu_reg)); break; // XCHG 8/16,r case 0x86: fetchea(); tempb = geteab(); seteab(getr8 (cpu_reg)); setr8 (cpu_reg, tempb); break; case 0x87: fetchea(); tempw = geteaw(); seteaw(getr16(cpu_reg)); setr16(cpu_reg, tempw); break; // MOV modrm case 0x88: fetchea(); seteab(getr8 (cpu_reg)); break; case 0x89: fetchea(); seteaw(getr16(cpu_reg)); break; case 0x8A: fetchea(); setr8 (cpu_reg, geteab()); break; case 0x8B: fetchea(); setr16(cpu_reg, geteaw()); break; // MOV w, sreg case 0x8C: { fetchea(); switch (rmdat & 0x38) { case 0x00: seteaw(segs[SEG_ES]); break; case 0x08: seteaw(segs[SEG_CS]); break; case 0x10: seteaw(segs[SEG_SS]); break; case 0x18: seteaw(segs[SEG_DS]); break; case 0x20: seteaw(segs[SEG_FS]); break; case 0x28: seteaw(segs[SEG_GS]); break; } break; } // LEA r16, ea case 0x8D: fetchea(); regs[cpu_reg] = eaaddr; break; // MOV sreg, r16 case 0x8E: { fetchea(); noint = 1; switch (rmdat & 0x38) { case 0x00: loades(geteaw()); break; case 0x08: ud(6); break; case 0x10: loadss(geteaw()); break; case 0x18: loadds(geteaw()); break; case 0x20: loadfs(geteaw()); break; case 0x28: loadgs(geteaw()); break; } break; } // POP rm case 0x8F: fetchea(); seteaw(pop()); break; // XCHG ax, r16 case 0x90: case 0x91: case 0x92: case 0x93: case 0x94: case 0x95: case 0x96: case 0x97: { tempw = regs[opcode&7]; regs[opcode&7] = regs[REG_AX]; regs[REG_AX] = tempw; break; } // CBW, CWD case 0x98: AX_ = (AX_ & 0x0080 ? 0xff00 : 0) | (AX_ & 0xff); break; case 0x99: DX_ = (AX_ & 0x8000) ? 0xffff : 0; break; // CALL cs:ip case 0x9A: tempw = getword(); callfar(getword(), tempw); break; case 0x9B: /* FWAIT */ break; // PUSHF/POPF case 0x9C: push((flags & ~0x2A) | 2); break; case 0x9D: flags = pop() & 0xfff; break; // SAHF, LAHF case 0x9E: flags = (flags & 0xFF00) | (AX_ >> 8); break; case 0x9F: setr8(REG_AH, flags); break; // MOV acc,16 case 0xA0: tempw = getword(); setr8(REG_AX, readmemb(segment + tempw)); break; case 0xA1: tempw = getword(); AX_ = readmemw(segment, tempw); break; case 0xA2: tempw = getword(); writememb(segment + tempw, AX_); break; case 0xA3: tempw = getword(); writememw(segment, tempw, AX_); break; // MOVSB: Переместить байт case 0xA4: { REPINIT; writememb(seg_es + DI_, readmemb(segment + SI_)); REPINC(SI_,1); REPINC(DI_,1); autorep(0); break; } // MOVSW: Переместить слово case 0xA5: { REPINIT; writememw(seg_es, DI_, readmemw(segment, SI_)); REPINC(SI_, p66 ? 4 : 2); REPINC(DI_, p66 ? 4 : 2); autorep(0); break; } // CMPSB case 0xA6: { REPINIT; setsub8(readmemb(segment + SI_), readmemb(seg_es + DI_)); REPINC(SI_,1); REPINC(DI_,1); autorep(0); break; } // CMPSW case 0xA7: { REPINIT; setsub16(readmemw(segment, SI_), readmemw(seg_es, DI_)); REPINC(SI_, p66 ? 4 : 2); REPINC(DI_, p66 ? 4 : 2); autorep(0); break; } // TEST al,#8 case 0xA8: setand8 (AX_, getbyte()); break; case 0xA9: setand16(AX_, getword()); break; // STOSB case 0xAA: { REPINIT; writememb(seg_es + DI_, AL_); REPINC(DI_, 1); autorep(0); break; } // STOSW case 0xAB: { REPINIT; writememw(seg_es, DI_, AX_); REPINC(DI_, p66 ? 4 : 2); autorep(0); break; } // LODSB case 0xAC: { REPINIT; setr8(REG_AL, readmemb(segment + SI_)); REPINC(SI_, 1); autorep(0); break; } // LODSW case 0xAD: { REPINIT; AX_ = readmemw(segment, SI_); REPINC(SI_, p66 ? 4 : 2); autorep(0); break; } // SCASB case 0xAE: { REPINIT; setsub8(AL_, readmemb(seg_es + DI_)); REPINC(DI_, 1); autorep(1); break; } // SCASW case 0xAF: { REPINIT; setsub16(AX_, readmemw(seg_es, DI_)); REPINC(DI_, p66 ? 4 : 2); autorep(1); break; } // MOV r8, #8 case 0xB0: case 0xB1: case 0xB2: case 0xB3: case 0xB4: case 0xB5: case 0xB6: case 0xB7: { setr8(opcode&7, getbyte()); break; } // MOV r16, #16 case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: { regs[opcode&7] = getword(); break; } // Grp#shift case 0xC0: fetchea(); tempb = getbyte(); seteab(groupshift(cpu_reg, 0, geteab(), tempb & 7)); break; case 0xC1: fetchea(); tempb = getbyte(); seteaw(groupshift(cpu_reg, 1, geteaw(), tempb & 31)); break; // RET #16/RET case 0xC2: tempw = getword(); ip = pop(); SP_ += tempw; break; case 0xC3: ip = pop(); break; // LES, LDS case 0xC4: fetchea(); setr16(cpu_reg, readmemw(segment, eaaddr)); loades(readmemw(segment, eaaddr+2)); break; case 0xC5: fetchea(); setr16(cpu_reg, readmemw(segment, eaaddr)); loadds(readmemw(segment, eaaddr+2)); break; // MOV e, #8/16 case 0xC6: fetchea(); seteab(getbyte()); break; case 0xC7: fetchea(); seteaw(getword()); break; // ENTER / LEAVE case 0xC8: ud(4); break; case 0xC9: ud(5); break; // RETF [#16] case 0xCA: tempw = getword(); tempw2 = pop(); loadcs(pop()); ip = tempw; SP_ += tempw; break; case 0xCB: tempw = getword(); tempw2 = pop(); loadcs(pop()); ip = tempw; break; // INT xx case 0xCC: interrupt(3); break; case 0xCD: interrupt(getbyte()); break; case 0xCE: if (flags & V_FLAG) interrupt(4); break; // IRET case 0xCF: tempw = pop(); tempw2 = pop(); flags = pop() & 0xfff; loadcs(tempw2); ip = tempw; break; // Сдвиговые case 0xD0: fetchea(); seteab(groupshift(cpu_reg, 0, geteab(), 1)); break; case 0xD1: fetchea(); seteaw(groupshift(cpu_reg, 1, geteaw(), 1)); break; case 0xD2: fetchea(); seteab(groupshift(cpu_reg, 0, geteab(), CX_&7)); break; case 0xD3: fetchea(); seteaw(groupshift(cpu_reg, 1, geteaw(), CX_&31)); break; // AAM, AAD case 0xD4: aam(); break; case 0xD5: aad(); break; // SALC, XLAT case 0xD6: setr8(REG_AL, flags & C_FLAG ? 0xff : 00); case 0xD7: setr8(REG_AL, readmemb(segment + BX_ + (AX_ & 255))); break; // ESC-последовательности case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: { fetchea(); break; } // LOOP[NZ|Z] JCXZ case 0xE0: offset = (int8_t) getbyte(); CX_--; if ( CX_ && !(flags & Z_FLAG)) ip += offset; break; case 0xE1: offset = (int8_t) getbyte(); CX_--; if ( CX_ && (flags & Z_FLAG)) ip += offset; break; case 0xE2: offset = (int8_t) getbyte(); CX_--; if ( CX_) ip += offset; break; case 0xE3: offset = (int8_t) getbyte(); if (!CX_) ip += offset; break; // IN/OUT #8 case 0xE4: tempb = getbyte(); setr8(REG_AL, ioread(tempb)); break; case 0xE5: tempb = getbyte(); setr8(REG_AL, ioread(tempb)); setr8(REG_AH, ioread(tempb+1)); break; case 0xE6: tempb = getbyte(); iowrite(tempb, AL_); break; case 0xE7: tempb = getbyte(); iowrite(tempb, AL_); iowrite(tempb+1, AH_); break; // CALL, JMP #8/16 case 0xE8: tempw = getword(); push(ip); ip += tempw; break; case 0xE9: tempw = getword(); ip += tempw; break; case 0xEA: tempw = getword(); tempw2 = getword(); loadcs(tempw2); ip = tempw; break; case 0xEB: tempb = getbyte(); ip += (tempb & 0x80 ? tempb - 256 : tempb); break; // IN/OUT dx case 0xEC: setr8(REG_AL, ioread(DX_)); break; case 0xED: setr8(REG_AL, ioread(DX_)); setr8(REG_AH, ioread(DX_+1)); break; case 0xEE: iowrite(DX_, AL_); break; case 0xEF: iowrite(DX_, AL_); iowrite(DX_+1, AH_); break; // LOCK: INT1, REP, HLT, CMC case 0xF0: cont = 1; break; case 0xF1: interrupt(1); break; case 0xF2: rep = REPNZ; cont = 1; break; case 0xF3: rep = REPZ; cont = 1; break; case 0xF4: inhlt = 1; ip--; break; case 0xF5: flags ^= C_FLAG; break; // Групповые инструкции #byte case 0xF6: { fetchea(); tempb = geteab(); switch (cpu_reg) { // TEST/NOT/NEG b case 0: case 1: setand8(tempb, getbyte()); break; case 2: seteab(~tempb); break; case 3: seteab(setsub8(0, tempb)); break; // MUL AL, b case 4: { setznp8(AL_); AX_ = AL_ * tempb; if (AX_) flags &= ~Z_FLAG; else flags |= Z_FLAG; if (AH_) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG|V_FLAG); break; } // IMUL AL, b case 5: { setznp8(AL_); AX_ = (int16_t)((int8_t)AL_)*(int16_t)((int8_t)tempb); if (AX_) flags &= ~Z_FLAG; else flags |= Z_FLAG; if (AH_) flags |= (C_FLAG|V_FLAG); else flags &= ~(C_FLAG|V_FLAG); break; } // DIV AL, b case 6: { tempw = AX_; if (tempb) { tempw2 = tempw % tempb; tempw /= tempb; setr8(REG_AH, tempw2); setr8(REG_AL, tempw); } else interrupt(0); break; } // IDIV AL, b case 7: { tempws = (int16_t) AX_; if (tempb) { tempw2 = tempws % (int16_t)((int8_t)tempb); tempws /= (int16_t)((int8_t)tempb); setr8(REG_AH, tempw2); setr8(REG_AL, tempws); } else interrupt(0); break; } } break; } // Групповые инструкции #word case 0xF7: { fetchea(); tempw = geteaw(); switch (cpu_reg) { // TEST/NOT/NEG w case 0: case 1: setand16(tempw, getword()); break; case 2: seteaw(~tempw); break; case 3: seteaw(setsub16(0, tempw)); break; // MUL AX, w case 4: { setznp16(AX_); templ = AX_ * tempw; AX_ = templ; DX_ = templ >> 16; if (AX_ | DX_) flags &= ~Z_FLAG; else flags |= Z_FLAG; if (DX_) flags |= (C_FLAG|V_FLAG); else flags &= ~(C_FLAG|V_FLAG); break; } // IMUL AX, w case 5: { setznp16(AX_); templ = (long)((int16_t)AX_) * (long)((int16_t)tempw); AX_ = templ; DX_ = (uint16_t)(templ >> 16); if (AX_ && DX_ != 0xFFFF) flags |= (C_FLAG | V_FLAG); else flags &= ~(C_FLAG | V_FLAG); if (AX_ | DX_) flags &= ~Z_FLAG; else flags |= Z_FLAG; break; } // DIV AX, w case 6: { templ = ((uint32_t)DX_ << 16) | AX_; if (tempw) { tempw2 = templ % tempw; templ /= tempw; DX_ = tempw2; AX_ = templ; } else interrupt(0); break; } // IDIV AX, w case 7: { if (DX_ != 0 && DX_ != 0xFFFF) { interrupt(0); break; } templs = (int)(((int32_t)DX_ << 16) | AX_); if (tempw) { tempw2 = templs % (int32_t)(int16_t)tempw; templs /= (int32_t)(int16_t)tempw; DX_ = tempw2; AX_ = templs; } else interrupt(0); break; } } break; } // CLC, STC, CLI, STI case 0xF8: flags &= ~C_FLAG; break; case 0xF9: flags |= C_FLAG; break; case 0xFA: flags &= ~I_FLAG; break; case 0xFB: flags |= I_FLAG; break; case 0xFC: flags &= ~D_FLAG; break; case 0xFD: flags |= D_FLAG; break; // INC/DEC b8 case 0xFE: { fetchea(); tempb = geteab(); switch (cpu_reg) { case 0: seteab(setadd8nc(tempb, 1)); break; case 1: seteab(setsub8nc(tempb, 1)); break; default: ud(3); } break; } // Групповые смешанные case 0xFF: { fetchea(); tempw = geteaw(); switch (cpu_reg) { case 0: seteaw(setadd16nc(tempw, 1)); break; case 1: seteaw(setsub16nc(tempw, 1)); break; // CALL case 2: push(ip); ip = tempw; break; // CALL far case 3: { tempw = readmemw(segment, eaaddr); tempw2 = readmemw(segment, eaaddr + 2); callfar(tempw2, tempw); break; } // JMP case 4: ip = tempw; break; // JMP far case 5: { tempw = readmemw(segment, eaaddr); tempw2 = readmemw(segment, eaaddr+2); loadcs(tempw2); ip = tempw; break; } // PUSH w case 6: push(geteaw()); break; default: ud(1); } break; } default: ud(2); break; } } while (cont); // Если вызван trap if (trap && (flags & T_FLAG) && !noint) interrupt(1); } return 0; } };
26 мая 2025, 14:41
© 2011-2025 Все права весьма запакованы