首页 文章

英特尔X86 - 如何通过'32-bit'影响内存访问/写入?

提问于
浏览
0

维基百科说:

32位CPU和ALU架构是基于寄存器,地址总线或该大小的数据总线的架构 .

因此每个存储器地址指的是32位 .

但究竟是什么意思呢?在同意为32位的Intel X86-32汇编中,有32位寄存器,16位寄存器和8位寄存器 .

考虑以下程序集

mov ax, bx  ; move 16-bit bx into 16-bit ax
mov ah, bh  ; move 8-bit bh into 8-bit ah
movzx eax, ax ; move 16-bit ax into 32-bit eax (zero-extending ax)

所有这些线都可以接受吗?如果是这样,为什么我们坚持认为这是一个32位系统?不可思议的是,程序集管理较小的地址大小 .

2 回答

  • 2

    维基百科的解释有点模糊,但这又是一个很难得到精确定义的主题 . 以“乘用车”这个词为例 . 你能准确定义吗?没有 .

    过去,32位架构是一个拥有32位数据总线的架构,但现在情况要复杂得多 .

    今天的工作定义是架构的位数倾向于与最大可用通用寄存器的位大小一致 .

    因此,32位系统可以预期具有8位,16位和32位寄存器,但(通常)没有更大的寄存器 . 类似地,可以预期16位系统具有8位和16位寄存器,但(通常)没有更大的寄存器 .

  • 3

    x86-32(又名IA-32)是16位8086的32位扩展,旨在将asm源从8位8080轻松移植到8086.(逆编译时为Why are first four x86 GPRs named in such unintuitive order?) .

    这个历史就是为什么现代x86有如此多的部分寄存器,直接支持8位和16位操作数大小 .

    大多数其他具有32位寄存器的架构仅允许窄负载/存储,ALU操作仅为完整寄存器宽度 . (但这也是因为它们是RISC架构(MIPS,SPARC,甚至是稍微不那么RISCy ARM),而x86绝对是CISC架构 . )

    像MIPS这样的RISC架构的64位扩展仍然支持32位操作,通常隐含地将32位结果零扩展到"full"寄存器the same way x86-64 does . (特别是如果64位不是新模式,而只是在同一模式下的新操作码,其语义设计使得现有机器代码在寻址模式时将以相同方式运行使用完整寄存器但所有传统操作码仍然只有写低32位 . )

    因此,您在x86-32上观察到的情况(支持对部分寄存器进行窄操作)存在于所有体系结构中,作为旧体系结构的更广泛扩展,无论它是以新模式运行(机器代码解码方式不同),还是不 . 只是x86的祖先在x86内回到了16位,而在8086上又回到了8位 .


    Motorola 68000有32位寄存器,根据维基百科"the main ALU"只有16位 . (可能32位操作较慢或者某些不受支持,但绝对支持32位add /和指令 . 我不知道维基百科为什么这么说的细节) .

    最初68000设计用于16位外部总线,因此16位加载/存储在这些早期CPU上更有效 . 我认为后来68k CPU扩展了数据总线,使得32位加载/存储速度与16位一样快 . 无论如何, I think m68k is another example of a 32-bit architecture that supports a lot of 16-bit operations. 维基百科将其描述为"a 16/32-bit CISC microprocessor" .


    通过添加高速缓存,两倍于16位整数的高速缓存行可以作为32位整数,因此对于顺序访问,16位仅占平均/持续内存带宽的一半 . Talking about "bus width" gets more complicated when there's cache ,因此加载/存储单元和缓存之间以及缓存和内存之间存在总线或内部数据路径 . (并且在多级缓存中,在不同级别的缓存之间) .


    决定是否调用架构(或该架构的特定实现)8/16/32/64位是非常随意的 . The marketing department is likely to pick the widest thing they can justify, and use that in descriptions of the CPU . 这可能是数据总线或寄存器宽度,地址空间或其他任何内容 . (许多8位CPU在两个8位寄存器的串联中使用16位地址,尽管它们中的大多数并不试图声称是16位 . 但它们可能被宣传为8/16位 . )


    32-bit x86 is considered 32-bit because that's the maximum width of a pointer, or a "general purpose" integer register. 386增加了几个主要的新功能:32位整数寄存器/操作数大小(可通过实模式前缀访问)和带虚拟内存分页的32位保护模式,其中默认地址和操作数大小为32位 .


    The physical CPUs that can run IA-32 machine code today 拥有比第一代386SX CPU更宽的总线和更好的内存带宽,但他们仍然支持相同的IA-32架构(加上扩展) .

    目前,基本上所有新的x86 CPU也可以在x86-64模式下运行 . 在IA-32模式下运行时,现代x86 CPU将仅使用其64位物理整数寄存器的低32位(对于在32位或16位模式下使用32位操作数大小的指令) .

    但除了整数寄存器外,还有80位x87寄存器(可用作64位整数SIMD MMX寄存器),还有XMM / YMM / ZMM寄存器(SSE / AVX / AVX512) .

    SSE2是x86-64的基线,并且现在可以在大多数32位代码中假设,因此至少有128位寄存器可用,并且即使在32位中也可用于64位整数加/子/移位模式与paddq等指令 .

    现代CPU在矢量加载/存储单元和缓存之间也至少有128位连接,因此数据适合L1d缓存时的加载/存储/复制带宽不受外部双/三/四通道DDR3 / DDR4 DRAM的限制控制器(通过64位外部总线进行8x 64位的突发传输=一个64字节高速缓存线) .

    相反,CPU具有较大的快速缓存,包括共享的L3缓存,因此由一个内核写入并由另一个内核读取的数据在L3中仍然很热 . 请参阅some details on how cache can be that fast for Intel IvyBridge,即使它支持256位AVX指令,它也只有128位加载/存储路径 . Haswell也将加载/存储路径扩展到256位 . Skylake-AVX512将寄存器和数据路径扩展为512位用于L1d高速缓存,以及L1d和L2之间的连接 .

    但在纸面上,x86(因为P5 Pentium及更高版本)仅保证aligned loads/stores up to 64 bits are atomic,因此允许使用SSE的实现将128位XMM加载/存储分成两个64位的一半 . 奔腾III和奔腾M实际做到了这一点 . 但需要注意的是,i586 Pentium在x86-64之前已经过了十年,而加载/存储64位的唯一方法是使用x87 fldfild . Pentium MMX可以进行64位MMX movq 加载/存储 . 无论如何,这个原子性保证包括未缓存的商店(例如MMIO),这是可能的(便宜,没有总线锁),因为 the P5 microarchitecture has a 64-bit external bus, even though it's strictly 32-bit other than the FPU .

    即使是纯整数代码也可以从宽数据路径中受益,因为它增加了整数代码的带宽,其中加载/存储在L3或特别是L2缓存中,而不是L1d缓存 .


    对x86的所有这些SIMD扩展使其比纯粹的32位整数架构更强大 . 但是当在32位模式下运行时,它仍然是由386引入的相同模式,我们将其称为32位模式 . 这个名字和其他名字一样好,但不要试图过多地阅读它 .

    实际上,除了整数/指针寄存器宽度之外,不要读取任何内容 . 它运行的硬件通常具有64位整数寄存器和48位虚拟地址空间 . 数据总线缓存各种巨大的宽度,以及复杂的无序机器,以便在actually looking at a window of up to 224 uops to find instruction-level parallelism时提供按顺序运行的错觉 . (Skylake / Kaby Lake / Coffee Lake ROB尺寸) .

相关问题