嵌入式:ARM内嵌汇编及C和ARM汇编相互调用

这篇具有很好参考价值的文章主要介绍了嵌入式:ARM内嵌汇编及C和ARM汇编相互调用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

内嵌汇编

在C程序中嵌入汇编程序可以实现一些高级语言没有的功能,并可以提高执行效率。armcc和armcpp内嵌汇编器支持完整的ARM指令集;tcc和tcpp用于Thumb指集。但是内嵌汇编器并不支持诸如直接修改PC实现跳转的底层功能。

内嵌的汇编指令包括大部分的ARM指令和Thumb指令,但是不能直接引用C的变量定义,数据交换必须通过ATPCS进行。嵌入式汇编在形式上表现为独立定义的函数体。

内嵌汇编指令的语法格式

__asm(“指令[;指令]”);

ARM C汇编器使用关键字“__asm"。如果有多条汇编指令需要嵌入,可以用“{}”将它们归为一条语句。如:

__asm
{
指令[;指令]
…
[指令]
}

各指令用“;”分隔。如果一条指令占据多行,除最后一行外都要使用连字符“\”。在汇编指令段中可以使用C语言的注释语句。需要特别注意的是__asm是两个下划线。

内嵌汇编注意事项

必须小心使用物理寄存器,如R0~R3,LR和PC

不要使用寄存器寻址变量

使用内嵌汇编时,编译器自己会保存和恢复它可能用到的寄存器,用户无须保存和恢复寄存器。事实上,除了CPSR和SPSR寄存器,对物理寄存器没写就读都会引起汇编器报错。

LDM和STM指令的寄存器列表只允许物理寄存器

汇编语言用“,”作为操作数分隔符

内嵌汇编举例

#include <stdio.h>
void my_strcpy(const char *src, char *dest)
{
  char ch;
  _asm
  {
    loop:
    ldrb ch, [src], #1
    strb ch, [dest], #1
    cmp ch, #0
    bne loop
  }
}
int main()
{
  char *a = "forget it and move on!";
  char b[64];
  my_strcpy(a, b);
  printf("original: %s", a);
  printf("copyed: %s", b);
  return 0;
}

C和ARM汇编程序间相互调用

在C和ARM汇编程序之间相互调用必须遵守ATPCS(ARM-Thumb Procedure Call Standard)规则。

汇编程序对C全局变量的访问

汇编程序可以通过地址间接访问在C语言程序中声明的全局变量。通过使用IMPORT关键词引入全局变量,并利用LDR和STR指令根据全局变量的地址可以访问它们。

对于不同类型的变量,需要采用不同选项的LDR和STR指令,如下所示:

unsigned char LDRB/STRB
unsigned short LDRH/STRH
unsigned int LDR/STR
char LDRSB/STRSB
short LDRSH/STRSH

举例:

/* cfile.c

定义全局变量,并作为主调程序
*/
#include <stdio.h>
int gVar_1 = 12;
extern asmDouble(void);
int main()
{
printf("original value of gVar_1 is: %d", gVar_1);
asmDouble();
printf(" modified value of gVar_1 is: %d", gVar_1);
return 0;
}

对应的汇编语言文件:

;called by main(in C),to double an integer, a global var defined in C is used.
AREA asmfile, CODE, READONLY
EXPORT asmDouble
IMPORT gVar_1
asmDouble
ldr r0, =gVar_1
ldr r1, [r0]
mov r2, #2
mul r3, r1, r2
str r3, [r0]
mov pc, lr
END

在C语言程序中调用汇编程序

为了保证程序调用时参数的正确传递,汇编程序的设计要遵守ATPCS。在汇编程序中需要使用EXPORT伪操作来声明,使得本程序可以被其它程序调用。同时,在C程序调用该汇编程序之前需要在C语言程序中使用extern关键词来声明该汇编程序。

举例:

/* cfile.c

*in C,call an asm function, asm_strcpy
*/
#include <stdio.h>
extern void asm_strcpy(const char *src, char *dest);
int main()
{
const char *s = "seasons in the sun";
char d[32];
asm_strcpy(s, d);
printf("source: %s", s);
printf(" destination: %s",d);
return 0;
}
;asm function implementation
AREA asmfile, CODE, READONLY
EXPORT asm_strcpy
asm_strcpy
loop
ldrb r4, [r0], #1 address increment after read
cmp r4, #0
beq over
strb r4, [r1], #1
b loop
over
mov pc, lr
END

在汇编程序中调用C语言程序

为了保证程序调用时参数的正确传递,汇编程序的设计要遵守ATPCS。在C程序中不需要使用任何关键字来声明将被汇编语言调用的C程序,但是在汇编程序调用该C程序之前需要在汇编语言程序中使用IMPORT伪操作来声明该C程序。在汇编程序中通过BL指令来调用子程序。

举例:

