当前位置: 首页 > news >正文

一个alignment trap的解决办法

在移植一份代码时,遇到一个alignment trap的错误:

 经过定位,触发alignment trap的汇编语句如下:

printk("status %#x\r\n", stData.info->status);

38c0:    f8d4 3181     ldr.w    r3, [r4, #385]    ; 0x181
38c4:    f240 2261     movw    r2, #609    ; 0x261
38c8:    485d          ldr    r0, [pc, #372]
38ca:    9301          str    r3, [sp, #4]
38cc:    4b57          ldr    r3, [pc, #348]
38ce:    9200          str    r2, [sp, #0]
38d0:    4619          mov    r1, r3
38d2:    f7ff fffe     bl    0 <printk>

原因是ARM对ldr指令访问内存时要求4字节对齐,根据r4+0x181=0xd0b02181,这个地址不是4字节对齐的,所以arm触发了alignment异常。

造成这个对齐异常,与下面这个结构体的定义有关:

#pragma pack(push, 1)

struct
{
    unsigned int bit_0_3     :4;  
    unsigned int bit_7_4     :4;
    unsigned int status      :32; 
    ......
};

#pragma pack(pop)

由于使用了1字节对齐(为了节省内存),所以访问status成员时,就访问了4字节对齐偏移1字节的地址了。 

解决办法

使用-mno-unaligned-access编译选项,该编译选项是 ARM 架构编译器的优化选项,用于禁止编译器生成可能导致非对齐内存访问的指令。

重新编译后对应的汇编代码:

printk("int_status %#x\r\n", stData.info->status);
3b50:    f894 2182     ldrb.w    r2, [r4, #386]    ; 0x182
3b54:    f894 3181     ldrb.w    r3, [r4, #385]    ; 0x181
3b58:    4879          ldr    r0, [pc, #484]    ; (3d40 <EncFwAnaNodeInfo+0x1618>)
3b5a:    ea43 2302     orr.w    r3, r3, r2, lsl #8
3b5e:    f894 2183     ldrb.w    r2, [r4, #387]    ; 0x183
3b62:    ea43 4302     orr.w    r3, r3, r2, lsl #16
3b66:    f894 2184     ldrb.w    r2, [r4, #388]    ; 0x184
3b6a:    ea43 6302     orr.w    r3, r3, r2, lsl #24
3b6e:    f240 2261     movw    r2, #609    ; 0x261
3b72:    9301          str    r3, [sp, #4]
3b74:    4b6d          ldr    r3, [pc, #436]    ; (3d2c <EncFwAnaNodeInfo+0x1604>)
3b76:    9200          str    r2, [sp, #0]
3b78:    4619          mov    r1, r3
3b7a:    f7ff fffe     bl    0 <printk>

发现之前的

ldr.w    r3, [r4, #385] 

变成了

ldrb.w    r2, [r4, #386] 

ldrb.w    r3, [r4, #385]

ldrb.w    r2, [r4, #387] 

ldrb.w    r2, [r4, #388]

这是一种以时间换空间的解决方法。

http://www.dtcms.com/a/108843.html

相关文章:

  • TRDI 公司的RiverPro 和 RioPro ADCP 用户指南
  • UE5 Cast To的作用
  • 图形库 EasyX - EasyX 初识(EasyX 概述、EasyX 下载与安装、打开一个窗口、打开一个彩色窗口、绘制简易图形、输出文字)
  • .NET 创建MCP使用大模型对话二:调用远程MCP服务
  • 本地化部署DeepSeek-R1蒸馏大模型:基于飞桨PaddleNLP 3.0的实战指南
  • OC添加滑块验证码
  • XLRS-Bench:您能否理解极端大型超高分辨率遥感影像?
  • 预测分析(三):基于机器学习的分类预测
  • 基于微信小程序的生签到系统设计与实现
  • c语言数据结构--------拓扑排序和逆拓扑排序(Kahn算法和DFS算法实现)
  • MySQL的安装与初始化流程
  • 联想M7400打印机怎么清零
  • 基于LangChain和通义(Tongyi)实现NL2SQL的智能检索(无需训练)
  • Spring Boot 3.4.3 和 Spring Security 6.4.2 实现基于内存和 MySQL 的用户认证
  • 《Linux内存管理:实验驱动的深度探索》【附录】【实验环境搭建 1】【Qemu 运行 linux 6.0.9】
  • c++函数中的多态是怎样体现的
  • Cursor的主要好处
  • 【排序算法】堆排、快排、归并排、各种排
  • 动态规划 线性dp系列:数字三角形
  • Mysql 中数据主键类型不一样导致数据插入速度快慢问题
  • Java开发如何基于 Spring AI Alibaba 玩转 MCP:从发布、调用到 Claude Manus 集成
  • 2.5路径问题专题:LeetCode 64. 最小路径和
  • Python的三方库之Pandas(三)
  • MetaBase Mysql8.0连接不上
  • 怎么理解量子比特模型,迁移到量子计算机开始编程
  • 飞桨新一代框架3.0正式发布:加速大模型时代的技术创新与产业应用
  • AF3 OpenFoldMultimerDataset类解读
  • 洛谷题单3-P1035 [NOIP 2002 普及组] 级数求和-python-流程图重构
  • JavaScript日期对象
  • Python 编程实战:打造高效便捷的目录结构生成器