You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于--mno-unaligned-access编译选项的精确行为问询

关于ARM Compiler --mno-unaligned-access选项的行为疑问

根据ARM Compiler armclang参考指南6.4版本的描述:

如果禁用非对齐访问,打包数据结构中的字会逐字节访问。

但在实际测试中,读取打包结构体数组的第二个元素的int成员时,编译生成的机器码先执行了一次单字节访问(1e0行),随后使用了对齐的字访问(1e2行),而非预期的全字节访问。现确认:启用--mno-unaligned-access选项后,是否即使是打包结构体,只要目标地址对齐就可以用字访问?

示例代码

typedef struct __attribute__((packed, aligned(1))) MyStruct{
    int A;
    short B;
    char C;
} MyStruct_t;
int main(void) {
    MyStruct_t M[2];
    int D, E;
    M[0].A = 0xffffffff;
    M[1].A = 0xeeeeeeee;
    D = M[0].A;
    E = M[1].A;
    D = E;
    return 0 ;
}

编译命令(MCUXpresso IDE)

arm-none-eabi-gcc -nostdlib -Xlinker -Map="m7_experiments.map" -Xlinker --cref -Xlinker --gc-sections -Xlinker -print-memory-usage -mcpu=cortex-m7 -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -T "m7_experiments_Debug.ld" -o "m7_experiments.axf" $(OBJS) $(USER_OBJS) $(LIBS)

使用--mno-unaligned-access编译得到的机器码

000001b0 <main>:
 1b0:   b480            push    {r7}
 1b2:   b087            sub     sp, #28
 1b4:   af00            add     r7, sp, #0
 1b6:   f04f 33ff       mov.w   r3, #4294967295 ; 0xffffffff
 1ba:   603b            str     r3, [r7, #0]
 1bc:   2300            movs    r3, #0
 1be:   f063 0311       orn     r3, r3, #17
 1c2:   71fb            strb    r3, [r7, #7]
 1c4:   2300            movs    r3, #0
 1c6:   f063 0311       orn     r3, r3, #17
 1ca:   723b            strb    r3, [r7, #8]
 1cc:   2300            movs    r3, #0
 1ce:   f063 0311       orn     r3, r3, #17
 1d2:   727b            strb    r3, [r7, #9]
 1d2:   727b            strb    r3, [r7, #9]
 1d4:   2300            movs    r3, #0
 1d6:   f063 0311       orn     r3, r3, #17
 1da:   72bb            strb    r3, [r7, #10]
 1dc:   683b            ldr     r3, [r7, #0]
 1de:   617b            str     r3, [r7, #20]
 1e0:   79fb            ldrb    r3, [r7, #7]
 1e2:   68ba            ldr     r2, [r7, #8]
 1e4:   f022 427f       bic.w   r2, r2, #4278190080     ; 0xff000000
 1e8:   0212            lsls    r2, r2, #8
 1ea:   4313            orrs    r3, r2
 1ec:   613b            str     r3, [r7, #16]
 1ee:   693b            ldr     r3, [r7, #16]
 1f0:   617b            str     r3, [r7, #20]
 1f2:   2300            movs    r3, #0
 1f4:   4618            mov     r0, r3
 1f6:   371c            adds    r7, #28
 1f8:   46bd            mov     sp, r7
 1fa:   f85d 7b04       ldr.w   r7, [sp], #4
 1fe:   4770            bx      lr

补充:使用-munaligned-access编译得到的机器码

000001b0 <main>:
 1b0:   b480            push    {r7}
 1b2:   b087            sub     sp, #28
 1b4:   af00            add     r7, sp, #0
 1b6:   f04f 33ff       mov.w   r3, #4294967295 ; 0xffffffff
 1ba:   603b            str     r3, [r7, #0]
 1bc:   2300            movs    r3, #0
 1be:   f063 0311       orn     r3, r3, #17
 1c2:   71fb            strb    r3, [r7, #7]
 1c4:   2300            movs    r3, #0
 1c6:   f063 0311       orn     r3, r3, #17
 1ca:   723b            strb    r3, [r7, #8]
 1cc:   2300            movs    r3, #0
 1ce:   f063 0311       orn     r3, r3, #17
 1d2:   727b            strb    r3, [r7, #9]
 1d4:   2300            movs    r3, #0
 1d6:   f063 0311       orn     r3, r3, #17
 1da:   72bb            strb    r3, [r7, #10]
 1dc:   683b            ldr     r3, [r7, #0]
 1de:   617b            str     r3, [r7, #20]
 1e0:   f8d7 3007       ldr.w   r3, [r7, #7]
 1e4:   613b            str     r3, [r7, #16]
 1e6:   693b            ldr     r3, [r7, #16]
 1e8:   617b            str     r3, [r7, #20]
 1ea:   2300            movs    r3, #0
 1ec:   4618            mov     r0, r3
 1ee:   371c            adds    r7, #28
 1f0:   46bd            mov     sp, r7
 1f2:   f85d 7b04       ldr.w   r7, [sp], #4
 1f6:   4770            bx      lr

解答

核心结论

是的,--mno-unaligned-access的核心规则是禁止生成非对齐的字/半字访问指令,而非强制所有打包结构体成员必须逐字节访问。编译器会在遵守规则的前提下尽可能优化:当要读取的多字节数据的部分地址处于对齐位置时,会优先使用对齐的字访问提升效率。

具体分析

你的示例中,M[1].A的起始地址r7+7是非对齐的,但从r7+8开始是4字节对齐地址。编译器拆分了读取操作:

  1. 用ldrb读取r7+7处的第一个字节;
  2. 用对齐的ldr读取r7+8开始的4字节;
  3. 通过bic(清除高位字节)、lsl(左移)、orr(拼接)操作,把第一个字节和后续3字节组合成完整的int值。

这种做法既符合--mno-unaligned-access禁止非对齐字访问的要求,又利用了对齐访问的高效性,属于编译器的合理优化。

而启用-munaligned-access时,编译器直接生成ldr.w指令读取非对齐地址的完整int,这也符合允许非对齐访问的规则。

内容的提问来源于stack exchange,提问作者e.ad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 18:40:39