;the details of parameters transfer comes from ATPCS
;if there are more than 4 args, stack will be used
EXPORT asmfile
AREA asmfile, CODE, READONLY
IMPORT cFun
ENTRY
mov r0, #11
mov r1, #22
mov r2, #33
BL cFun
END
/*C file, called by asmfile */
int cFun(int a, int b, int c)
{
return a + b + c;

参考文献:

孟祥莲.嵌入式系统原理及应用教程(第2版)[M].北京:清华大学出版社,2017.文章来源地址https://www.toymoban.com/news/detail-432432.html

到了这里,关于嵌入式:ARM内嵌汇编及C和ARM汇编相互调用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ARM汇编第一次上机(顺序、分支、单重循环)【嵌入式系统】

    2023-4-14 19:30:55 以下内容源自《创作模板三》 仅供学习交流使用 ARM简单程序设计【嵌入式系统】 第一点 关于 号 不会有人不知道? 我流程图中写的 R3=nums 是什么意思吧? 请看下面C语言程序 回答 号是 取地址 的意思哦 第二点 关于说明中的 R0++ 说明 此处R0用来遍历数组的指针

    2023年04月15日
    浏览(38)
  • ARM简单程序设计【嵌入式系统】

    2023-4-6 20:26:54 以下内容源自《【嵌入式系统】》 仅供学习交流使用 Keil 4 安装教程及简单使用【嵌入式系统】 新建工程xxx 芯片:ARM7 (Little Endian) 设置工程属性 Build结果必须是0Error的 如果是下图看配置是否正确 注意这个: 1.每一次修改代码就需要重写Build 2.READWRITE区变量初始

    2023年04月20日
    浏览(48)
  • 【ARM 嵌入式 编译系列 10.2 -- 符号表与可执行程序分离详细讲解】

    请阅读 【ARM GCC 编译专栏导读】 上篇文章:ARM 嵌入式 编译系列 10.1 – GCC 编译缩减可执行文件 elf 文件大小 下篇文章:ARM 嵌入式 编译系列 10.3 – GNU elfutils 工具小结 接着上篇文章 ARM 嵌入式 编译系列 10.1 – GCC 编译缩减可执行文件 elf 文件大小 介绍,在前两篇文章中我们去

    2024年02月13日
    浏览(45)
  • 嵌入式Qt-动手编写并运行自己的第1个ARM-Qt程序

    介绍了如何搭建在Linux开发板中搭建Qt的运行环境,并测试了Qt自带的例程。 本篇,来介绍如何自己编写一个Qt程序,并将编译结果放到Linux开发板中运行。 因为Qt是支持跨平台的,所以我们可以先在Windows平台上编写和查看Qt的运行效果,然后再通过交叉编译,编译出ARM Linux平

    2024年02月02日
    浏览(33)
  • 嵌入式学习笔记(16)反汇编工具objdump

    2.4.1反汇编的原理为什么要用反汇编 arm-linux-objdump -D led.elf led_elf.dis objdump是gcc工具链中的反汇编工具,作用是由编译链接好的elf格式的可执行程序反过来得到汇编源代码 -D表示反汇编 左边的是elf可执行程序(反汇编的源) 右边的是反汇编生成的反汇编程序 反汇编的原因有以

    2024年02月09日
    浏览(36)
  • 嵌入式Linux裸机开发(一)基础介绍及汇编LED驱动

    现在开始正式在开发板上进行开发,仍然看的是正点原子的资料 使用的是Cortex-A7 点击芯片名字打开介绍,主要参考的手册是: 以及数据手册: 对于一般的STM32来说,IO的表现形式为: 管教名为PA1,管脚的功能在倒数第二列 对于IMX6ULL,IO形式在参考手册里面,且没有上面的表

    2024年02月07日
    浏览(51)
  • 嵌入式开发——ARM介绍

    ARM是一种芯片架构,由英国的ARM Holdings公司开发和授权,被广泛应用于各种嵌入式系统、移动设备和消费电子产品中。ARM架构被设计成低功耗、高性能、可定制化的特点,能够满足各种应用场景下的需求。 ARM架构主要设计了以下几个部分内容: 指令集架构 (Instruction Set Ar

    2024年02月04日
    浏览(45)
  • 嵌入式学习---ARM时钟体系

    按 一定电压幅度 , 一定时间间隔 连续发出的脉冲信号。它是一个周期性的信号,每个周期内包含一个上升沿和一个下降沿。时钟脉冲的上升沿和下降沿通常用于触发和同步各个电子元件的操作,例如CPU的指令执行、数据传输、寄存器更新等。 时钟频率是指时钟脉冲的频率

    2024年01月16日
    浏览(51)
  • 嵌入式:ARM Day6

    目的:1.输入\\\'a\\\',显示\\\'b\\\',将输入的字符的ASCII码下一位字符输出            2.原样输出输入的字符串 源码: uart4.h  uart4.c main.c 结果1: 结果2: 

    2024年02月12日
    浏览(37)
  • 嵌入式:ARM Day4

     源码:         在上述代码中,int *ptr定义了一个指向整数类型的指针ptr,(int *)将地址0x5000A28强制转换为整数类型的指针,后续可以通过*ptr访问与修改该地址空间中的值。  

    2024年02月12日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包