如何查找机器代码指令的结束以增加指令指针

时间:2014-04-08 22:08:40

标签: c++ emulation machine-code

所以我正在制作模拟器,我目前正在制作一个小型虚拟CPU。使用我的代码,我的CPU将运行自定义指令就好 - 但我正在做的方式是hacky。在正常环境中,计算机如何处理单个机器代码操作?

我知道每次操作都有一个操作码,硬件本身是否会增加指令指针?或者CPU是否以不同的方式递增指令指针?如果CPU递增指令指针,它如何知道要移动多少字节,它是否以某种方式从操作码中获取数据?

如果这看起来像个愚蠢的问题,我很抱歉。我没有我需要的经验,我只是找不到任何能回答这个问题的资源。

这是我正在研究的小CPU,我跳过了RAM类和指令类,ram类基本上只是一个连续的内存块,而且指令类中只有一个函数指针(不是最快的方法) “当然,但我正在学习)

const int REGNUM = 8;
class cpu{
    protected:
        ui16 reg[REGNUM];//registers should change to unions?
        ram* pram;//pipeline pointer to ram
        vector<module*> addons;
        instruction itable[255];//can make vector if more than 255 instructions
        byte inum; //current number of instructions in the itable, increments when instruction added
    public:

    cpu();
    //~cpu();

    void connect_ram(ram* inram);//reset instruction pointer
    void connect_module(module* addon); //anything from a hard drive to a screen

    ram* getram();

    byte add_instruction(const instruction& ins);

    void setreg(ui8 which, ui16 val);
    ui16 getreg(ui8 which);

    void exe(); //run execution unit, increment instruction pointer
};
cpu::cpu(){
    inum=0;
    pram=NULL;
    for(int a = 0; a<REGNUM; a++){
        reg[a]=0;
    }
}

void cpu::connect_ram(ram* inram){
    pram=inram;
    reg[7]=0;
}
void cpu::connect_module(module* addon){
    addons.push_back(addon);
}
ram* cpu::getram(){
    return pram;
}
void cpu::setreg(ui8 which, ui16 val){
    reg[which]=val;
}
ui16 cpu::getreg(ui8 which){
    return reg[which];
}
void cpu::exe(){
    itable[(*getram())[getreg(7)]].func(this);
}
byte cpu::add_instruction(const instruction& ins){
    itable[inum]=ins;
    inum++;
    return inum-1; //return table num of instruction
}

void jmp(cpu* c){ //can depend on architecture, 16 bit jump different than 8 bit?
    ui16 ins = (*c->getram())[c->getreg(7) + 1];//next byte
    ins = ins << 8;
    ins +=  (*c->getram())[c->getreg(7) + 2];//second next byte
    c->setreg(7,ins);
}

void output(cpu* c){ //outputs the first register
    cout << (char)c->getreg(0);
    c->setreg(7,c->getreg(7)+1);
}

void getram(cpu* c){
    ui16 ad = (((ui16)(*c->getram())[c->getreg(7) + 1])<<8)+(ui16)(*c->getram())[c->getreg(7)+2];
    c->setreg(0,(*c->getram())[ad]); //set register 1 to the value of the address
    c->setreg(7,c->getreg(7)+3); //move instruction pointer
}

void setram(cpu* c){
    ui16 ad = (((ui16)(*c->getram())[c->getreg(7) + 1])<<8)+(ui16)(*c->getram())[c->getreg(7)+2]; //address to change
    (*c->getram())[ad] = c->getreg(0); //set byte at address to value in first register
    c->setreg(7,c->getreg(7)+3); //move instruction pointer
}

void increg(cpu* c){
    c->setreg(0,c->getreg(0)+1);
    c->setreg(7,c->getreg(7)+1);
}
void decreg(cpu* c){
    c->setreg(0,c->getreg(0)-1);
    c->setreg(7,c->getreg(7)+3);
}

void nop(cpu* c){
    c->setreg(7,c->getreg(7)+1); //move instruction pointer
}

1 个答案:

答案 0 :(得分:2)

在解释器中,每个指令在获取其操作数的过程中找到自己的结束。初始获取指令本身及其自己的所有读取都会增加PC,因此PC始终指向下一个要获取的内容。

它在硬件中的完成方式并不相关。你不是在写硬件。