ARM汇编与C言语的混合编程

1. C言语如何与汇编进行交互

有些时候,我们需要在汇编代码中调用C代码,或者说C代码中调用汇编代码。

那么,汇编调用C代码,或者C代码调用汇编函数,他们的函数参数、返回值是如何传递的?

对应ARM架构来说,有一个 ATPCS (ARM-Thumb Produce Call Standard),ARM-Thumb过程调用标准。ATPCS 标准规定了下面几个方面:

  • 1、函数调用过程中的寄存器用法。比如说 R4-R11 、 R13(SP) 、R14(LR) 这些寄存器的值,应该由子程序保证不改变。也就是说在执行子程序时,如果这些寄存器需要被修改的话,那么应该先压栈,然后才能再去调用子程序。
  • 2、规定函数参数和返回值的传递。一般来说 R0-R3 这4个寄存器用于函数的输入参数,然后函数的返回值是放在 R0 寄存器的。当然,如果输入参数大于 4 个参数是,寄存器就不够用了,那么这时需要使用到栈。
  • 3、规定栈对齐。如果汇编代码调用C函数,就要确保当前的栈指针指向了双字对齐的地址(如0x20000000、0x20000008、0x20002010 等)。

对于在函数调用时的参数传递过程,可归纳为如下表格:

寄存器输入参数返回值
R0第 1 个输入参数函数返回值
R1第 2 个输入参数不使用,或者返回值(返回值是64位时)
R2第 3 个输入参数不使用
R3第 4 个输入参数不使用

函数调用过程中,寄存器的用法如下表:

在这里插入图片描述

2. 汇编调用C函数

汇编调用C函数,是汇编与C语言混合编程遇见最多的场合了。

前面说过了,ATPCS标准,函数调用时,使用 R0-R3 传递参数,R0 作为返回值。

比如,下面的一个C函数:

int my_add_c(int x1, int x2, int x3, int x4)
{return (x1 + x2 + x3 + x4);
}

根据ATPCS标准,x1=R0, x2=R1, x3=R2, x4=R3, 然后返回值是存放在 R0 寄存器的。另外,还需要注意调用者保存的寄存器(R0-R3, R12)这些寄存器可能会被C函数修改。

下面的汇编代码调用C函数示例:

MOVS R0, #0x1 ; First parameter (x1)
MOVS R1, #0x2 ; Second parameter (x2)
MOVS R2, #0x3 ; Third parameter (x3)
MOVS R3, #0x4 ; Fourth parameter (x4)
IMPORT my_add_c
BL my_add_c ; Call “my_add_c” function. Result store in R0

3. C函数调用汇编函数

使用汇编代码实现函数,然后通过C代码调用汇编函数。

在汇编代码中,我们需要确保,如果C代码要修改被调用者保存的寄存器(如R4-R11等),那么在汇编代码中要先对这些寄存器进行压栈处理,然后退出函数之前将这些寄存器恢复。

如果这个C函数还可能会调用到另一个函数,那么在汇编代码中,还需要保存LR寄存器的值。

汇编函数的实现:

EXPORT My_Addmy_add_asm FUNCTIONADDS R0, R0, R1ADDS R0, R0, R2ADDS R0, R0, R3BX LR ; Return result in R0ENDFUNC

当然,如果汇编代码需要访问C代码中的变量,则可以使用 IMPORT 关键字(不同的工具链可能不一样,gcc工具链是 .global 关键字)

然后,在C代码中调用这个汇编函数。

extern int my_add_asm(int x1, int x2, int x3, int x4);
...
int y;
...
y = my_add_asm(1, 2, 3, 4); // call the my_add_asm function

4. C代码嵌入汇编

很多编译器都支持,在C代码中,实现汇编函数。

对应 ARM CC 编译器来说,需要在函数前面加上 __asm 关键字修饰。

比如,下面在C代码中,实现一个加法函数:

__asm int My_Add1(int x1, int x2, int x3, int x4)
{ADDS R0, R0, R1ADDS R0, R0, R2ADDS R0, R0, R3BX LR ; Return result in R0
}

当然,如果你需要在嵌入的汇编函数中,需要访问变量或者地址值,可以使用 __cpp 关键字,如下:

