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

第一个程序深度解析(STM32F407)

一.编程知识-进制

10进制里,每一位的权重,从右往左数:个十百千万,也就是:10^0, 10^1, 10^2,10^3……

16进制里,每一位的权重,从右往左数,分别是:16^0, 16^1, 16^2, 16^3, 16^4, ……

8进制里,每一位的权重,从右往左数,分别是:8^0, 8^1, 8^2, 8^3, 8^4, ……

进制输出(printf)输入(scanf)
十进制%d%i%d
八进制%o(输出无前缀)%o(输入时可带可不带0)
十六进制%x(小写字母)或%X(大写)%x(输入时可带可不带0x)
二进制标准C没有原生占位符,需自定义函数或使用itoa()

二.编程知识-字节序

1.大小字节序(大小端)

假设int a = 0x12345678;
16进制数中每位数值占据4 bit;在内存中,是以8个bit作为1byte。
因此0x12345678中每两位作为1byte, 其中0x78是低byte,0x12是高byte。
在内存中的存储方式有两种:

判断大小字节序的方法:指针强转类型

2.位操作

1.逻辑左移

int a = 0x123; int b = a<<2; // b=0x48C

2.逻辑右移

int a = 0x123; int b = a>>2; // b=0x48

3.取反

unsigned int a = 0x123; unsigned int b = ~a; // b的每一位,都是a对应位的取反

4.位与

unsigned int a = 0x123; unsigned int b = 0x456; unsigned int c = a & b; // c等于a位与b,即:a,b的每一位进行与操作 1 & 1 = 1 1 & 0 = 0 0 & 1 = 0 0 & 0 = 0

5.位或

unsigned int a = 0x123; unsigned int b = 0x456; unsigned int c = a | b; // c等于a位或b,即:a,b的每一位进行或操作 1 | 1 = 1 1 | 0 = 1 0 | 1 = 1 0 | 0 = 0

6.置位(重要)

置位公式: x |= (1<<n)

unsigned int a = 0x123; unsigned int b = a | (1<<7) | (1<<8); // 设置a的bit7, bit8, 赋给b

7.清位(重要)

清位公式: x &= ~(1<<n)

unsigned int a = 0x123; unsigned int b = a & ~((1<<7) | (1<<8)); // 清除a的bit7, bit8, 赋给b

8.把某几位设置位某值

比如要把bit7设置为1,把bit8清除为0,这可以分两步操作:先设置bit7,再清除bit8。 还有一种情况:bit[8:7]= val, 不知道val的取值是多少,怎么办? 先清除bit8、bit7,再或上val,代码如下:

unsigned int a = 0x123; unsigned int b = a & ~(3<<7); /* 清除bit7, bit8 */ b = b | (val << 7); /* 设置bit7, bit8为val */

三、汇编知识-汇编、反汇编、机器码

1.程序处理4个步骤

步骤输入输出核心动作常见报错类型
1. 预处理.c.i宏替换、头文件展开、删注释无(不检查语法)
2. 编译.i.s语法分析、生成汇编代码语法错误(Syntax Error)
3. 汇编.s.o/.obj生成二进制机器码(目标文件)极少数低级错误
4. 链接.o+ 库.exe/a.out合并目标文件、解析外部地址未定义引用(Undefined reference)

2.反汇编

文件格式推荐写法 (命令)说明

.bin

文件

fromelf.exe --bin -o "$L@L.bin" "#L"$L@L.bin意思是,在输出文件.axf的目录下,生成一个同名的.bin文件。
fromelf.exe --bin -o .\Objects\你的工程名.bin .\Objects\你的工程名.axf这种是直接写明路径和文件名。需要你把Objects你的工程名换成自己工程对应的实际目录和名字。
.dis文件fromelf.exe --text -a -c -o "$L@L.dis" "#L"--text -a -c是输出反汇编信息的标准参数组合。
fromelf.exe --text -a -c -o .\Objects\你的工程名.dis .\Objects\你的工程名.axf同样,可以替换为你的实际路径和文件名。

生成 .bin 文件(二进制固件)
在 Run #1 的输入框中添加以下命令:
fromelf --bin -o "$L@L.bin" "$L@L.axf"

生成 .dis 文件(反汇编文件)
在 Run #2 的输入框中添加以下命令:
fromelf --text -a -c --output="$L@L.dis" "$L@L.axf"

3.汇编深入分析

1.汇编怎么调用C函数?

直接调用

2.寄存器的作用

3.栈的作用

假设A函数把变量val放在了R4寄存器里。如果这时候调用B函数,而B函数也要用R4,就会把A函数的值覆盖掉。为了解决这个问题,B函数在开头会先把R4原来的值临时存到栈里(压栈),等B函数执行完了,在返回前再从栈里把值取回来放回R4(出栈)。这样A函数回来后,R4里的val还是原来的值,一切正常。

