STM32启动代码分析及其汇编学习-ARM
2021/8/16 17:06:35
本文主要是介绍STM32启动代码分析及其汇编学习-ARM,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
STM32 启动代码
Author By YuCloud
边看启动文件边学汇编
汇编
see ARM: Assembler User Guide
see: https://blog.csdn.net/zlmm741/article/details/105189487
指令 | 作用 |
---|---|
EQU | 取符号名(类似C #define),同义词 * |
AREA | 指示编译器汇编一个新段(代码段或数据段) |
SPACE | 分配内存空间并填零。[标号] SPACE [表达式], 同义词 % |
PRESERVE8 | 按8字节对齐 |
EXPORT | 声明全局,可被外部文件使用,同义词 GLOBAL |
DCD | 以字为单位分配内存,要求4字节对齐且初始化该内存 |
PROC | 定义子程序,与ENDP成对使用,表示子程序结束 同义词 FUNCTION |
WEAK | 编译器特性。弱定义,优先使用外部文件定义的标号。 |
IMPORT | 声明标号来自外部文件,类似于C extern |
B | 跳转到一个标号 |
ALIGN | 编译器指令,对指令或数据存放地址进行对齐(一般跟一个立即数,缺省为4字节) |
END | EOF,文件结束 |
IF,ELSE,ENDIF | 条件分支 |
STM32 启动文件详解
注意,汇编里的注释符是;
,但这里为了视觉效果,用了斜杆
栈
Stack_Size EQU 0x00000400 // 定义一个符号,0x400为1KB // 汇编一个新段,名为STACK 不初始化(即不填零) 可读可写 2^3=8字节对齐 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size // 栈本体,这里指令是分配栈大小 __initial_sp // 标名, 表示该地址(这里是末尾,即栈顶地址)
也就是 通知编译器链接 -> 分配一片栈空间 -> 记录栈顶地址
栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM的大小。如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小。如果某一天,你写的程序出现了莫名奇怪的错误,并进入了硬 fault 的时候,这时你就要考虑下是不是栈不够大,溢出了。
指令详解
即 SPACE
指令用于留出一段填零的内存空间
初始化是指
Indicates that the data section is uninitialized, or initialized to zero.
指令文档链接:EQU 、SPACE、AREA
EQU 是伪指令,不生成二进制代码
另外,Label 就是一个标号,加不加只是为了规范,不影响二进制结果。其实上面代码等价于
AREA STACK, NOINIT, READWRITE, ALIGN=3 SPACE 0x00000400 // 栈本体,这里指令是分配栈大小 <编译器拿到__initial_sp所在行编译时的地址> //标名, 表示该地址(这里是末尾,即栈顶地址)
对了,官方文档说 Use the ALIGN
directive to align any code following a SPACE
or FILL
directive.
用 ALIGN
指令对齐 SPACE
或 FILL
指令之后的任何代码,而AREA
里有 ALIGN 参数
个人猜测: AREA
和 SPACE
配合,才能生成一个段
反汇编一个程序,段是这样的(黑色箭头是 段名,方框是 整个段的内容)
堆
Heap_Size EQU 0x00000200 //Heap_Size=512B // 新段,名为HEAP,可读可写,不初始化,8B对齐 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base // 堆的起始地址 Heap_Mem SPACE Heap_Size // 堆本体 __heap_limit // 堆的结束地址
堆用于 malloc/calloc 等用于动态分配内存的函数
通知编译器链接->记录堆头地址->分配一片堆空间->记录堆尾地址
静态变量和局部变量都是在SRAM中分配
过渡
PRESERVE8 // 指定当前文件的栈按 8B 对齐 THUMB // 表示后面的指令兼容 Thumb 指令集(ARM以前的16位指令集)
向量表
AREA RESET, DATA, READONLY // 汇编新段,名为RESET的数据段,只读 EXPORT __Vectors //向量表起始 EXPORT __Vectors_End //向量表末尾 EXPORT __Vectors_Size //向量表大小,可由__Vectors_End-__Vectors计算 __Vectors DCD __initial_sp DCD Reset_Handler DCD NMI_Handler // ... 省略一些代 DCD DMA2D_IRQHandler __Vectors_End __Vectors_Size EQU __Vectors_End - __Vectors
EXPORT
/GLOBAL
声明全局,可被外部文件使用
向量表作用:
当内核响应了一个发生的异常后,对应的异常服务例程(ESR)就会执行。为了决定 ESR的入口地址, 内核使用了―向量表查表机制‖。这里使用一张向量表。向量表其实是一个WORD(32 位整数)数组,每个下标对应一种异常,该下标元素的值则是该 ESR 的入口地址。向量表在地址空间中的位置是可以设置的,通过 NVIC 中的一个重定位寄存器来指出向量表的地址。
在复位后,该寄存器的值为 0。因此,在地址 0 (即 FLASH 地址 0) 处必须包含一张向量表,用于初始时的异常分配。要注意的是这里有个另类: 0 号类型并不是什么入口地址,而是给出了复位后 MSP 的初值。
向量表从 FLASH 的 0 地址开始放置,以 4 个字节为一个单位,地址 0 存放的是栈顶地址, 0X04 存放的是复位程序的地址,以此类推。从代码上看,向量表中存放的都是中断服务函数的函数名,可我们知道 C 语言中的函数名就是一个地址。
DCD:分配一个或者多个以字为单位的内存,以四字节对齐,并要求初始化这些内存。在向量表中, DCD 分配了一堆内存,并且以 ESR 的入口地址初始化它们。
用人话说:
内核在异常时会访问这个表地址,并根据异常类型查表,按表跳转到异常处理函数执行。
各种中断处理程序 xxx_Handler
先指示编译器汇编一个新的代码段,名为 |.text|
,只读
AREA |.text|, CODE, READONLY
复位程序,也就是默认上电复位后执行的程序
; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP
弱符号导出本程序Reset_Handler
,导入 SystemInit
和 __main
两个符号,并LDR数据到R0寄存器,跳转执行(BLX/BX)
注:R0~R3 寄存器通常用于函数入参出参或子程序调用,详细请自行搜索 ARM 寄存器作用
PORC 标记了程序的开始,ENDP 标记了程序的末尾。与R13(SP)寄存器相关。
R13(即SP栈指针寄存器): 当程序的运行进入异常模式时,可以将需要保护的寄存器放入R13所指向的堆栈,而当程序从异常模式返回时,则从对应的堆栈中恢复,采用这种方式可以保证异常发生后程序的正常执行。
B 跳转的都是相对地址(相对于 PC寄存器),偏移值是由编译器计算的
B {条件} 目标地址
条件可选,立即跳转执行。(不返回程序),B .
是死循环while(1);的用法
BL 目标地址
无条件跳转到目标地址处执行,并保存PC值到 R14(LR) 寄存器
BLX 目标地址
无条件跳转到目标地址处执行,并切换工作状态为 Thumb
,同时保存PC值到 R14(LR) 寄存器
子程序返回:通过将 R14 寄存器值复制到 PC 来实现。
前文说到, Label 代表的就是其所在地址
其他异常处理程序
定义异常处理子程序
; Dummy Exception Handlers (infinite loops which can be modified) NMI_Handler PROC EXPORT NMI_Handler [WEAK] B . ENDP HardFault_Handler\ PROC EXPORT HardFault_Handler [WEAK] B . ENDP //...省略一些 SysTick_Handler PROC EXPORT SysTick_Handler [WEAK] B . ENDP
这里虽然有 B .
(跳转到当前地址执行,这里会不断跳转执行 B .
,也就是死循环),
但是有外部 xxx_Handler
时,应该是会返回异常之前的处理函数的,所以在有处理函数的情况下,不会死循环,而是执行完异常处理函数后再跳回异常之前的函数。
弱导出 异常处理函数 的符号表
Default_Handler PROC EXPORT WWDG_IRQHandler [WEAK] EXPORT PVD_IRQHandler [WEAK] // 省略一些 EXPORT FPU_IRQHandler [WEAK] EXPORT SPI4_IRQHandler [WEAK]
这里 [WEAK]
表示优先使用外部符号,如果没有才使用内部的(即刚才上面定义的子程序)
中断处理函数的符号表
这里是标号,也就是表明程序地址在这里
这样就排列出了中断处理函数表,顺序必须和前面的符号表对应,
应该就是为了让编译器对着符号名链接子程序?
WWDG_IRQHandler PVD_IRQHandler TAMP_STAMP_IRQHandler RTC_WKUP_IRQHandler FLASH_IRQHandler //...省略一些 FPU_IRQHandler SPI4_IRQHandler
// 死循环(点表示当前地址,B表示立即跳转)应该是防止程序跑飞,,所以一切执行完成后就在这里死循环 B . // 程序的结束符 ENDP // 对齐(默认4B对齐 ALIGN
堆栈初始化
-
if
- 如果使用了微库(MicroLib),就直接导出堆栈地址符号
-
else
-
导入外部程序
__use_two_region_memory
并马上执行调用 -
并导出子程序符号
__user_initial_stackheap
给外部程序调用
-
;******************************************************************************* ; User Stack and Heap initialization ;******************************************************************************* IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE IMPORT __use_two_region_memory // EXPORT __user_initial_stackheap //导出了
__user_initial_stackheap
的程序定义: 保存堆栈地址和大小到寄存器
// 下面是 __user_initial_stackheap 的程序定义,用于导出给外部程序调用的 __user_initial_stackheap LDR R0, = Heap_Mem LDR R1, =(Stack_Mem + Stack_Size) LDR R2, = (Heap_Mem + Heap_Size) LDR R3, = Stack_Mem BX LR ALIGN ENDIF END ;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****
启动文件代码(startup_stm32f401xx.s)
点击展开完整代码 [startup_stm32f401xx.s]
;******************** (C) COPYRIGHT 2014 STMicroelectronics ******************** ;* File Name : startup_stm32f401xx.s ;* Author : MCD Application Team ;* @version : V1.4.0 ;* @date : 04-August-2014 ;* Description : STM32F401xx devices vector table for MDK-ARM toolchain. ;* This module performs: ;* - Set the initial SP ;* - Set the initial PC == Reset_Handler ;* - Set the vector table entries with the exceptions ISR address ;* - Configure the system clock ;* - Branches to __main in the C library (which eventually ;* calls main()). ;* After Reset the CortexM4 processor is in Thread mode, ;* priority is Privileged, and the Stack is set to Main. ;* <<< Use Configuration Wizard in Context Menu >>> ;******************************************************************************* ; ; Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); ; You may not use this file except in compliance with the License. ; You may obtain a copy of the License at: ; ; http://www.st.com/software_license_agreement_liberty_v2 ; ; Unless required by applicable law or agreed to in writing, software ; distributed under the License is distributed on an "AS IS" BASIS, ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ; See the License for the specific language governing permissions and ; limitations under the License. ; ;******************************************************************************* ; Amount of memory (in bytes) allocated for Stack ; Tailor this value to your application needs ; <h> Stack Configuration ; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp ; <h> Heap Configuration ; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8> ; </h> Heap_Size EQU 0x00000200 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit PRESERVE8 THUMB ; Vector Table Mapped to Address 0 at Reset AREA RESET, DATA, READONLY EXPORT __Vectors EXPORT __Vectors_End EXPORT __Vectors_Size __Vectors DCD __initial_sp ; Top of Stack DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler ; External Interrupts DCD WWDG_IRQHandler ; Window WatchDog DCD PVD_IRQHandler ; PVD through EXTI Line detection DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line DCD FLASH_IRQHandler ; FLASH DCD RCC_IRQHandler ; RCC DCD EXTI0_IRQHandler ; EXTI Line0 DCD EXTI1_IRQHandler ; EXTI Line1 DCD EXTI2_IRQHandler ; EXTI Line2 DCD EXTI3_IRQHandler ; EXTI Line3 DCD EXTI4_IRQHandler ; EXTI Line4 DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0 DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1 DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2 DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3 DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4 DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5 DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6 DCD ADC_IRQHandler ; ADC1 DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD EXTI9_5_IRQHandler ; External Line[9:5]s DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9 DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10 DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11 DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare DCD TIM2_IRQHandler ; TIM2 DCD TIM3_IRQHandler ; TIM3 DCD TIM4_IRQHandler ; TIM4 DCD I2C1_EV_IRQHandler ; I2C1 Event DCD I2C1_ER_IRQHandler ; I2C1 Error DCD I2C2_EV_IRQHandler ; I2C2 Event DCD I2C2_ER_IRQHandler ; I2C2 Error DCD SPI1_IRQHandler ; SPI1 DCD SPI2_IRQHandler ; SPI2 DCD USART1_IRQHandler ; USART1 DCD USART2_IRQHandler ; USART2 DCD 0 ; Reserved DCD EXTI15_10_IRQHandler ; External Line[15:10]s DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7 DCD 0 ; Reserved DCD SDIO_IRQHandler ; SDIO DCD TIM5_IRQHandler ; TIM5 DCD SPI3_IRQHandler ; SPI3 DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0 DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1 DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2 DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3 DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4 DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD OTG_FS_IRQHandler ; USB OTG FS DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5 DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6 DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7 DCD USART6_IRQHandler ; USART6 DCD I2C3_EV_IRQHandler ; I2C3 event DCD I2C3_ER_IRQHandler ; I2C3 error DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD FPU_IRQHandler ; FPU DCD 0 ; Reserved DCD 0 ; Reserved DCD SPI4_IRQHandler ; SPI4 __Vectors_End __Vectors_Size EQU __Vectors_End - __Vectors AREA |.text|, CODE, READONLY ; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP ; Dummy Exception Handlers (infinite loops which can be modified) NMI_Handler PROC EXPORT NMI_Handler [WEAK] B . ENDP HardFault_Handler\ PROC EXPORT HardFault_Handler [WEAK] B . ENDP MemManage_Handler\ PROC EXPORT MemManage_Handler [WEAK] B . ENDP BusFault_Handler\ PROC EXPORT BusFault_Handler [WEAK] B . ENDP UsageFault_Handler\ PROC EXPORT UsageFault_Handler [WEAK] B . ENDP SVC_Handler PROC EXPORT SVC_Handler [WEAK] B . ENDP DebugMon_Handler\ PROC EXPORT DebugMon_Handler [WEAK] B . ENDP PendSV_Handler PROC EXPORT PendSV_Handler [WEAK] B . ENDP SysTick_Handler PROC EXPORT SysTick_Handler [WEAK] B . ENDP Default_Handler PROC EXPORT WWDG_IRQHandler [WEAK] EXPORT PVD_IRQHandler [WEAK] EXPORT TAMP_STAMP_IRQHandler [WEAK] EXPORT RTC_WKUP_IRQHandler [WEAK] EXPORT FLASH_IRQHandler [WEAK] EXPORT RCC_IRQHandler [WEAK] EXPORT EXTI0_IRQHandler [WEAK] EXPORT EXTI1_IRQHandler [WEAK] EXPORT EXTI2_IRQHandler [WEAK] EXPORT EXTI3_IRQHandler [WEAK] EXPORT EXTI4_IRQHandler [WEAK] EXPORT DMA1_Stream0_IRQHandler [WEAK] EXPORT DMA1_Stream1_IRQHandler [WEAK] EXPORT DMA1_Stream2_IRQHandler [WEAK] EXPORT DMA1_Stream3_IRQHandler [WEAK] EXPORT DMA1_Stream4_IRQHandler [WEAK] EXPORT DMA1_Stream5_IRQHandler [WEAK] EXPORT DMA1_Stream6_IRQHandler [WEAK] EXPORT ADC_IRQHandler [WEAK] EXPORT EXTI9_5_IRQHandler [WEAK] EXPORT TIM1_BRK_TIM9_IRQHandler [WEAK] EXPORT TIM1_UP_TIM10_IRQHandler [WEAK] EXPORT TIM1_TRG_COM_TIM11_IRQHandler [WEAK] EXPORT TIM1_CC_IRQHandler [WEAK] EXPORT TIM2_IRQHandler [WEAK] EXPORT TIM3_IRQHandler [WEAK] EXPORT TIM4_IRQHandler [WEAK] EXPORT I2C1_EV_IRQHandler [WEAK] EXPORT I2C1_ER_IRQHandler [WEAK] EXPORT I2C2_EV_IRQHandler [WEAK] EXPORT I2C2_ER_IRQHandler [WEAK] EXPORT SPI1_IRQHandler [WEAK] EXPORT SPI2_IRQHandler [WEAK] EXPORT USART1_IRQHandler [WEAK] EXPORT USART2_IRQHandler [WEAK] EXPORT EXTI15_10_IRQHandler [WEAK] EXPORT RTC_Alarm_IRQHandler [WEAK] EXPORT OTG_FS_WKUP_IRQHandler [WEAK] EXPORT DMA1_Stream7_IRQHandler [WEAK] EXPORT SDIO_IRQHandler [WEAK] EXPORT TIM5_IRQHandler [WEAK] EXPORT SPI3_IRQHandler [WEAK] EXPORT DMA2_Stream0_IRQHandler [WEAK] EXPORT DMA2_Stream1_IRQHandler [WEAK] EXPORT DMA2_Stream2_IRQHandler [WEAK] EXPORT DMA2_Stream3_IRQHandler [WEAK] EXPORT DMA2_Stream4_IRQHandler [WEAK] EXPORT OTG_FS_IRQHandler [WEAK] EXPORT DMA2_Stream5_IRQHandler [WEAK] EXPORT DMA2_Stream6_IRQHandler [WEAK] EXPORT DMA2_Stream7_IRQHandler [WEAK] EXPORT USART6_IRQHandler [WEAK] EXPORT I2C3_EV_IRQHandler [WEAK] EXPORT I2C3_ER_IRQHandler [WEAK] EXPORT FPU_IRQHandler [WEAK] EXPORT SPI4_IRQHandler [WEAK] WWDG_IRQHandler PVD_IRQHandler TAMP_STAMP_IRQHandler RTC_WKUP_IRQHandler FLASH_IRQHandler RCC_IRQHandler EXTI0_IRQHandler EXTI1_IRQHandler EXTI2_IRQHandler EXTI3_IRQHandler EXTI4_IRQHandler DMA1_Stream0_IRQHandler DMA1_Stream1_IRQHandler DMA1_Stream2_IRQHandler DMA1_Stream3_IRQHandler DMA1_Stream4_IRQHandler DMA1_Stream5_IRQHandler DMA1_Stream6_IRQHandler ADC_IRQHandler EXTI9_5_IRQHandler TIM1_BRK_TIM9_IRQHandler TIM1_UP_TIM10_IRQHandler TIM1_TRG_COM_TIM11_IRQHandler TIM1_CC_IRQHandler TIM2_IRQHandler TIM3_IRQHandler TIM4_IRQHandler I2C1_EV_IRQHandler I2C1_ER_IRQHandler I2C2_EV_IRQHandler I2C2_ER_IRQHandler SPI1_IRQHandler SPI2_IRQHandler USART1_IRQHandler USART2_IRQHandler EXTI15_10_IRQHandler RTC_Alarm_IRQHandler OTG_FS_WKUP_IRQHandler DMA1_Stream7_IRQHandler SDIO_IRQHandler TIM5_IRQHandler SPI3_IRQHandler DMA2_Stream0_IRQHandler DMA2_Stream1_IRQHandler DMA2_Stream2_IRQHandler DMA2_Stream3_IRQHandler DMA2_Stream4_IRQHandler ETH_IRQHandler OTG_FS_IRQHandler DMA2_Stream5_IRQHandler DMA2_Stream6_IRQHandler DMA2_Stream7_IRQHandler USART6_IRQHandler I2C3_EV_IRQHandler I2C3_ER_IRQHandler FPU_IRQHandler SPI4_IRQHandler B . ENDP ALIGN ;******************************************************************************* ; User Stack and Heap initialization ;******************************************************************************* IF :DEF:__MICROLIB EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE IMPORT __use_two_region_memory EXPORT __user_initial_stackheap __user_initial_stackheap LDR R0, = Heap_Mem LDR R1, =(Stack_Mem + Stack_Size) LDR R2, = (Heap_Mem + Heap_Size) LDR R3, = Stack_Mem BX LR ALIGN ENDIF END ;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****
这篇关于STM32启动代码分析及其汇编学习-ARM的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-07-04TiDB 资源管控的对撞测试以及最佳实践架构
- 2024-07-03万字长文聊聊Web3的组成架构
- 2024-07-02springboot项目无法注册到nacos-icode9专业技术文章分享
- 2024-06-26结对编程到底难不难?答案在这里
- 2024-06-19《2023版Java工程师》课程升级公告
- 2024-06-15matplotlib作图不显示3D图,怎么办?
- 2024-06-1503-Loki 日志监控
- 2024-06-1504-让LLM理解知识 -Prompt
- 2024-06-05做软件测试需要懂代码吗?
- 2024-06-0514-ShardingSphere的分布式主键实现