__asm void function_A(void)
{PUSH {R0-R2, LR}BL __cpp(LCD_clr_screen) ; 方法1调用C函数LDR R0,=__cpp(&pos_x)    ; 获取C代码变量地址,存放到R0寄存器LDR R0, [R0]			 ; 把 R0 的值,写到以R0的值作为地址的内存中LDR R1,=__cpp(&pos_y)LDR R1, [R1]LDR R2, =__cpp(LCD_pixel_set) ; Import the address of a functionBLX R2 ; 方法2调用C函数POP {R0-R2, PC}
}

5. C代码内联汇编

在一个C函数中,我们可以使用内联汇编的语法,把一些汇编指令,插入到C函数里面。

比如下面的一个C函数:

int My_Add2(int i, int j)
{int ret;__asm{ADD ret, i, j}return ret;
}

这个函数,本身是一个C函数,但是在C函数内部插入了汇编指令。

对于GCC编译器,支持的内联汇编语法如下:

__asm (“ inst1 op1, op2, ... \n”
“ inst2 op1, op2, ... \n”
...
“ instN op1, op2, . \n”
: output_operands /* optional */
: input_operands /* optional */
: clobbered_operands /* optional */
);

关于内联汇编语法的详细介绍,可以参考 GUN 工具链的帮助文档 GCC-Inline-Assembly-HOWTO 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/148565.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

angularjs开发环境搭建

Angularjs是一个前端页面应用开发框架,其使用TypeScript作为开发语言,Angularjs的特性包括,使用组件、模板以及依赖注入的开发框架构建可扩展的web应用,使用易于集成的类库支持页面路由、页面表单、前后端接口交互等各种不同特性&…

RabbitMQ-主题模式

接上文 RabbitMQ-发布订阅模式和路由模式 1 主题模式 #通配符 代表0个或多个。*通配符 代表 1个或多个 进行测试,修改配置文件 Configuration public class RabbitConfiguration {Bean("topicExchange") //这里使用预置的Topic类型交换机public Exchan…

Android Studio实现简易计算器(带横竖屏,深色浅色模式,更该按钮颜色,selector,style的使用)

目录 前言 运行结果: 运行截屏(p50e) apk文件 源码文件 项目结构 总览 MainActivity.java drawable 更改图标的方法: blackbutton.xml bluebuttons.xml greybutton.xml orangebuttons.xml whitebutton.xml layout 布…

嵌入式Linux应用开发-驱动大全-同步与互斥③

