keil把c语言函数转成汇编

汇编可以让开发人员从根源上理解程序的运行逻辑,本文介绍如何在keil环境下如何把一个c文件中的某一个函数,转换为汇编函数,并编译运行。

右击某个c文件,选择Option for File。。。

  图1

然后把下图中的Generate Assembler SRC File(生成汇编源文件)打黑色勾。(默认是灰色勾)

图2

然后执行编译,这样就会在工程的输出文件夹(一般会被命名为OBJ)下,找到与.c文件同名的.s文件,这个C文件中的所有函数,都会被一一转换为汇编函数。

以我的ad.c为例,里面有个test()函数,这个函数中会调用另外一个函数uint16_t AD_getValue1(void),还会对一个全局变量var做写操作。

图3

转换出的汇编函数如下:

图4

由这段代码可以看到在汇编中是如何调用C函数的,以及汇编是如何读写c语言中的全局变量var的。

写var的代码是这两行:

图5

首先LDR指令从|L0.260|标签处载入var变量的内存地址,然后VSTR指令把s0的值写入该内存地址处。汇编中的标签和C语言中的goto语句标签,是类似的。

那么|L0.260|标签定义了什么?在s文件中搜索可见:

图6

有上图可见,这个标签对应的flash地址处,通过DCD命令占用了一个32bit的空间,这个空间中的值被初始化成了全局变量var的地址。DCD本身并不是一个可执行语句,只是一个占位而已。

上图还可以看到,对于C语言中定义的很多常量,也用DCD命令给保存下来了。

接下来我们就可以把c语言中的这个test()函数,用汇编给替换一下:

float var;
void test(void)
{
	volatile float k = 1.5f;
	
	var = AD_getValue1() * k;
}

//前缀__asm代表这是个汇编语言编写的函数,以便编译时供编译器识别
__asm void test(void)
{
	THUMB
    REQUIRE8
    PRESERVE8
    //本汇编函数所有要调用的c函数,必须全部用IMPORT指令导入,不然编译报错
    IMPORT AD_getValue1[CODE]
    
    //全局变量也必须IMPORT导入
    IMPORT var
    
//以下代码直接从生成的.s文件中对应的test函数拷贝而来,见前文图4,我加了注释
        PUSH     {r3,lr}//PC指针存储到如r3寄存器
        VMOV.F32 s0,#1.50000000//把常量1.5加载到浮点寄存器s0中
        VSTR     s0,[sp,#0]//把s0中的值,存储到(sp指针+0)指向的内存处
        BL       AD_getValue1//调用c函数,其返回值(uint16类型)会被存到r0寄存器
        VMOV     s0,r0//把R0寄存器中的数转存到浮点寄存器s0中
        VCVT.F32.U32 s0,s0//把s0中的值由uint类型转成float类型
        VLDR     s1,[sp,#0]//把(sp指针+0)内存处的值加载到s1中
        VMUL.F32 s0,s0,s1//等价于s0=s0*si
        LDR      r0,|L0.260|/从|L0.260|标签处载入全局变量var的地址
        VSTR     s0,[r0,#0]//把s0中的值存储到var中
        POP      {r3,pc}//函数返回
//以上代码需要调用|L0.260|标签处的数据,也手动复制进来:
    |L0.260|
        DCD      var
}

至此,这个汇编函数__asm void test(void)和C语言函数void test(void),功能完全一致了。把这个c函数void test(void)删掉后,只保留汇编函数,仍然可以编译通过。这样我们就实现了:在一个c源文件中,既有c函数,又有汇编函数共存。

如果编译时看到以下报错:

error: A1875E: Register Rn must be from R0 to R7 in this instruction

 报错对应的代码为LDR      r0,|L0.260|,这行代码本身并没有问题,问题出在|L0.260|这个标签没有4字节对齐。

同时伴随上述报错的,还有一个警告:

 warning: A1581W: Added 2 bytes of padding at address 0x2aa

这个你警报的意思是ROM没有4字节对齐,编译器自动添加了2字节的空白。这个问题来源于图6中第一行DCW,这个指令占用了2字节的位置,导致后面的DCD无法4字节对齐了。解决方法就是直接把DCW这行删掉。

相关推荐

  1. 用GCCC语言文件编译Intel语法汇编代码

    2024-04-23 10:02:07       29 阅读
  2. python教程——视频gif

    2024-04-23 10:02:07       46 阅读
  3. pythonpngjpg

    2024-04-23 10:02:07       27 阅读
  4. #phppdf文件图片#

    2024-04-23 10:02:07       32 阅读
  5. js如何json列表数组

    2024-04-23 10:02:07       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-23 10:02:07       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-23 10:02:07       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-23 10:02:07       82 阅读
  4. Python语言-面向对象

    2024-04-23 10:02:07       91 阅读

热门阅读

  1. 分布式与微服务的区别

    2024-04-23 10:02:07       41 阅读
  2. python-读写文本数据

    2024-04-23 10:02:07       34 阅读
  3. 从零手写 tomcat

    2024-04-23 10:02:07       55 阅读
  4. STM32 ST-LINK

    2024-04-23 10:02:07       78 阅读
  5. QML与C++交互

    2024-04-23 10:02:07       38 阅读
  6. 每日一题:Spring MVC 的执行流程是什么❓

    2024-04-23 10:02:07       41 阅读
  7. 【LeetCode热题100】【图论】课程表

    2024-04-23 10:02:07       149 阅读
  8. Linux bond0 配置方法

    2024-04-23 10:02:07       32 阅读
  9. 【C++提高】算法

    2024-04-23 10:02:07       26 阅读
  10. 7-17 KMP模式匹配算法

    2024-04-23 10:02:07       22 阅读