Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #define ax ((ah<<8)+al)
- #define bx ((bh<<8)+bl)
- #define cx ((ch<<8)+cl)
- #define dx ((dh<<8)+dl)
- #define stepip ip=(ip+1)&0xFFFF
- extern struct structVGAparm {
- unsigned char videomode;
- int textwidth;
- int textheight;
- int width;
- int height;
- char istextmode;
- int pitch;
- } VGAparm;
- unsigned char *RAM = NULL;
- unsigned char resetcode[16];
- extern unsigned char *VGAmemory;
- unsigned char al, ah, bl, bh, cl, ch, dl, dh; //general purpose registers
- unsigned sp, bp, si, di; //stack pointer, base pointer, index registers
- unsigned cs, ds, ss, es; //segment registers
- unsigned ip; //instruction pointer
- char cf, pf, af, zf, sf, tf, ifl, df, of; //flags
- unsigned datasize, opcode, adrmode, tempval, savecs, saveip, disp, oper1, oper2;
- unsigned char mod, reg, rmnum;
- long templong;
- unsigned long totalexec = 0;
- extern int cursorx, cursory;
- char useseg;
- extern char running;
- extern const unsigned char *opdesc[256];
- extern void setnewmode();
- extern void vgahandler();
- extern void bioshandler();
- extern void keyhandler();
- FILE *binfile = NULL;
- extern FILE *logfile;
- long bytesread = 0;
- unsigned read86(long addr) {
- if (addr>0x9FFFF && addr<0xB0000) return VGAmemory[addr-0xa0000];
- if (addr>0xFFFEF && addr<0x100000) return resetcode[addr-0xFFFF0];
- if (addr>655359) return 0;
- return RAM[addr];
- }
- unsigned write86(long addr, unsigned char value) {
- if (addr>0x9FFFF && addr<0xB0000) { VGAmemory[addr-0xa0000] = value; VGAupdate(); return; }
- if (addr>655359) return 0;
- RAM[addr] = value;
- }
- int signextend(unsigned char value) {
- if (value&0x80) templong = 0xFF00; else templong = 0;
- return value+templong;
- }
- void modifystatusflags(long value) {
- if (value) zf = 0; else zf = 1;
- if (value&0x8000) sf = 1; else sf =0;
- }
- void push16(unsigned pushval) {
- sp = (sp-2)&0xFFFF;
- templong = (ss<<4)+sp;
- write86(templong++, pushval&0xFF);
- write86(templong, pushval>>8);
- }
- void push8(unsigned char pushval) {
- sp = (sp-2)&0xFFFF;
- templong = (ss<<4)+sp;
- write86(templong++, pushval);
- write86(templong, 0);
- }
- unsigned pop16() {
- templong = (ss<<4)+sp;
- tempval = read86(templong++) + (read86(templong)<<8);
- sp = (sp+2)&0xFFFF;
- return tempval;
- }
- unsigned char pop8() {
- tempval = read86((ss<<4)+sp);
- sp = (sp+2)&0xFFFF;
- return tempval;
- }
- void calcmodregrm() {
- tempval = read86((cs<<4)+ip); stepip; disp = 0;
- mod = tempval>>6; reg = (tempval>>3)&7; rmnum = tempval&7;
- if (mod==1) { disp = read86((cs<<4)+ip); stepip; }
- else if (mod==2) { disp = read86((cs<<4)+ip); stepip; disp += read86((cs<<4)+ip)<<8; stepip; }
- }
- unsigned makeflagsword() {
- return cf+(pf<<2)+(af<<4)+(zf<<6)+(sf<<7)+(tf<<8)+(ifl<<9)+(df<<10)+(of<<1);
- }
- void decodeflagsword(unsigned flagsval) {
- cf = flagsval&1; pf = (flagsval>>2)&1; af = (flagsval>>4)&1; zf = (flagsval>>6)&1; sf = (sf>>7)&1;
- tf = (flagsval>>8)&1; ifl = (flagsval>>9)&1; df = (flagsval>>10)&1; of = (flagsval>>11)&1;
- }
- unsigned readsreg(char regval) {
- switch (regval) {
- case 0: return es;
- case 1: return cs;
- case 2: return ss;
- case 6: return ds;
- }
- }
- unsigned readreg(char regval) {
- switch (regval) {
- case 0: if (datasize==0) return al; else return ax;
- case 1: if (datasize==0) return cl; else return cx;
- case 2: if (datasize==0) return dl; else return dx;
- case 3: if (datasize==0) return bl; else return bx;
- case 4: if (datasize==0) return ah; else return sp;
- case 5: if (datasize==0) return ch; else return bp;
- case 6: if (datasize==0) return dh; else return si;
- case 7: if (datasize==0) return bh; else return di;
- }
- }
- unsigned readrm(char rmval) {
- if (mod==3) return readreg(rmval);
- fprintf(logfile, "Use segment register %u.\n", useseg);
- switch (useseg) {
- case 0: templong = cs<<4; break;
- case 1: templong = ds<<4; break;
- case 2: templong = es<<4; break;
- case 3: templong = ss<<4; break;
- default: templong = 0;
- }
- if (mod==0) { //using R/M table 1
- fprintf(logfile, "RM table 1 w/ %u w/ disp = %i\n", rmval, disp);
- switch (rmval) {
- case 0: templong += bx+si; break;
- case 1: templong += bx+di; break;
- case 2: templong += bp+si; break;
- case 3: templong += bp+di; break;
- case 4: templong += si; break;
- case 5: templong += di; break;
- case 6: templong += disp; break;
- case 7: templong += bx; break;
- }
- } else { //using R/M table 2
- switch (rmval) {
- case 0: templong += bx+si; break;
- case 1: templong += bx+di; break;
- case 2: templong += bp+si; break;
- case 3: templong += bp+di; break;
- case 4: templong += si; break;
- case 5: templong += di; break;
- case 6: templong += bp; break;
- case 7: templong += bx; break;
- }
- templong += disp;
- }
- tempval = read86(templong);
- if (datasize==1) tempval += read86(templong+1)<<8;
- return tempval;
- }
- void writesreg(char regval, unsigned value) {
- switch (regval) {
- case 0: es = value; break;
- case 1: cs = value; break;
- case 2: ss = value; break;
- case 3: ds = value; break;
- }
- }
- void writereg(char regval, unsigned value) {
- switch (regval) {
- case 0: if (datasize==0) al = value; else { al = value&0xFF; ah = value>>8; } break;
- case 1: if (datasize==0) cl = value; else { cl = value&0xFF; ch = value>>8; } break;
- case 2: if (datasize==0) dl = value; else { dl = value&0xFF; dh = value>>8; } break;
- case 3: if (datasize==0) bl = value; else { bl = value&0xFF; bh = value>>8; } break;
- case 4: if (datasize==0) ah = value; else sp = value; break;
- case 5: if (datasize==0) ch = value; else bp = value; break;
- case 6: if (datasize==0) dh = value; else si = value; break;
- case 7: if (datasize==0) bh = value; else di = value; break;
- }
- }
- void writerm(char rmval, unsigned value) {
- if (mod==3) { writereg(rmval, value); return; }
- switch (useseg) {
- case 0: templong = cs<<4; break;
- case 1: templong = ds<<4; break;
- case 2: templong = es<<4; break;
- case 3: templong = ss<<4; break;
- }
- if (mod==0) { //using R/M table 1
- switch (rmval) {
- case 0: templong += bx+si; break;
- case 1: templong += bx+di; break;
- case 2: templong += bp+si; break;
- case 3: templong += bp+di; break;
- case 4: templong += si; break;
- case 5: templong += di; break;
- case 6: templong += disp; break;
- case 7: templong += bx; break;
- }
- } else { //using R/M table 2
- switch (rmval) {
- case 0: templong += bx+si; break;
- case 1: templong += bx+di; break;
- case 2: templong += bp+si; break;
- case 3: templong += bp+di; break;
- case 4: templong += si; break;
- case 5: templong += di; break;
- case 6: templong += bp; break;
- case 7: templong += bx; break;
- }
- templong += disp;
- }
- write86(templong, value&0xFF);
- if (datasize==1) write86(templong+1, value>>8);
- }
- void loadbin(char *filename, long loadpoint) {
- long i;
- binfile = fopen(filename, "rb");
- if (binfile==NULL) { printf("Unable to load %s into RAM.\n", filename); running = 0; return; }
- bytesread = fread(&RAM[loadpoint], 1, 512, binfile);
- // fclose(binfile);
- printf("%u bytes read from %s\n", bytesread, filename);
- }
- void reset86() {
- resetcode[0] = 0xEA; resetcode[1] = 0x00; resetcode[2] = 0x7C; resetcode[3] = 0x00; resetcode[4] = 0x00;
- //cs = 0xffff; ip = 0x0000;
- cs = 0x0000; ip = 0x7c00;
- al = 0; ah = 0; bl = 0; bh = 0; cl = 0; ch = 0; dl = 0; dh = 0;
- sp = 0; bp = 0; si = 0; di = 0;
- ds = 0; ss = 0; es = 0;
- cf = 0; pf = 0; af = 0; zf = 0; sf = 0; tf = 0; ifl = 1; df = 0; of = 0;
- cursorx = 0; cursory = 0; VGAparm.pitch = 160;
- VGAparm.istextmode = 1; VGAparm.textheight = 24; VGAparm.textwidth = 79; VGAparm.videomode = 3;
- for (tempval=1; tempval<4000; tempval+=2) VGAmemory[0x1800+tempval] = 7;
- setnewmode();
- //RAM[(cs<<4)+ip] = 0xEA; RAM[(cs<<4)+ip+1] = 0x08; RAM[(cs<<4)+ip+2] = 0x00; RAM[(cs<<4)+ip+3] = 0x00; RAM[(cs<<4)+ip+4] = 0x00;
- running = 1;
- }
- void intcall86(unsigned char intnum) {
- switch (intnum) {
- case 0x10: //VGA BIOS call
- vgahandler(); return;
- case 0x13: //BIOS call
- bioshandler(); return;
- case 0x16: //keyboard BIOS call
- keyhandler(); return;
- }
- push16(makeflagsword()); push16(cs); push16(ip);
- templong = intnum<<2;
- cs = read86(templong++) + (read86(templong++)<<8);
- ip = read86(templong++) + (read86(templong)<<8);
- return;
- //ip = pop16(); cs = pop16(); decodeflagsword(pop16());
- }
- void exec86() {
- char rel8; int rel16;
- savecs = cs; saveip = ip; opcode = read86((cs<<4)+ip); stepip;
- //printf("Exec: %s @ %x:%x\n", opdesc[opcode], savecs, saveip);
- fprintf(logfile, "Exec: %s @ %x:%x\n", opdesc[opcode], savecs, saveip);
- useseg = 1; //default segment is DS
- if (opcode==0x2e) { useseg = 0; savecs = cs; saveip = ip; opcode = read86((cs<<4)+ip); stepip;
- fprintf(logfile, "Exec: %s @ %x:%x\n", opdesc[opcode], savecs, saveip);}
- else if (opcode==0x3e) { useseg = 1; savecs = cs; saveip = ip; opcode = read86((cs<<4)+ip); stepip;
- fprintf(logfile, "Exec: %s @ %x:%x\n", opdesc[opcode], savecs, saveip);}
- else if (opcode==0x26) { useseg = 2; savecs = cs; saveip = ip; opcode = read86((cs<<4)+ip); stepip;
- fprintf(logfile, "Exec: %s @ %x:%x\n", opdesc[opcode], savecs, saveip);}
- else if (opcode==0x36) { useseg = 3; savecs = cs; saveip = ip; opcode = read86((cs<<4)+ip); stepip;
- fprintf(logfile, "Exec: %s @ %x:%x\n", opdesc[opcode], savecs, saveip); }
- switch (opcode) {
- case 0x06: //PUSH ES
- push16(es); break;
- case 0x07: //POP ES
- es = pop16(); break;
- case 0x0e: //PUSH CS
- push16(cs); break;
- case 0x16: //PUSH SS
- push16(ss); break;
- case 0x17: //POP SS
- ss = pop16(); break;
- case 0x1e: //PUSH DS
- push16(ds); break;
- case 0x1f: //POP DS
- ds = pop16(); break;
- case 0x33: //XOR Gv, Ev
- calcmodregrm(); writereg(reg, readrm(rmnum)^ax); break;
- case 0x3b: //CMP Gv, Ev
- calcmodregrm(); datasize = 1; oper1 = readreg(reg); oper2 = readrm(rmnum);
- modifystatusflags(oper1 - oper2); stepip;
- if (oper1<oper2) cf = 1; else cf = 0; break;
- case 0x3c: //CMP AL, Ib
- oper1 = al; oper2 = read86((cs<<4)+ip);
- modifystatusflags(oper1 - oper2); stepip;
- if (oper1<oper2) cf = 1; else cf = 0; break;
- case 0x41: //INC eCX
- templong = (cx+1)&0xFFFF; break;
- case 0x46: //INC eSI
- si++; break;
- case 0x4a: //DEC eDX
- templong = (dx-1)&0xFFFF; dl = templong&0xFF; dh = templong>>8; break;
- case 0x50: //PUSH eAX
- push16(ax); break;
- case 0x51: //PUSH eCX
- push16(cx); break;
- case 0x52: //PUSH eDX
- push16(dx); break;
- case 0x53: //PUSH eBX
- push16(bx); break;
- case 0x54: //PUSH eSP
- push16(sp); break;
- case 0x55: //PUSH eBP
- push16(bp); break;
- case 0x56: //PUSH eSI
- push16(si); break;
- case 0x57: //PUSH eDI
- push16(di); break;
- case 0x58: //POP eAX
- tempval = pop16(); al = tempval&0xFF; ah = tempval>>8; break;
- case 0x59: //POP eCX
- tempval = pop16(); cl = tempval&0xFF; ch = tempval>>8; break;
- case 0x5A: //POP eDX
- tempval = pop16(); dl = tempval&0xFF; dh = tempval>>8; break;
- case 0x5B: //POP eBX
- tempval = pop16(); bl = tempval&0xFF; bh = tempval>>8; break;
- case 0x5C: //POP eSP
- sp = pop16(); break;
- case 0x5D: //POP eBP
- bp = pop16(); break;
- case 0x5E: //POP eSI
- si = pop16(); break;
- case 0x5F: //POP eDI
- di = pop16(); break;
- case 0x74: //JZ Jb
- rel8 = read86((cs<<4)+ip); stepip;
- if (zf) ip = (ip+rel8)&0xFFFF; break;
- case 0x75: //JNZ Jb
- rel8 = read86((cs<<4)+ip); stepip;
- if (zf==0) ip = (ip+rel8)&0xFFFF; break;
- case 0x76: //JBE Jb
- rel8 = read86((cs<<4)+ip); stepip;
- if (zf || cf) ip = (ip+rel8)&0xFFFF; break;
- case 0x80: //CMP Eb, Ib
- calcmodregrm(); datasize = 0; oper1 = readrm(rmnum); stepip; stepip;
- oper2 = read86((cs<<4)+ip); stepip; modifystatusflags(oper1 - oper2);
- if (oper2<oper1) cf = 1; else cf = 0; break;
- case 0x83: //CMP Ev, Ib
- calcmodregrm(); datasize = 1; oper1 = readrm(rmnum);
- oper2 = read86((cs<<4)+ip); stepip; modifystatusflags(oper1 - signextend(oper2)); break;
- if (oper2<signextend(oper1)) cf = 1; else cf = 0; break;
- case 0x8a: //MOV Gb, Eb
- calcmodregrm(); datasize = 0; writereg(reg, readrm(rmnum)); break;
- case 0x8e: //MOV Sw, Ew
- calcmodregrm(); datasize = 1; writesreg(reg, readrm(rmnum)); break;
- case 0x90: //NOP
- break;
- case 0xa0: //MOV AL, Ob
- al = read86((cs<<4)+read86((cs<<4)+ip)); stepip; stepip; break;
- case 0xa1: //MOV AL, Ov
- al = read86((cs<<4)+read86((cs<<4)+ip)); stepip;
- ah = read86((cs<<4)+read86((cs<<4)+ip)); stepip; break;
- case 0xa2: //MOV Ob, AL
- write86(read86((cs<<4)+ip), al); stepip; break;
- case 0xa3: //MOV Ob, AL
- write86(read86((cs<<4)+ip), al);
- write86(read86((cs<<4)+ip)+1, ah); stepip; break;
- case 0xb0: //MOV AL, Ib
- al = read86((cs<<4)+ip); stepip; break;
- case 0xb1: //MOV CL, Ib
- cl = read86((cs<<4)+ip); stepip; break;
- case 0xb2: //MOV DL, Ib
- dl = read86((cs<<4)+ip); stepip; break;
- case 0xb3: //MOV BL, Ib
- bl = read86((cs<<4)+ip); stepip; break;
- case 0xb4: //MOV AH, Ib
- ah = read86((cs<<4)+ip); stepip; break;
- case 0xb5: //MOV CH, Ib
- ch = read86((cs<<4)+ip); stepip; break;
- case 0xb6: //MOV DH, Ib
- dh = read86((cs<<4)+ip); stepip; break;
- case 0xb7: //MOV BH, Ib
- bh = read86((cs<<4)+ip); stepip; break;
- case 0xb8: //MOV AX, Iv
- al = read86((cs<<4)+ip); stepip;
- ah = read86((cs<<4)+ip); stepip; break;
- case 0xb9: //MOV CX, Iv
- cl = read86((cs<<4)+ip); stepip;
- ch = read86((cs<<4)+ip); stepip; break;
- case 0xba: //MOV DX, Iv
- dl = read86((cs<<4)+ip); stepip;
- dh = read86((cs<<4)+ip); stepip; break;
- case 0xbb: //MOV BX, Iv
- bl = read86((cs<<4)+ip); stepip;
- bh = read86((cs<<4)+ip); stepip; break;
- case 0xbc: //MOV SP, Iv
- sp = read86((cs<<4)+ip); stepip;
- sp += read86((cs<<4)+ip)<<8; stepip; break;
- case 0xbd: //MOV BP, Iv
- bp = read86((cs<<4)+ip); stepip;
- bp += read86((cs<<4)+ip)<<8; stepip; break;
- case 0xbe: //MOV SI, Iv
- si = read86((cs<<4)+ip); stepip;
- si += read86((cs<<4)+ip)<<8; stepip; break;
- case 0xbf: //MOV DI, Iv
- di = read86((cs<<4)+ip); stepip;
- di += read86((cs<<4)+ip)<<8; stepip; break;
- case 0xc3: //RET
- ip = pop16(); break;
- case 0xc6: //MOV Eb, Ib
- calcmodregrm(); datasize = 0; tempval = read86((cs<<4)+ip); stepip; writerm(rmnum, tempval); break;
- case 0xc7: //MOV Ev, Iv
- calcmodregrm(); datasize = 1; tempval = read86((cs<<4)+ip); stepip;
- tempval += read86((cs<<4)+ip)<<8; stepip; stepip; stepip; writerm(rmnum, tempval); break;
- case 0xcd: //INT Ib
- tempval = read86((cs<<4)+ip); stepip;
- intcall86((unsigned char)tempval); break;
- case 0xd2: //ROR Eb, CL
- calcmodregrm(); datasize = 0; oper1 = readrm(rmnum);
- for (tempval=0; tempval<cl; tempval++) {
- cf = oper1&1; oper1 = oper1>>1; oper1 += (cf<<7);
- } break;
- case 0xe8: //CALL Jv
- push16(ip+2); rel16 = read86((cs<<4)+ip)+(read86((cs<<4)+ip+1)<<8); ip += rel16+2; break;
- case 0xe9: //JMP Jv
- ip = (read86((cs<<4)+ip)+(read86((cs<<4)+ip+1)<<8)+3) % 0xFFFF; break;
- case 0xea: //JMP Ap
- templong = cs;
- cs = read86((templong<<4)+ip+2)+(read86((templong<<4)+ip+3)<<8);
- ip = read86((templong<<4)+ip)+(read86((templong<<4)+ip+1)<<8); break;
- case 0xeb: //JMP Jb
- rel8 = read86((cs<<4)+ip); ip = (ip+rel8+1)&0xFFFF; break;
- case 0xf4: //HLT
- running = 0; break;
- case 0xfa: //CLI
- ifl = 0; break;
- case 0xfc: //CLD
- df = 0; break;
- case 0xfe: //INC Eb
- calcmodregrm(); tempval = (readrm(rmnum)+1)&0xFF; writerm(rmnum, tempval); break;
- default:
- running = 0;
- fprintf(logfile, "UNKNOWN OPCODE EXCEPTION: %s @ %x:%x\n", opdesc[opcode], savecs, saveip);
- fprintf(logfile, "AX: %x BX: %x CX: %x DX: %x\n", ax, bx, cx, dx);
- fprintf(logfile, "CS: %x IP: %x SS: %x SP: %x\n", savecs, saveip, ss, sp);
- fprintf(logfile, "SI: %x DI: %x DS: %x ES: %x\n", si, di, ds, es);
- fprintf(logfile, "CS: %x DS: %x\n\n", cs, ds);
- fprintf(logfile, "Total operations executed: %u\n\n", totalexec);
- return;
- }
- totalexec++;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement