标签大小不固定时如何处理前向引用

How to handle forward referencing when Label size is not fixed

我正在尝试用 C++ 编写 8086 仿真器。 但是我遇到了一个问题。

假设代码是:

MOV AL, BL
JMP X
MOV BL, CL
MOV DL, CL
.
.
.
X:
ADD AX, BX
HLT

现在 JMP X 的机器码将取决于 X,是否 near location or short location

near: 8位地址[00-ff]

短:16位地址(ff-ffff]

因此,如果 JMP 指令的大小过去是恒定的(固定大小),那么我可以进一步移动,只要我找到 X,我就可以将它的地址放回去。 但是这里我不能再移动了,因为下一个位置也取决于 JMP X,而且它的大小不固定。

不知道怎么处理。

jmp 你可能有更多问题。请参阅以下可能的操作码及其含义:

EB cb   JMP rel8        Jump short, relative, displacement relative to next instruction.
E9 cw   JMP rel16       Jump near, relative, displacement relative to next instruction.
E9 cd   JMP rel32       Jump near, relative, displacement relative to next instruction.
FF /4   JMP r/m16       Jump near, absolute indirect, address given in r/m16.
FF /4   JMP r/m32       Jump near, absolute indirect, address given in r/m32.
EA cd   JMP ptr16:16    Jump far, absolute, address given in operand.
EA cp   JMP ptr16:32    Jump far, absolute, address given in operand.
FF /5   JMP m16:16      Jump far, absolute indirect, address given in m16:16.
FF /5   JMP m16:32      Jump far, absolute indirect, address given in m16:32.

所以,你需要考虑更多的特殊情况。

解决方案是实现多通道汇编程序。无论如何,您需要将所有操作码和操作数存储在 std::vector 或任何地方。然后你就可以在第二步设置正确的数据了。

如果你为操作码和操作数定义一个struct并将所有这些结构存储在一个std::vector中,它不会对另一个opcodes/operands产生影响。您还可以 运行 多次传递,直到一切正确。

然后,当一切都修复后,您可以再次检查 std::vector 并发出真正需要的数据。

你可能会想到:

struct Operation {
    bool updateNeeded{false};
    unsigned int opcode{};
    unsigned long operand1{};
    unsigned long operand2{};
    unsigned long operand3{};
    size_t indexOfRelated{};
};

std::vector<Operation> operation;

当然你可以根据需要添加更多的属性。

然后您可以读取源数据并填充std::vector。阅读完完整的源代码后,您将再次查看数据,并修复未解决的问题。

然后,将其交给虚拟机,或者发出最终指令。