0

所以,我正在设计自己的虚拟 CPU。我有一些寄存器和内存,可以执行一些基本指令。但是,现在我被困住了。

我如何区分(在我组装的“机器代码”中):

LDA $02 ; Load the hex value 0x01 into register A

LDA B   ; Load the value of B into A

现在我已将操作数 ($02B) 都编码为0x02. 该指令LDA被编码为单个字(此时为 uint16)。

这显然会带来问题。解决此问题的最佳方法是什么?我想我有以下选择:

  1. 以某种方式将我们正在处理的值或寄存器(或稍后的内存位置)的指令编码为 16 位
  2. 为不同的操作数创建不同的指令。例如LOADIA, LOADRA,LOADMA分别用于文字、寄存器和内存。

恕我直言,选项 1 是最好的。您能否确认 1 是一个有效选项或提供其他处理此问题的方法。谢谢!

4

3 回答 3

3

首先将助记符转换为长手。

lda $02变成ld a $02变成load immediate a with 02

lda b变成ld a b变成copy register a from b

可以看出lda不一定是指令,你需要看整个。此外,如果您保持所有指令的长度相同,则可以获得更好的性能(使用真正的处理器)。

看看 ARM 处理器,它有据可查、干净且仍在使用(很多)。http://simplemachines.it/doc/arm_inst.pdf

于 2014-07-01T11:55:35.767 回答
1

X86 CPU 使用所谓的 Mod R/M-bytes 或 Postbytes。

Instruction Prefix                0 or 1 Byte
Address-Size Prefix               0 or 1 Byte
Operand-Size Prefix               0 or 1 Byte
Segment Prefix                    0 or 1 Byte
Opcode                            1 or 2 Byte
Mod R/M                           0 or 1 Byte
SIB, Scale Index Base (386+)      0 or 1 Byte
Displacement                      0, 1, 2 or 4 Byte (4 only 386+)
Immediate                         0, 1, 2 or 4 Byte (4 only 386+)

Format of Postbyte(Mod R/M from Intel)
------------------------------------------
MM RRR MMM

MM  - Memory addressing mode
RRR - Register operand address
MMM - Memory operand address

RRR Register Names
Filds  8bit  16bit  32bit
000    AL     AX     EAX
001    CL     CX     ECX
010    DL     DX     EDX
011    Bl     BX     EBX
100    AH     SP     ESP
101    CH     BP     EBP
110    DH     SI     ESI
111    BH     DI     EDI

---

16bit memory (No 32 bit memory address prefix)
MMM   Default MM Field
Field Sreg     00        01          10             11=MMM is reg
000   DS       [BX+SI]   [BX+SI+o8]  [BX+SI+o16]
001   DS       [BX+DI]   [BX+DI+o8]  [BX+DI+o16]
010   SS       [BP+SI]   [BP+SI+o8]  [BP+SI+o16]
011   SS       [BP+DI]   [BP+DI+o8]  [BP+DI+o16]
100   DS       [SI]      [SI+o8]     [SI+o16]
101   DS       [DI]      [DI+o8]     [SI+o16]
110   SS       [o16]     [BP+o8]     [BP+o16]
111   DS       [BX]      [BX+o8]     [BX+o16]
Note: MMM=110,MM=0 Default Sreg is DS !!!!

32bit memory (Has 67h 32 bit memory address prefix)
MMM   Default MM Field
Field Sreg     00        01          10             11=MMM is reg
000   DS       [EAX]     [EAX+o8]    [EAX+o32]
001   DS       [ECX]     [ECX+o8]    [ECX+o32]
010   DS       [EDX]     [EDX+o8]    [EDX+o32]
011   DS       [EBX]     [EBX+o8]    [EBX+o32]
100   SIB      [SIB]     [SIB+o8]    [SIB+o32]
101   SS       [o32]     [EBP+o8]    [EBP+o32]
110   DS       [ESI]     [ESI+o8]    [ESI+o32]
111   DS       [EDI]     [EDI+o8]    [EDI+o32]
Note: MMM=110,MM=0 Default Sreg is DS !!!!

---

SIB is (Scale/Base/Index)
SS BBB III
Note: SIB address calculated as:
<sib address>=<Base>+<Index>*(2^(Scale))

Fild   Default Base
BBB    Sreg    Register   Note
000    DS      EAX
001    DS      ECX
010    DS      EDX
011    DS      EBX
100    SS      ESP
101    DS      o32        if MM=00 (Postbyte)
SS      EBP        if MM<>00 (Postbyte)
110    SS      ESI
111    DS      EDI

Fild  Index
III   register   Note
000   EAX
001   ECX
010   EDX
011   EBX
100              never Index SS can be 00
101   EBP
110   ESI
111   EDI

Fild Scale coefficient
SS   =2^(SS)
00   1
01   2
10   4
11   8
于 2014-07-01T11:35:20.910 回答
1

由于您已经获得了一些回放,因此我将尝试简化答案。

您可以以特定方式定义您的 cpu 命令。例如,您的LDA命令可以定义为:1010101x(二进制格式),其中 1010101 表示LDA,最后一位指定下一个字节是立即值 (0) 还是寄存器 (1)。

因此,在您的情况下,它将是:

LDA $02  = 10101010 00000010 
LDA B    = 10101011 00000010

这只是一个例子,但这就是我所知道的所有处理器的工作方式。对于某些命令,您可能会使用更多的 xxx 位。您也可能有零个(NOP指令示例)。

于 2014-07-01T12:50:29.657 回答