《嵌入式 - 嵌入式大杂烩》Keil反编译入门

Posted Bruceoxl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《嵌入式 - 嵌入式大杂烩》Keil反编译入门相关的知识,希望对你有一定的参考价值。

我们在写单片机裸机程序时,在主函数之前,会有一段启动代码,而启动代码是用汇编写的,有些朋友可能看到汇编头都大了,当时要想深入研究底层架构,这快硬骨头就必须去啃。

汇编:汇编文件转换为目标文件(里面是机器码)。

反汇编:可执行文件(目标文件,里面是机器码),转换为汇编文件。

关于汇编的基础知识,请看笔者以前的文章。

今天笔者以STM32F1的点灯程序为例,带领大家进行反汇编,并阅读反汇编后的代码。

1新建LED裸机程序

关于STM32裸机程序的创建,请看笔者博文:

Keil新建工程

但是今天这个程序非常简单,不应那么复杂。

1.新建文件夹
新建文件夹“STM32F1”,当然名字也可以另取,在 STM32F1文件夹下,我们新建五个文件夹,分别为CMSIS、Listing、Output、Project、User。
在这里插入图片描述

其中CMSIS文件夹放启动文件:
在这里插入图片描述

笔者的开发板芯片是STM32F103ZE,这个文件是根据STM32的固件库startup_stm32f10x_md.s文件修改而来。

2.新建工程

打开Keil,在工具栏 Project->New μVision Project…新建我们的工程文件。

在这里插入图片描述

输入工程名,保存即可。
在这里插入图片描述

窗口是让我们选择公司跟芯片的型号,我们用的芯片是 ST 公司的STM32F103ZE,有64K SRAM,512K Flash,属于高集成度的芯片。按如下选择即可。
在这里插入图片描述

然后点击项目管理。

在这里插入图片描述

最后修改后的内容如下:

在这里插入图片描述

并添加相应的文件。
在这里插入图片描述

其中main.c的内容如下所示:

/**
  * @brief  延时函数
  * @param  d
  * @retval None
  */
void delay(int d)
{
	while(d--);
}

/**
  * @brief  mian
  * @param  None
  * @retval int
  */
int main(void)
{
	unsigned int *pReg;
	
	/* 使能GPIOB */
	pReg = (unsigned int *)(0x40021000 + 0x18);
	*pReg |= (1<<3);
	
	/* 设置GPIOB0为输出引脚 */
	pReg = (unsigned int *)(0x40010C00 + 0x00);
	*pReg |= (1<<0);

	pReg = (unsigned int *)(0x40010C00 + 0x0C);
	
	while (1)
	{
		/* 设置GPIOB0输出1 */
		*pReg |= (1<<0);
		
		delay(1000000);

		/* 设置GPIOB0输出0 */
		*pReg &= ~(1<<0);
		
		delay(1000000);		
	}
}

startup.s文件的内容如下:

;************************************ STM32F1 ************************************
;* File Name          : startup.s
;* Author             : BruceOu
;* Version            : V1.0
;* Date               : 2021-06-27
;* Description        : STM32F10x Medium Density 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 clock system
;*                      - Branches to __main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the CortexM3 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.
;*******************************************************************************
                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+0x10000)
				BL main

                ENDP 
                
                END

接下来还有配置工程。
在这里插入图片描述

选择Output文件夹。

在这里插入图片描述

选择Listing文件夹。

在这里插入图片描述

基本配置就这些,接下来编译工程。

在这里插入图片描述

只要没有错误就可以了,最后就是下载程序,笔者使用的是J-Link,最后的现象如下:

在这里插入图片描述

LED会不停闪烁。

2 Keil反汇编

接下来才是今天正题,反汇编。

在KEIL的User选项中,如下图添加这两项:

fromelf  --bin  --output=STM32F1.bin  ../Output/STM32F1.axf
fromelf  --text  -a -c  --output=STM32F1.dis  ../Output/STM32F1.axf

然后重新编译,即可得到二进制文件led.bin(以后会分析)、反汇编文件STM32F1.dis。
如下图所示:

在这里插入图片描述

正常编译过程是分为四个阶段进行的,即预处理(也称预编译,Preprocessing)、编译(Compilation)、汇编 (Assembly)和链接(Linking)

但是反编译是讲为二进制文件反编译成汇编文件,因此反汇编的流程如下:

在这里插入图片描述

3反汇编代码解析

接下来就是查看反编译代码,打开反编译文件Project/STM32F1.dis。这里只截取一段查看,因为格式都是一样的,知识每条内容不同罢了。

在这里插入图片描述

第一列是链接地址,第二列是机器码,第三列是汇编指令。

根本汇编指令,我们找到ARM®v7-M Architecture Reference Manual_DDI 0403E.d (ID070218)中的LDR指令。

在这里插入图片描述

我们将F8DFD004变成二进制。

在这里插入图片描述

这个使用的32位的Thumb2指令集。

在这里插入图片描述

其中b0~b11是立即数,这里是4,对应的汇编代码的也是4,这里要注意的是,ARM指令采用流水线机制,当前执行地址A的指令,同时已经在对下一条指令进行译码同时已经在读取下下一条指令:PC = A +4 (Thumb/Thumb2指令集)。

在这里插入图片描述

B12~b15是寄存器,这段大小是0XC,对应的寄存器就是sp;

在这里插入图片描述

后面16bit除了23位意外,全是固定的,其中‘U’表示无条件执行,这里置为1。

其他的汇编指令对应的机器码也是类似的,值得注意的是,不同的架构对应的机器码也是不同的,这也就回答了为了不同的处理器架构会对应不同的指令集。

有兴趣的可以对比Cortex-M系列和Cortex-A系列的的指令集。请参考以下手册:

ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition.pdf
ARM®v7-M Architecture Reference Manual.pdf




代码获取方法

1.长按下面二维码,关注公众号[嵌入式实验楼]
2.在公众号回复关键词[ARM]获取资料
在这里插入图片描述




欢迎访问我的网站

BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书

以上是关于《嵌入式 - 嵌入式大杂烩》Keil反编译入门的主要内容,如果未能解决你的问题,请参考以下文章

《嵌入式 - 嵌入式大杂烩》Keil反编译入门

《嵌入式 - 嵌入式大杂烩》Keil反编译入门

《嵌入式 - 嵌入式大杂烩》ARM汇编入门

《嵌入式 - 嵌入式大杂烩》ARM汇编入门

嵌入式项目生成器,了解一下!

《嵌入式 - 嵌入式大杂烩》详解J-Link RTT打印