GNU内联汇编

内联汇编即在C中直接使用汇编语句进行编程,使程序可以在C程序中实现C语言不能完成的一些工作,例如,在下面几种情况中必须使用内联汇编或嵌入型汇编

  1. 程序中使用饱和算术运算(Saturating Arithmetic)
  2. 程序需要对协处理器进行操作
  3. 在C程序中完成对程序状态寄存器的操作
__asm__ __volatile__("asm code":output:input:changed registers);

Note:

  1. 使用__asm____volatile__表示编译器将不检查后面的内容,而是直接交给汇编器。
  2. 如果希望变压器你优化,__volatile__可以不加
  3. 没有asm code也不能省略""
  4. 没有前面的和中间的部分,不可以相应的省略:
  5. 没有changed 部分,必须相应的省略:
  6. 最后的;不能省略,对于C语言来说这是一条语句
  7. 汇编代码必须放在一个字符串内,且字符串中间不能直接按回车换行,可以写成多个字符串,注意中间不能有任何符号,这样就会将两个字符串合并为一个
  8. 指令之间必须要换行,还可以使用\t使指令在汇编中保持整齐

asm code

"mov r0, r0\n\t"
"mov r1,r1\n\t"
"mov r2,r2"

output(asm->C)

:"constraint" (variable)

"constraint"用于定义variable的存放位置:

r表示使用任何可用的寄存器

m表示使用变量的内存地址

+可读可写

=只写

&表示该输出操作数不能使用输入部分使用过的寄存器,只能用"+&""=&"的方式使用

input(C->asm)

:"constraint" (variable/immediate)

"constraint"用于定义variable的存放位置:

r表示使用任何可用的寄存器(立即数和变量都可以)

m表示使用变量的内存地址

i表示使用立即数

例子

int a=100,b=200;
int result;
__asm__ __volatile__(
"mov %0,%3\n\t" //%0是一个占位符,表示result,之后的类推
"ldr r0,%1\n\t"
"ldr r1,%2\n\t"
"str r0,%2\n\t"
"str %1,%1\n\t"
:"=r"(result),"+m"(a),"+m"(b)
:"i"(123)
);

ATPCS

  1. 子程序间通过寄存器R0R3来传递参数,如果参数多于四个,则多出的部分用堆栈传递,被调用的子程序在返回前无须恢复寄存器R0R3的内容
  2. 在子程序中,使用寄存器R4R11来保存局部变量,如果在子程序中使用到了R4R11中的某些寄存器,子程序进入时必须保存这些寄存器的值,在返回前必须恢复这些寄存器的值;对于子程序中没有用到的寄存器则不必进行这些操作,在Thumb程序中,通常只能使用寄存器R4~R7来保存局部变量
  3. R12用作子程序间scrtach寄存器(用于保存SP,在函数返回时使用该寄存器出栈),记作ip
  4. R13用作数据栈指针,记作sp
  5. R14用作连接寄存器,记作lr
  6. R15记作程序寄存器,记作pc

相互调用

C和汇编相互调用要特别注意遵守相应的ATPCS规则

C调用汇编

//.c
#include <stdio.h>
extern void strcopy(char* des, const char* src);
int main(){
const char* srcstr = "src string";
char desstr[]="des string";
strcopy(desstr, srcstr);
return 0;
}
;.asm
.global strcopy
strcopy: ;R0指向目的字符串
;R1指向源字符串
LDRB R2, [R1], #1 ;加载字节并更新源字符串指针地址
STRB R2, [R0], #1 ;存储季节并更新目的字符串指针地址
CMP R2, #0 ;判断是否为字符串结尾
BNE strcopy ;如果不是,程序跳转到strcopy继续循环
MOV pc, ir ;程序返回

汇编调用C

