【问题标题】:Should all code compiled for 32 bit machines be in 4 byte chunks?为 32 位机器编译的所有代码都应该是 4 字节块吗?
【发布时间】:2013-11-19 02:58:55
【问题描述】:

我编写了一个简单的 32 位汇编代码:

movl  $0x542412e6, %eax
movl  %ebp , %edx
addl  $0x30, %edx
movl  %edx, %ebp
pushl 0x08048dd6
ret

当我运行这个命令时:

gcc -m32 -c e.s

我得到以下 18 个字节:

0:  b8 e6 12 24 54          mov    $0x542412e6,%eax
5:  89 ea                   mov    %ebp,%edx
7:  83 c2 30                add    $0x30,%edx
a:  89 d5                   mov    %edx,%ebp
c:  68 d6 8d 04 08          push   $0x8048dd6
11: c3                      ret 

为什么目标代码是 18 字节而不是 20 或 16?对于 32 位机器,它不应该总是 4 字节的字吗?

【问题讨论】:

  • 不。代码必须位于架构定义的边界上。这可能与机器的“字大小”有某种关系,但这种关系很少那么强。 (特别是 x86 指令集在 8 位和 16 位机器中具有继承性,并且存在一定程度的向前/向后兼容性。)

标签: gcc assembly x86 instructions


【解决方案1】:

指令大小不与数据或地址总线大小相关。一些 16 位 x86 CPU 有 3 种完全不同的大小,包括 8 位数据总线、20 位地址总线和 可变长度指令 大小。现代 32 位或 64 位 x86 也具有可变长度指令以实现向后兼容性。

只要看看movl $0x542412e6, %eax 和pushl 0x08048dd6 行,你就会发现不可能在32 位数据内编码32 位立即数数据、操作码和寄存器。如果架构使用 32 位 固定长度 指令,那么它必须使用多条指令或文字池来加载 32 位常量。

RISC 架构通常具有固定宽度的指令,作为 代码密度 和 解码器简单性 之间的权衡。但也存在指令大小不同于 32 位的 32 位 RISC 架构。例如,MIPS16e 和 ARM thumb v1 具有 16 位指令,而 ARM thumb2 和 dalvikVM 具有可变长度指令。现代 64 位 RISC 架构也没有 64 位指令,而是经常坚持使用 32 位大小

【讨论】:

    【解决方案2】:

    x86 没有固定长度的指令,也不需要对齐。架构需要使其指令匹配某个偏移量。这就是为什么x86 进程需要更多逻辑来解码 RISC 处理器的指令。

    现在大多数 RISC 架构确实有固定长度的指令,并且会被调整。

    【讨论】:

    • 我熟悉的大多数 RISC 机器都有 16 位和 32 位指令。包括它们之母——IBM 801。
    • 最初的 RISC 机器是类似 IBM 7000 系列机器的设备,具有简单的寄存器和简单的指令格式。那些机器是 36 位的。见en.wikipedia.org/wiki/IBM_7090
    • @HotLicks:后来添加了 ARM thumb 和 MIPS 16 位紧凑指令,作为嵌入式系统的优化,消耗 CPU 复杂性以支持两种模式,和/或支持短和长的混合指示。早期的 MIPS、Alpha、SPARC、RISC-V 等经典 RISC 系统只有 32 位指令字。当前的 AArch64 相同:仅支持 32 位指令字。 (即使是早期的 ARM 也比 MIPS 等系统的 RISCy 少得多;它只有一条指令可以执行 1 到 15 次存储,因此它不可避免地要进行微编码。以及复杂的寻址模式......)
    • @PeterCordes - 使用 16 位指令是因为大多数情况下只需要这些指令,而更少的位意味着内存吞吐量不是瓶颈。添加了 32 位指令以允许在指令中包含文字和长地址,但大多数指令不需要这些。
    • @HotLicks:我不是在谈论 IBM 801,我只是在谈论后来的 CPU,它们的第一代类似于 en.wikipedia.org/wiki/Classic_RISC_pipeline(以及模仿它的 ISA,比如 DEC Alpha。)他们通常有一个 I-cache,简单的解码是一个优先事项。经典 MIPS 我实际上直接使用指令位作为内部控制信号,因此解码非常容易。如果没有额外的处理阶段,这对于紧凑的 16 位指令是不可能的。但是分支需要在ID阶段计算取/不取,所以只有1个延迟分支槽
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-20
    • 1970-01-01
    • 2010-10-22
    相关资源
    最近更新 更多