工程中uint8变量文件比uint32变量文件大4字节的问题排查

前言

(1)如果有嵌入式企业需要招聘湖南区域日常实习生,任何区域的暑假Linux驱动实习岗位,可C站直接私聊,或者邮件:zhangyixu02@gmail.com,此消息至2025年1月1日前均有效
(2)今天在一个交流群看到一个有意思的问题,网友问:开发32位单片机,能够使用unsigned char 就不使用unsigned int,这样是否可以节约内存呢?
(3)当时我看到这个问题是懵的,uint8怎么会比uint32更节省空间呢?
(4)学习本文之前,需要先了解数据的内存分配知识,所以需要各位先了解这篇博客:
RAM明明断电会丢失数据,为什么初始化的全局变量存储在RAM?详细分析程序的存储

网友问题解决思路

(1)首先申明一下这位网友的测试环境,是在STM32F103中进行的相关测试。

问题

(1)这位网友在测试代码工程的时候,发现将unsigned char修改为unsigned int的时候,工程代码会减少4字节。

在这里插入图片描述
在这里插入图片描述

解决思路

(1)对于这个问题,很容易知道大体问题是在哪里。
<1>首先,这个是局部变量,他不会占用实际的空间,因此我们发现,实际变化的内存大小是在code段。
<2>其次,在32位的机器中,CPU寄存器都是32位的,因此在处理数据的时候,低于4字节数据会被提升到4字节再进行处理。
(2)那么,我们就可以大致的推断出,这个地方大概率是需要汇编指令进行字节提升,新增加的汇编指令导致code段增多了。
(3)既然有了上述的基础概念之后,就开始定位问题。
<1>第一步,查看map文件。我们需要知道,这个增加的汇编指令具体是在那个文件中。

在这里插入图片描述

<2>对比uint8uint32map文件中Image component sizes部分,我们能够发现,提升的4字节果然是在main.o中,因此此时就知道是在main.c中的在汇编阶段导致的汇编代码不同的问题。

在这里插入图片描述

<3>查看汇编,使用keil的Debug功能,能够帮我们看到汇编内容,直接在mian.c中开断点,对比汇编代码。我们能够发现,如果是uint32,只有一个BCC的指令,但是如果是uint8就是UXTBBLT

在这里插入图片描述

<4>既然知道的区别之后,开始研读这几条汇编代码,进行对比分析。因为这里是无符号数据的对比,所以说,BCCBLT其实是等效的。如果是有符号数据比较,那么就需要使用BLT。(这是arm汇编的内容,简单了解即可,不会的时候查谷歌、百度、chatgpt)

# uint8
UXTB   r4 , r0 ;将一个8位无符号字节零扩展为32位无符号整数,高位的24位填充为零
CMP    r4 , 0x64 ;将寄存器r4的值和0x64(十进制就是100)对比
BLT    0x0800aA8C ; 如果CMP指令的比较结果是负数(即r4<0x64),则跳转到0x0800aA8C 地址
# uint32
CMP    r4 , 0x64 ;将寄存器r4的值和0x64(十进制就是100)对比
BCC    0x0800aA8C ; 如果前一条CMP指令的比较结果没有产生进位(即r4>=0x64),则执行分支

<5>知道汇编代码的大致意思之后,此时就要考虑汇编代码的大小问题。通过询问chatgpt可知,这三条指令都是4字节,因此,当我们main.c中汇编之后多了一条汇编指令,code段就会增加4字节。

在这里插入图片描述

扩展测试1

问题

(1)我们发现,上面测试的都是局部变量,我们要不试试全局变量看看结果如何?
(2)我们能够发现两个有意思的问题:
<1>对比两个全局变量,我们会发现,生成的代码一模一样。
<2>对比全局变量和局部变量:code段增加了,rodata不变,rw增加4字节,zi段减少了4字节。(这个我也不会,苦笑。查了很久资料,也调了很久,不知道为啥怎么是这样的结果。应该是工程中某些细节影响,具体细节没排查到)

在这里插入图片描述

解决思路

(1)首先我们先看两个全局变量工程怎么会一模一样的。还是直接看map文件,通过对比map文件知道内存布局信息。
(2)我们能够发现main.o的RW-data确实少了3字节数据,但是呢,在(incl. Padding),RW-data却多了3字节数据。

在这里插入图片描述