//.c
int fcn(int a, int b , int c, int d, int e){
return a+b+c+d+e;
}
;.asm
;假设程序进入f时,R0中的值为i
;int f(int i){return fcn(i, 2*i, 3*i, 4*i, 5*i);}
.text
.global _start
_start:
STR lr, [sp, #-4]! ;保存返回地址lr
ADD R1, R0, R0 ;计算2*i(第2个参数)
ADD R2, R1, R0 ;计算3*i(第3个参数)
ADD R3, R1, R2 ;计算5*i
STR R3, [SP, #-4]! ;第5个参数通过堆栈传递
ADD R3, R1, R1 ;计算4*i(第4个参数)
BL fcn ;调用C程序
ADD sp, sp, #4 ;从堆栈中删除第五个参数
.end

ARM汇编与C混合编程的更多相关文章

  1. VS2005混合编译ARM汇编代码-转

    原文地址:http://blog.csdn.net/annelcf/article/details/5468093 公司HW team有人希望可以给他们写一个在WinCE上,单独读写DDR的工具,以方 ...

  2. ARM中C和汇编混合编程及示例(转)

    在嵌入式系统开发中,目前使用的主要编程语言是C和汇编,C++已经有相应的编译器,但是现在使用还是比较少的.在稍大规模的嵌入式软件中,例如含有OS,大部分的代码都是用C编写的,主要是因为C语言的结构比较 ...

  3. 九、ARM 汇编与 C 的混合编程

    9.1 ARM 汇编与 C 的混合编程 9.1.1 内嵌汇编 __asm __asm("指令")例如关闭/打开总中断开关 CPSR __asm //使用 C 中变量名代替寄存器 { ...

  4. c语言环境初始化&c语言和汇编混合编程

    bootloader通常会分为两个阶段:第一阶段采用汇编语言来编写,主要是一些核心的初始化工作(内存,时钟的初始化),第二阶段使用C语言来编写,主要是它会完成一些板载硬件的初始化(串口,网口)然后其启 ...

  5. ARM汇编编程基础之一 —— 寄存器

    ARM的汇编编程,本质上就是针对CPU寄存器的编程,所以我们首先要弄清楚ARM有哪些寄存器?这些寄存器都是如何使用的? ARM寄存器分为2类,普通寄存器和状态寄存器 寄存器类别 寄存器在汇编中的名称 ...

  6. 3.1 ARM汇编编程概述

    1. 汇编编程 为什么要学习汇编 1). Bootloader初始化 2). Linux kernel 3). 高效 2. ARM汇编分类 1. ARM标准汇编:ARM公司得汇编器适合在Windows ...

  7. ARM汇编编程概述

    1.为什么需要学些汇编指令 2.ARM汇编指令分类 3.汇编程序框架 4.编程准备 +++++++++++++++++++++++++++++++++++ 1.为什么需要学些汇编指令 bootload ...

  8. C51与汇编混合编程详解

    C51和汇编混合编程(1)-C语言中嵌入汇编 1.在 C文件中要嵌入汇编代码片以如下方式加入汇编代码: #pragma ASM ;Assembler Code Here #pragma ENDASM ...

  9. 【转】VxWorks中高精度实时时钟的实现及C语言汇编混合编程

    最近一个项目中需要在VxWorks下使用一个高精度实时时钟,要求精度为1ms,溢 出时间大于5小时.VxWorks提供系统时钟,该时钟在操作系统启动后开始计数,精度为1个tick,可以通过tickGe ...

随机推荐

  1. JavaScript 中的相等检测

    一.有时JavaScript的等价比较是一件抓狂的事情,看看这个表格就一目了然了.

  2. 一个网站完整详细的SEO优化方案

    根据自己的个人经验完成了这篇文章,希望对SEOer有点帮助,高手直接跳过,请勿喷水... 一个完整的SEO优化方案主要由四个小组组成: 一.前端/页编人员 二.内容编辑人员 三.推广人员 四.数据分析 ...

  3. iOS多线程技术方案

    iOS多线程技术方案 目录 一.多线程简介 1.多线程的由来 2.耗时操作的模拟试验 3.进程和线程 4.多线程的概念及原理 5.多线程的优缺点和一个Tip 6.主线程 7.技术方案 二.Pthrea ...

  4. asp.net mvc4 添加分区出现错误 找到多个与名为“home”的控制器匹配的类型

    会出现如下错误”找到多个与名为“home”的控制器匹配的类型“   在RouteConfig文件中添加命名空间可解决   routes.MapRoute(                 name: ...

  5. 【C#公共帮助类】分页逻辑处理类

    分页逻辑处理类 PageCollection.cs using System; using System.Collections.Generic; using System.Linq; using S ...

  6. 扩展lamda表达中distinct按照字段去除重复

    首先,我们定义一个Student类来测试. public class Student { public int ID { get; set; } public string Name { get; s ...

  7. java for循环冒泡排序

    int[]a =new int[]{7,19,66,21,88,40}; for(int i=1;i<=a.length-1;i++){ //比总长度减1趟就排好序了.因为每一趟出一个值. fo ...

  8. Jenkins在Windows系统dotnet平台持续集成

            之前写过一篇文章是在CentOS上构建.net自动化编译环境, 今天这篇是针对于Windows平台的环境.        Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平 ...

  9. phpstorm10.0.3破解版安装教程及汉化方法

    phpstorm是一个轻量级且便捷的PHP IDE,其旨在提供用户效率,可深刻理解用户的编码,提供智能代码补全,快速导航以及即时错误检查.不但是php开发的利器,前端开发也是毫不逊色的.下面记录php ...

  10. PHP 字符串左边补0,字符串右边补0

    概述:项目中经常会使用到在一串编码左边.右边甚至中间自动填充制定字符如"0" 并且制定填充后的字符串长度. 函数str_pad:该函数返回 input 被从左端.右端或者同时两端被 ...