8086从RAM中加载程序
Loading program from RAM in 8086
8086 使用的是 16 位指令,但 RAM 地址只有 8 位,那么 CPU 如何从 RAM 加载程序?它是否加载一个地址然后检查指令是否需要 1/2/3 字节(例如将立即数移动到寄存器 8/16 位)然后执行操作或者我弄错了一个 RAM 'space' 16 位大吗?
许多指令是多字节的,是的,这意味着它们跨越两个或多个地址。
8086的内存总线是16位的,所以一次操作可以加载16位(两个相邻的地址)。您将字节可寻址内存与总线宽度混淆了。
Does it load one address and then checks if the instruction needs 1/2/3 bytes (e.g. moving a immediate to a register 8/16 bit)
当总线不忙时,它会不断地将指令字节提取到一个 6 字节的预取缓冲区中(一次 2 个字节,因为它是一个 16 位 CPU 和 16 位总线)由 运行.
指令触发的数据访问
缓冲区足够容纳最大允许的 8086 指令1(不包括前缀,在 CPU 获取操作码之前每个时钟周期处理一个前缀).当它执行完前一条指令时,它会查看缓冲区。请参阅下面的 link 以获得更好的描述,但它可能会尝试将缓冲区解码为整个指令,或者至少找到一个操作码,否则等待下一次提取再试一次。 (我不确定它可以为更长的指令流水线获取后面的字节多少;如果它可以在发生这种情况时开始执行。)
注 1: 但是 8088 及其 8 位总线缩小了预取缓冲区 to 4 bytes, see this retrocomputing Q&A。但显然 8088 除了总线接口单元 (BIU) 之外具有相同的晶体管布局。所以它,因此 8086,不能依赖于能够在预取缓冲区中保存整个指令,因为 8088 可以执行 mov word [0x1234], 0x5678
(6 字节:opcode + modrm + disp16 + imm16)。但是操作码 + modrm 只有 2 个字节,在寻址模式下有更多字节用于 disp8 或 disp16,and/or imm8 或 imm16 立即数,所以大概这些可以稍后获取/解码。
这篇8086门级逆向工程文章Latches inside: Reverse-engineering the Intel 8086's instruction register说8086的实际指令寄存器是1个字节,保存着当前正在执行的指令的操作码。 (直到后来 CPU 才引入任何 0F xx
2 字节操作码)。
另请参阅:8086 CPU architecture,这是“8086 代码获取”的第一个命中。它确认 fetch 和 execute 确实重叠,所以它以最基本的方式流水线化。
TL:DR:它取入一个缓冲区,直到它有一个完整的指令要解码。然后它将任何额外的字节移到缓冲区的前面,因为它们是下一条指令的一部分。
我读到通常指令获取是 8086 的瓶颈,因此优化代码大小几乎比其他一切都重要。
流水线 CPU 无需等待上一条指令执行完毕即可开始解码。现代 CPUs 也有 多 更高的带宽代码获取,所以他们有一个解码指令队列准备好(除非分支搞砸了。)见 http://agner.org/optimize/, and other links in the x86 标记维基。
此外,一些非常常见的指令是单字节的,例如push r16
。
8086 使用的是 16 位指令,但 RAM 地址只有 8 位,那么 CPU 如何从 RAM 加载程序?它是否加载一个地址然后检查指令是否需要 1/2/3 字节(例如将立即数移动到寄存器 8/16 位)然后执行操作或者我弄错了一个 RAM 'space' 16 位大吗?
许多指令是多字节的,是的,这意味着它们跨越两个或多个地址。
8086的内存总线是16位的,所以一次操作可以加载16位(两个相邻的地址)。您将字节可寻址内存与总线宽度混淆了。
Does it load one address and then checks if the instruction needs 1/2/3 bytes (e.g. moving a immediate to a register 8/16 bit)
当总线不忙时,它会不断地将指令字节提取到一个 6 字节的预取缓冲区中(一次 2 个字节,因为它是一个 16 位 CPU 和 16 位总线)由 运行.
指令触发的数据访问缓冲区足够容纳最大允许的 8086 指令1(不包括前缀,在 CPU 获取操作码之前每个时钟周期处理一个前缀).当它执行完前一条指令时,它会查看缓冲区。请参阅下面的 link 以获得更好的描述,但它可能会尝试将缓冲区解码为整个指令,或者至少找到一个操作码,否则等待下一次提取再试一次。 (我不确定它可以为更长的指令流水线获取后面的字节多少;如果它可以在发生这种情况时开始执行。)
注 1: 但是 8088 及其 8 位总线缩小了预取缓冲区 to 4 bytes, see this retrocomputing Q&A。但显然 8088 除了总线接口单元 (BIU) 之外具有相同的晶体管布局。所以它,因此 8086,不能依赖于能够在预取缓冲区中保存整个指令,因为 8088 可以执行 mov word [0x1234], 0x5678
(6 字节:opcode + modrm + disp16 + imm16)。但是操作码 + modrm 只有 2 个字节,在寻址模式下有更多字节用于 disp8 或 disp16,and/or imm8 或 imm16 立即数,所以大概这些可以稍后获取/解码。
这篇8086门级逆向工程文章Latches inside: Reverse-engineering the Intel 8086's instruction register说8086的实际指令寄存器是1个字节,保存着当前正在执行的指令的操作码。 (直到后来 CPU 才引入任何 0F xx
2 字节操作码)。
另请参阅:8086 CPU architecture,这是“8086 代码获取”的第一个命中。它确认 fetch 和 execute 确实重叠,所以它以最基本的方式流水线化。
TL:DR:它取入一个缓冲区,直到它有一个完整的指令要解码。然后它将任何额外的字节移到缓冲区的前面,因为它们是下一条指令的一部分。
我读到通常指令获取是 8086 的瓶颈,因此优化代码大小几乎比其他一切都重要。
流水线 CPU 无需等待上一条指令执行完毕即可开始解码。现代 CPUs 也有 多 更高的带宽代码获取,所以他们有一个解码指令队列准备好(除非分支搞砸了。)见 http://agner.org/optimize/, and other links in the x86 标记维基。
此外,一些非常常见的指令是单字节的,例如push r16
。