嵌入式Linux应用开发-驱动大全-同步与互斥③ 第一章 同步与互斥③1.4 Linux锁的介绍与使用1.4.1 锁的类型1.4.1.1 自旋锁1.4.1.2 睡眠锁 1.4.2 锁的内核函数1.4.2.1 自旋锁1.4.2.2 信号量1.4.2.3 互斥量1.4.2.4 semaphore和 mutex的区别 1.4.3 何时用何种锁1.4.4 内核抢占(pree…

2023年中国体育赛事行业现状及趋势分析:体育与科技逐步融合,推动产业高质量发展[图]

体育赛事运营是指组织体育赛事或获取赛事版权,并进行赛事推广营销、运营管理等一系列商业运作的运营活动。体育赛事运营相关业务主要包括赛事运营与营销、赛事版权运营两个部分。 体育赛事运营行业分类 资料来源:共研产业咨询(共研网&#x…

MySQL面试题合集

MySQL面经知识整理 文章目录 MySQL面经知识整理一、查询相关1.什么是MySQL的连接查询,左连接,右连接,内外连接2.SQL慢查询优化的方法3.大表查询如何优化 二、索引相关1.在MySQL中,可以通过哪些命令来查看查询是否使用了索引2.MySQL的最左匹配…

实验三十四、串联型稳压电路参数的选择

一、题目 电路如图1所示。已知输入电压为 50 Hz 50\,\textrm{Hz} 50Hz 的正弦交流电,来源于电源变压器副边;输出电压调节范围为 5 ∼ 20 V 5\sim20\,\textrm V 5∼20V,满载为 0.5 A 0.5\,\textrm A 0.5A; C 3 C_3 C3​ 为消振…

在排序数组中查找元素的第一个和最后一个位置

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。 如果数组中不存在目标值 target,返回 [-1, -1]。 你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。 示例 1&#xff1a…

结构和基本尺寸

声明 本文是学习GB-T 586-2015 船用法兰铸钢止回阀. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了法兰连接尺寸和密封面按 CB/T 4196、GB/T 2501 的船用法兰铸钢止回阀(以下简 称止回阀)的分类和标记、要求、试验方法、检验规…

使用Java操作Redis

要在Java程序中操作Redis可以使用Jedis开源工具。 一、jedis的下载 如果使用Maven项目&#xff0c;可以把以下内容添加到pom中 <!-- https://mvnrepository.com/artifact/redis.clients/jedis --> <dependency> <groupId>redis.clients</groupId>…

【LeetCode热题100】--114.二叉树展开为链表

114.二叉树展开为链表 方法一&#xff1a;对二叉树进行先序遍历&#xff0c;得到各个节点被访问到的顺序&#xff0c;利用数组存储下来&#xff0c;然后在先序遍历之后更新每个节点的左右节点的信息&#xff0c;将二叉树展开为链表 /*** Definition for a binary tree node.* …

Vue+ElementUI实现动态树和表格数据的分页模糊查询

目录 前言 一、动态树的实现 1.数据表 2.编写后端controller层 3.定义前端发送请求路径 4.前端左侧动态树的编写 4.1.发送请求获取数据 4.2.遍历左侧菜单 5.实现左侧菜单点击展示右边内容 5.1.定义组件 5.2.定义组件与路由的对应关系 5.3.渲染组件内容 5.4.通过动态…

FFmpeg 命令:从入门到精通 | ffmpeg filter(过滤器 / 滤镜)

FFmpeg 命令&#xff1a;从入门到精通 | ffmpeg filter&#xff08;过滤器 / 滤镜&#xff09; FFmpeg 命令&#xff1a;从入门到精通 | ffmpeg filter&#xff08;过滤器 / 滤镜&#xff09;ffmpeg fliter 基本内置变量视频裁剪文字水印图片水印画中画视频多宫格处理 FFmpeg 命…

希尔排序(C++实现)

文章目录 前言1. 基础概念2. 动图演示3. 代码实现4. 排序过程5. 效率分析6. 总结 前言 上篇文章讲了直接插入排序算法。 首先&#xff0c;在待排序的数组中&#xff0c;元素本身就是有序的情况下&#xff0c;就不需要移动任何元素&#xff0c;所以直接插入排序最好情况时间复…

进程调度的时机,切换与过程以及方式

1.进程调度的时机 进程调度&#xff08;低级调度〉&#xff0c;就是按照某种算法从就绪队列中选择一个进程为其分配处理机。 1.需要进行进程调度与切换的情况 1.当前运行的进程主动放弃处理机 进程正常终止运行过程中发生异常而终止进程主动请求阻塞&#xff08;如等待l/O)…

数据结构与算法-顺序表

数据结构与算法 &#x1f388;1.线性表&#x1f50e;1.1基本操作&#x1f50e;1.2线性表的存储结构 &#x1f388;2.线性表的顺序表示和实现&#x1f50e;2.1线性表的顺序存储表示&#x1f52d;2.1.1静态顺序表&#x1f52d;2.1.2动态顺序表 &#x1f50e;2.2顺序表基本操作的实…

MYSQL8解压版 windows 主从部署步骤及配置(包含配置文件,教程文件,免积分下载)

MYSQL8解压版 windows 主从部署步骤及配置 一.安装MSYQL 这里只讲大概,详细步骤、my.ini文件、安装包等会在页尾文件中(正常情况按首个mysql安装,只是名字有区别) 1.主库my.ini配置 [mysqld] #典型的值是5-6GB(8GB内存)&#xff0c;8-11GB(16GB内存), 20-25GB(32GB内存)&…

阿里云对象存储OSS SDK的使用

官方文档 https://help.aliyun.com/zh/oss/developer-reference/java 准备工作 windows安装好JDK&#xff0c;这里使用JDK1.8为例 windows安装好IDEA&#xff0c;这里使用IDEA2022 登录阿里云控制台&#xff0c;通过免费试用OSS或开通OSS 步骤 配置访问凭证 有临时和长期…

【Go】go-es统计接口被刷数和ip访问来源

go-es模块统计日志中接口被刷数和ip访问来源 以下是使用go的web框架gin作为后端&#xff0c;展示的统计页面 背景 上面的数据来自elk日志统计。因为elk通过kibana进行展示&#xff0c;但是kibana有一定学习成本且不太能满足定制化的需求&#xff0c;所以考虑用编程的方式…

mysql-binlog

1. 常用的binlog日志操作命令 1. 查看bin-log是否开启 show variables like log_%;2. 查看所有binlog日志列表 show master logs;3.查看master状态 show master status;4. 重置&#xff08;清空&#xff09;所有binlog日志 reset master;2. 查看binlog日志内容 1、使用mysqlb…