gpt4 book ai didi

c++ - 在多个类上定义的面向对象的跳转表

转载 作者:行者123 更新时间:2023-11-28 00:15:33 24 4
gpt4 key购买 nike

我正在将 NMOS6502 仿真器重构为多个类。我想知道是否有一种“面向对象”的方式来定义函数跳转表。基本上,我已经定义了单独的指令类来对相关的 cpu 操作组进行分类——比如“CStackInstHandler”或“CArithmeticInstHandler”,它们将引用一个 cpu 对象。每个指令类都派生自一个抽象指令类。每个派生指令类都有一组函数,这些函数将使用 cpu 对象的公共(public)接口(interface)来更改 cpu 状态,例如:

uint8_t opcode = _memory->readMem(_cpu->getProgramCounter());
AInstructionHandler* _handler = _cpu->getInstHandler(opcode);
_handler->setCpu(&cpu);
_handler->setMemory(&memory);
_handler->execute(opcode);

问题在于,在运行时,需要使用操作码来确定指令处理程序以及为该处理程序定义的适当成员函数。

所以我们有 - 从内存中读取操作码,cpu 使用一个表将操作码映射到指令处理程序类型,然后指令处理程序使用相同的操作码来选择正确的函数。每条指令都会覆盖一个“执行”函数,例如:

void CBranchInstHandler::execute() {
switch(_opcode) {
case 0x90:
this->BCC();
break;
case 0xb0:
this->BCS();
break;
case 0xf0:
this->BEQ();
break;
case 0x30:
this->BMI();
break;
case 0xd0:
this->BNE();
break;
case 0x10:
this->BPL();
break;
default:
break;
}

void CBranchInstHandler::BCC() {
uint16_t address = this->getAddress();
if(!_cpu->isCarry()) {
uint16_t pc = _cpu->getPC();
pc += address;
_cpu->setPC(pc);
}
}

/*more instruction specific functions...*/

我最终进行了两次查找,其中一次是多余的。一个选择处理程序,另一个选择处理程序函数。我觉得这是完成这项任务的错误方法,但我不确定是否有一种替代方法不仅可以分解为非成员函数组。

我想知道是否有人对这个问题有深入的了解。它基本上归结为想要将一个类重构为更小的部分(cpu 类和指令成员函数重构为 cpu 类和指令类),但是所有组件都是如此相互关联,以至于我最终不得不重复自己。引入了冗余。

非面向对象的解决方案是让这些指令成为接受 cpu 引用的非成员函数。然后,将定义一个函数跳转表,指令将通过操作码查找和索引并执行。

这对于对象来说似乎并不实用。我可以将所有指令设为静态或其他内容,但这似乎没有捕获要点。

任何关于即使是无关紧要的问题的见解或信息都会非常有帮助。

谢谢。

最佳答案

我打算将我的评论提升为一个答案:正如您所说,面向对象的解决方案是让子类完全负责决定它们响应哪些操作码。

我建议最简单的方法不是尝试构建一个两阶段的 switch,而是简单地将每个操作码路由到每个 child ,让 child 做出贡献或不做出贡献.这是最低限度的可行解决方案。

如果您需要优化,那么最简单的方法就是重新制定:

void CBranchInstHandler::execute() {
switch(_opcode) {
case 0x90:
this->BCC();
break;
... etc ...
}
}

收件人:

FuncPtr CBranchInstHandler::execute() {
switch(_opcode) {
case 0x90:
return BCC;
... etc ...
}
return NULL;
}

因此每个execute 都会返回它是否确实处理了该操作码。

在父类中,您可以简单地保留一个从操作码到函数指针的表。一个数组就可以了。该表最初将始终包含 NULL

执行操作码时,在表中查找处理程序。如果处理程序在那里,调用它并继续。如果没有,则依次对每个 child 调用 execute 直到有人返回处理程序,然后将它们放入表中然后调用它。因此,您将在运行时及时构建它。每个操作码的第一次运行将花费稍长的时间,但您随后将拥有相当于一个跳转表的内容。

这样做的好处是,它允许有关子进程处理的信息在句法上与实际处理紧密相关,从而减少代码开销和出错的可能性。

关于c++ - 在多个类上定义的面向对象的跳转表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30575382/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com