assembly - 从 8086 的 RAM 加载程序

标签 assembly x86-16 cpu-architecture processor

8086 使用 16 位指令,但 RAM 地址仅保存 8 位,那么 CPU 如何从 RAM 加载程序呢?它是否加载一个地址,然后检查指令是否需要 1/2/3 字节(例如,将立即数移动到寄存器 8/16 位),然后执行操作,还是我弄错了,一个 RAM“空间”是 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 位总线的 16 位 CPU)正在运行。

缓冲区足够大,可以容纳允许的最大 8086 指令1(不包括前缀,在 CPU 到达操作码之前每个时钟周期处理一次)。当执行完前一条指令后,它会查看缓冲区。请参阅下面的链接以获取更好的描述,但它可能会尝试将缓冲区解码为整个指令,或者至少找到一个操作码,否则等待下一次获取以重试。 (我不确定它可以在多大程度上通过管道获取更长的指令的后续字节;如果它可以在发生这种情况时开始执行。)

注释 1:但是 8088 及其 8 位总线缩小了预取缓冲区 to 4 bytes ,参见this retrocomputing Q&A 。但显然,除了总线接口(interface)单元(BIU)之外,8088 具有相同的晶体管布局。因此,它以及 8086 一定不能依赖于能够在预取缓冲区中保存整个指令,因为 8088 可以执行 mov word [0x1234], 0x5678 (6 个字节:操作码 + modrm + disp16 + imm16)。但操作码 + modrm 只有 2 个字节,寻址模式下的 disp8 或 disp16 和/或 imm8 或 imm16 立即数有更多字节,因此推测这些可以稍后获取/解码。

这篇 8086 门级逆向工程文章,Latches inside: Reverse-engineering the Intel 8086's instruction register ,表示8086的实际指令寄存器是1字节,保存当前正在执行的指令的操作码。 (直到后来的 CPU 才引入了 0F xx 2 字节操作码)。

<小时/>

另请参阅:8086 CPU architecture ,这是“8086 code fetch”的第一个点击。它确认了获取和执行确实重叠,因此它以最基本的方式进行管道化

TL:DR:它取入缓冲区,直到有完整的指令要解码。然后它将任何额外的字节转移到缓冲区的前面,因为它们是下一条指令的一部分。

我读到,取指令通常是 8086 的瓶颈,因此优化代码大小几乎比其他一切都重要。

<小时/>

流水线 CPU 不必等待前一条指令的执行完成即可开始解码。现代CPU还具有更高的取码带宽,因此它们有一个准备好的解码指令队列(除非分支搞乱了它)。请参阅http://agner.org/optimize/ ,以及 中的其他链接标签维基。

<小时/>

此外,一些非常常见的指令是单个字节,例如 push r16 .

关于assembly - 从 8086 的 RAM 加载程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39112261/

相关文章:

arrays - 如何在 MIPS 中初始化数组?

linux - 64位版本的socketcall系统调用Linux

c - 在c中执行汇编代码

汇编、打印ascii码

cuda - 如果我们有 GPGPU,为什么要使用 SIMD?

assembly - CPU 上压入和弹出操作的必要性

assembly - riscv objdump 如何设置打印 x0-x31 寄存器名称而不是 abi 名称

assembly - 8086中方向标志的使用

assembly - 无法获得汇编语言代码的输出

memory - 字可寻址和字节可寻址的区别