(3)为什么在(incl. Padding),RW-data却多了3字节数据呢?查阅资料可知,编译器为了满足对齐要求而在数据或代码之间插入额外的填充字节。一般来说,字节对齐只有两种可能:
<1>硬件要求: 许多计算机体系结构对于某些数据类型的访问有硬件对齐的要求。例如,一些处理器可能要求访问特定大小的数据类型的变量时,其地址必须是该数据类型大小的倍数。如果不满足这些要求,可能导致性能下降或者引发硬件异常。如果是采用的冯诺依曼结构,不进行字节对齐,可能导致指令和数据弄混淆。
<2>性能优化: 计算机系统通常会将数据加载到寄存器中进行处理,而寄存器的大小通常是2的幂。如果数据类型的大小是寄存器大小的倍数,那么从内存加载数据到寄存器的操作就更为高效。字节对齐可以确保数据在内存中的地址是寄存器大小的倍数,提高访问速度。
(4)因为这里的测试平台是STM32F103,采用的是CM3内核,因此我打开CM3内核手册可知,寄存器的PUSHPOP永远是4字节对齐的。因此,这里是硬件层面要求进行字节对齐操作。因此,uint8uint32的全局变量产生的代码工程是一样的效果。

在这里插入图片描述

扩展测试2

问题

(1)上面我们发现,uint8和uint32的全局变量结果一模一样。那么我们尝试创建两个全局变量试试呢?
(2)结果发现,RW-data增加了4字节,ZI-data增加4字节。

在这里插入图片描述

解决思路

(1)依旧是看map文件,我们发现main.o的RW-data确实是从2字节变成了8字节,但是同时也少了2字节的字节对齐。因此RW-data是增加了4字节。

在这里插入图片描述

(2)看ZI-data,发现这里会增加4字节对齐,具体原因不清楚

在这里插入图片描述

总结

(1)关于uint8占用空间更多,还是uint32占用空间更多,这个取决于编译器的编译策略硬件特性性能优化。我们无法一概而论。正因如此,在目前内存不那么紧张的时代,不要过分的纠结于这个问题。什么时候用那个数据,就用那个,不要抱有心理负担。否则只会适得其反,拖慢研发速度。

参考

(1)CM3权威指南
(2)关于ARM中的tst、cmp、bne、beq指令
(3)用Keil生成bin、汇编、C与汇编混合文件,再也不想debug了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/593819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c#学习笔记:CheckedListBox控件的用法

一、常用属性 &#xff08;1&#xff09;、CheckOnClick属性 CheckOnClick属性是布尔类型的值&#xff0c;如果为True&#xff0c;那么单击条目就能将条目勾选&#xff1b;如果为false&#xff0c;则要双击条目才能将其勾选。 2&#xff09;ColumnWidth属性 ColumnWitdh属性…

调查过程之访谈

访谈可以根据不同的分类标准进行分类&#xff0c;以下是几种常见的分类方式&#xff1a; 1. 根据受访者的身份分类&#xff1a;政治家访谈、名人访谈、专家访谈等。 2. 根据访谈形式和方式分类&#xff1a;面对面访谈、电话访谈、邮件访谈、视频访谈等。 3. 根据访谈的主题分…

【python】pillow (PIL)库的用法介绍

Pillow&#xff08;也称为PIL&#xff09;是一个Python图像处理库&#xff0c;它提供了丰富的图像处理功能。下面是Pillow库的一些常用功能和用法介绍&#xff1a; 打开和保存图像&#xff1a; 使用Image.open()函数打开一个图像文件&#xff0c;并使用save()函数保存图像文件…

uniapp中组件库的Textarea 文本域的丰富使用方法

目录 #平台差异说明 #基本使用 #字数统计 #自动增高 #禁用状态 #下划线模式 #格式化处理 API #List Props #Methods #List Events 文本域此组件满足了可能出现的表单信息补充&#xff0c;编辑等实际逻辑的功能&#xff0c;内置了字数校验等 注意&#xff1a; 由于…

金和OA SAP_B1Config.aspx存在未授权访问漏洞

产品简介 金和网络是专业信息化服务商&#xff0c;为城市监管部门提供了互联网监管解决方案&#xff0c;为企事业单位提供组织协同OA系统升开发平台&#xff0c;电子政务一体化平台智慧电商平合等服务 漏洞概述 金和OA SAP_B1Config.aspx存在未授权访问漏洞&#xff0c;攻击…

nebula解压版 启动例子; ssh X11Forward

nebula-graph安装启动 下载页面 nebula启动参考 wget https://oss-cdn.nebula-graph.com.cn/package/3.6.0/nebula-graph-3.6.0.ubuntu2004.amd64.tar.gzcd /app/nebula-graph-3.6.0.ubuntu2004.amd64/tar -zxvf nebula-graph-3.6.0.ubuntu2004.amd64.tar.gz -C /app/ln -s /a…

Jenkins的Transfers路径怎么配置,解决Transfers配置不生效的问题

Transfers配置: 1.配置Source files: 要填写jar包的相对路径,从当前项目工作空间的根目录开始,看看我的工作空间你就懂了 !如图 我填的是 parent/build/libs/parent-1.0.0.jar,即不要 fdw1/ 的前缀 2.配置Remote directory: 远程目标文件夹,也就是你jar包要放到远程…

FreeRTOS的 vTaskDelay() 函数和 vTaskDelayUntil() 函数