4.解析汇编:

四.汇编点灯

PRESERVE8 THUMB ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY EXPORT __Vectors __Vectors DCD 0 DCD Reset_Handler ; Reset Handler AREA |.text|, CODE, READONLY ; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] ; IMPORT main ; LDR SP, =0x20000000 + 0x20000 ; BL main ; /* 使能GPIOF */ LDR R0, =(0x40023800 + 0x30) LDR R1, [R0] ORR R1, R1, #(1<<5) STR R1, [R0] ; /* 设置GPIOF9为输出引脚 */ LDR R0, =(0x40021400 + 0x00) LDR R1, [R0] ORR R1, R1, #(1<<18) STR R1, [R0] ; /* 设置GPIOF9为推挽输出 */ LDR R0, =(0x40021400 + 0x04) LDR R1, [R0] BIC R1, R1, #(1<<9) STR R1, [R0] ; /* 设置GPIOF9为低速输出 */ LDR R0, =(0x40021400 + 0x08) LDR R1, [R0] BIC R1, R1, #(3<<18) STR R1, [R0] LDR R2, =(0x40021400 + 0x18) Loop ; /* 设置GPIOF9输出1 */ LDR R1, [R2] ORR R1, R7, #(1<<9) STR R1, [R2] LDR R0, =100000 BL delay ; /* 设置GPIOF9输出0 */ LDR R1, [R2] ORR R1, R8, #(1<<25) STR R1, [R2] LDR R0, =100000 BL delay B Loop ENDP delay SUBS R0, R0, #1 BNE delay MOV PC, LR END
http://www.jsqmd.com/news/1178590/

相关文章:

  • 为什么92%的团队在DeepSeek-R1和DeepSeek-RLHF-v2之间选错?6项生产级指标横向对比,立即止损!
  • 魔兽争霸3现代化升级:WarcraftHelper终极优化指南
  • C++14二进制字面量:从硬件编程到协议解析的位操作利器
  • 如何通过路灯智能控制器提升城市照明的智能化管理?
  • 仅限首批200名开发者获取:ChatGPT生成API文档的私有化部署方案(支持内网离线运行+敏感字段脱敏+审计日志全留存)
  • Pydantic AI技能插件化:渐进式披露与模块化设计
  • Medooze流媒体服务器:RTMP与WebRTC视频编解码转换与性能优化
  • 抖音内容管理革命:Douyin Downloader 智能批量下载解决方案
  • 2026河南CPPM培训机构选择指南:排名靠谱吗?口碑怎么核验 - 企智芯
  • 双色球智能分析预测系统:从数据抓取到预测算法的完整实现
  • C++学习路径:从核心语法到现代特性,掌握系统编程基石
  • 基于C++与Qt的图形化Ping网络诊断工具开发全解析
  • colibrì : 1300 行 C 代码,25GB 笔记本,跑起 7440 亿参数大模型, 用纯 C 和 Claude 做了件所有人说不可能的事 | SSP Github Daily
  • NX插件开发中的C++异常安全编程:从原理到实战
  • nacos配置管理改造
  • VS Code Arduino 扩展弃用后:3种替代方案迁移指南与性能实测
  • C++17类模板参数推导:从原理到嵌入式实战避坑指南
  • 学人工智能只能当算法工程师?错!这5个岗位薪资更高更缺人
  • C++多线程开发实战:从基础同步到内存模型的避坑指南
  • 软件项目开发实践 7 步排错指南:从需求分析到测试的常见 5 大误区
  • 攻克So层SSL Pinning:Frida与IDA逆向实战指南
  • VTK分隔文本读取器开发:从CSV到三维可视化的C++实现
  • C++实现自动驾驶变道决策模拟器:状态机与代价函数设计详解
  • 如何快速掌握英雄联盟Akari助手:面向游戏玩家的免费效率工具完整指南
  • AI Agent开发实战:从基础到企业级项目的完整学习路径
  • 终极Deceive教程:3分钟掌握英雄联盟隐身技巧,享受真正的游戏自由 [特殊字符]
  • Pandas数据处理实战地图:从摄入到交付的6阶段操作指南
  • 我们如何用离散数学构建一个安全、完全可控的 Agent 内核-大模型可以生成内容、计划和工具调用建议,但不应拥有最终执行权。OneCode 在模型输出与真实行动之间建立确定性内核
  • optimizerDuck:开源免费的Windows系统优化工具实战指南
  • 30天从零搭建AI自动化业务:Claude AI与AI Agent技术实战