#include #include #include // Opcodes #define add 0x01 #define sub 0x29 #define hlt 0xf4 #define jnz 0x75 #define MRmov 0x8b #define RMmov 0x89 // extrahiere die enzelne Felder eines Befehls // anhand von Bitmasken. #define EXTEND8(x) ((signed int)(signed char)(x)) #define RD(I) (I&0x07) #define RS(I) ((I&0x38)>>3) #define mod(I) ((I&0xc0)>>6) // Die Namen der Register const char *Regs[8]= { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi" }; class cpu_Y86t { public: // constructor: alles auf 0 cpu_Y86t():IP(0) { for(unsigned i=0; i<100; i++) MEM[i]=0; for(unsigned j=0; j<8; j++) R[j]=0; ZF=false; } unsigned IP; // Der Instruction Pointer unsigned char MEM[100]; // Hauptspeicher: 100 Adressen unsigned R[8]; // Die Werte der 8 Register bool ZF; // Flags void show(); // Zustand anzeigen void step(); // eine Instruktion ausfuehren void run(); // Programm ausfuehren }; void cpu_Y86t::show() { std::cout << "IP=" << std::hex << IP << std::endl; for(unsigned i=0; i<8; i++) std::cout << Regs[i] << "=" << std::hex << std::setw(9) << R[i] << " "; std::cout << "ZF=" << ZF; std::cout << std::endl; std::cout << "MEM: "; for(unsigned i=0; i<32; i++) { std::cout << std::hex << std::setw(3) << (unsigned)MEM[i]; if((i&0xf)==0xf) std::cout << std::endl << " "; } std::cout << std::endl; } void cpu_Y86t::step() { unsigned ea; unsigned I0=MEM[IP]; unsigned I1=MEM[IP+1]; unsigned I2=MEM[IP+2]; IP+=1; switch(I0) { case MRmov: if(mod(I1)==1) // move from memory to register { IP+=2; std::cout << "MRmov " << Regs[RS(I1)] << ", [ESI+0x" << EXTEND8(I2) << "]" << std::endl; ea=R[6]+EXTEND8(I2); R[RS(I1)]=MEM[ea]|(MEM[ea+1]>>8)|(MEM[ea+2]>>16)|(MEM[ea+3]>>24); } else std::cout << "Modus nicht unterstuetzt" << std::endl; break; case RMmov: if(mod(I1)==1) // move from register to memory { IP+=2; ea=R[6]+EXTEND8(I2); std::cout << "RMmov [ESI+0x" << EXTEND8(I2) << "], " << Regs[RS(I1)] << std::endl; MEM[ea+0]=(R[RS(I1)]&0xff); MEM[ea+1]=(R[RS(I1)]&0xff00)>>8; MEM[ea+2]=(R[RS(I1)]&0xff0000)>>16; MEM[ea+3]=(R[RS(I1)]&0xff000000)>>24; } else if(mod(I1)==3) // move from register to register { IP+=1; std::cout << "RRmov " << Regs[RD(I1)] << ", " << Regs[RS(I1)] << std::endl; R[RD(I1)]=R[RS(I1)]; } else std::cout << "Modus nicht unterstuetzt" << std::endl; break; case add: IP+=1; std::cout << "add " << Regs[RD(I1)] << ", " << Regs[RS(I1)] << std::endl; R[RD(I1)]+=R[RS(I1)]; ZF=(R[RD(I1)]==0); break; case sub: IP+=1; std::cout << "sub " << Regs[RD(I1)] << ", " << Regs[RS(I1)] << std::endl; R[RD(I1)]-=R[RS(I1)]; ZF=(R[RD(I1)]==0); break; case jnz: // jump if not zero IP+=1; std::cout << "jnz 0x" << IP+EXTEND8(I1) << std::endl; if(!ZF) IP+=EXTEND8(I1); break; case hlt: // halt std::cout << "hlt" << std::endl; exit(0); default: std::cout << "Unbekannte Instruktion" << std::endl; } } void cpu_Y86t::run() { while(true) { show(); std::string s; if(!std::getline(std::cin, s)) break; if(s=="q") break; step(); } } unsigned char program[]= "\x29\xF6" // 00000000 sub esi,esi "\x29\xC0" // 00000002 sub eax,eax "\x29\xDB" // 00000004 sub ebx,ebx "\x8B\x56\x17" // 00000006 mov edx,[esi+0x17] "\x01\xD0" // 00000009 add eax,edx "\x01\xC3" // 0000000B add ebx,eax "\x89\xC1" // 0000000D mov ecx,eax "\x8B\x56\x1B" // 0000000F mov edx,[esi+0x1b] "\x29\xD1" // 00000012 sub ecx,edx "\x75\xF0" // 00000014 jnz 0x6 "\xF4" // 00000016 hlt "\x01\x00\x00\x00" // 00000017 dd 1 "\x0a\x00\x00\x00"; // 0000001B dd 10 int main() { cpu_Y86t cpu_Y86; for(unsigned i=0; i