关于两个函数 vTaskDelay() 函数&#xff1a;相对延时&#xff0c;即相对于当前时间进行延时 vTaskDelayUntil() 函数&#xff1a;绝对延时&#xff0c;即相对于上一次的唤醒时间进行延迟 这两个函数延时都是延时节拍数的&#xff01;而每个节拍多长时间可见 FreeRTOSConfig…

【LeetCode】每日一题 2023_12_31 一年中的第几天(日期)

文章目录 随便聊聊时间题目&#xff1a;一年中的第几天题目描述代码与解题思路 随便聊聊时间 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 12 月的打卡勋章&#xff0c;get&#xff01; 题目&#xff1a;一年中的第几天 题目链接&#xff1a;1154. 一年中…

英文字母替换加密(后移n位)

思路&#xff1a;首先写出后移&#xff08;前移&#xff09;1位的情况 &#xff0c; 然后逐渐累加至N位情况 #include <stdio.h> void test(char arr[] , int n ) { int i 0; int z 0; if( n < 0 ) { while( i ! n ) { …

php生成唯一ID的5种方法介绍

php生成唯一ID的5种方法介绍 工作中使用到唯一ID的场景非常多&#xff0c;如临时缓存文件、临时变量、临时安全码等。 uniqid()函数基于以微妙计的当前时间&#xff0c;生成一个唯一的ID。由于生成唯一ID与微妙时间关联&#xff0c;因此生成ID的唯一性非常可靠。 生成的唯一…

Nextjs打包类型检查报错ype error: Property ‘card_list‘ does not exist on type(已解决)

在Nextjs 中 在数组 map 的时候报错如下: 里面的数据类型是 data1 {cart_list:[]} 那么在 声明类型的时候 使用 data1:{card_list:any[]} export default function Card({authStates,data1,data2}:{authStates:boolean;data1:{card_list:any[]};data2:any[]}) {}) 这样就…

2024.1.3每日一题

LeetCode每日一题 2487.从链表中移除节点 2487. 从链表中移除节点 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个链表的头节点 head 。 移除每个右侧有一个更大数值的节点。 返回修改后链表的头节点 head 。 示例 1&#xff1a; 输入&#xff1a;head [5,…

设置代理IP地址对网络有什么影响?爬虫代理IP主要有哪些作用?

在互联网的广泛应用下&#xff0c;代理IP地址成为了一种常见的网络技术。代理IP地址可以改变用户的上网行为&#xff0c;进而影响网络访问的速度和安全性。本篇文章将探讨设置代理IP地址对网络的影响&#xff0c;以及爬虫代理IP的主要作用。 首先&#xff0c;让我们来了解一下代…

kafka容灾演练的方案

背景 kafka可以通过MirrorMaker工具把集群的数据从一个集群同步到另一个集群&#xff0c;通过在另一个数据中心创建灾备集群的方式可以做到容灾的效果,但是如果我们不通过如此重量级的工具也想达到容灾演练的目的&#xff0c;可以怎么做呢 kafka简单容灾实现 当原kafka集群发…

Allegro看不到PCB元件的丝印和装配层

#创作灵感# PCB板到处Gerber文件加工回来&#xff0c;板子上没有元件边框丝印&#xff0c;但是有元件编号。因为只是样板&#xff0c;影响不大&#xff0c;就没有当回事。直到发出去贴片&#xff0c;发送了钢网层和装配层&#xff0c;反馈说不知道元器件的极性。这就纳闷了&…

Android测试——(下篇)

Android测试&#xff08;五&#xff09;&#xff1a;Instrumented 单元测试 Instrumented 单元测试是在真机并且可以上运行的测试&#xff0c;它利用Android框架API和支持的API&#xff08;如Android测试支持库&#xff09;。如果你的测试需要访问工具信息&#xff08;例如目标…

STM32 学习(三)OLED 调试工具

目录 一、简介 二、使用方法 2.1 接线图 2.2 配置引脚 2.3 编写代码 三、Keil 工具调试 一、简介 在进行单片机开发时&#xff0c;有很多调试方法&#xff0c;如下图&#xff1a; 其中 OLED 就是一种比较好用的调试工具&#xff1a; OLED 硬件电路如下&#xff0c…

supervisor + uwsgi 部署python服务流程

supervisor uwsgi 部署python服务流程 最近由于某个python服务不稳定&#xff0c;有时候是造成服务器down机&#xff0c;有时候是服务本身突然就挂了。查了一下原因&#xff0c;发现是内存资源占用过高导致的&#xff0c; 为了让服务稳定运行&#xff0c;便打算引入superviso…

linux centos 部署 jenkins

一、试了用容器部署&#xff0c;不行。(建议别用容器部署) 二、直接部署在主机上 1、安装java环境 yum install java-11-openjdk-devel # 检查 java -version # 打印 [rootiZwz9a99mctbkabkh2imhdZ init.d] java -version openjdk version "11.0.21" 2023-10-17 L…