1、C嵌套汇编

首先说一下关于GCC编译嵌有汇编语言的c语言吧,GCC编译的汇编语言不是我们上课时学的Intel x86汇编,而是AT&T汇编,两者的区别可以查看《Gcc使用的内嵌汇编语法格式小教程》。

下面是内嵌汇编的格式:语法:__asm__(“instruction

……  instruction"); //Linux gcc中支持(注意asm的下划线均为两个否则GCC将会无法编译。)

__asm{

instruction

instruction

};   //ADS中支持(注意asm的下划线均为两个否则GCC将会无法编译。)

asm(“instruction [; instruction]”);   //ARM C++中使用

例1是我在linux环境下,编的嵌有汇编程序的c语言,并通过了GCC的编译:

例1:

#include<stdio.h>

int plus(int a,int b)

{

__asm__

(

“add %1,%0\n\t”:”+r”(a):”r”(b)

);

return (c);

}

int main()

{int a,b,c;

a=2;

b=1;

c=plus(a,b);

printf(“c=%d\n”,c);

}

这个程序应该是很简单的,但关键是子函数中嵌入的那段汇编程序,具体的写法可以参看其他文章。

例2同样是c语言中嵌入了汇编,与例1不同的是,这个程序的编译环境为ADS。

例2

#include <stdio.h>

void  my_strcpy(char* src, const char* dst){

int ch;

__asm{

loop:

LDRB        ch, [src], #1

STRB   ch, [dst], #1

CMP     ch, #0

BNE    loop

};

}

int main(void){

const char* a = "Hello World!";

char   b[20];

__asm{

MOV    R0, a

MOV    R1, b

BL           my_strcpy, {R0, R1}

};

printf("Original String: %s\n",a);

printf("Copied String: %s\n",b);

return 0;

}

一定要注意例1与例2中汇编语言的语法格式。

2、C语言调用汇编

再说一下如何将一个c语言文件与一个汇编文件通过ADS环境编译,并通过ATX进行DEBUG调试的。先看一下下面的例3。

例3

Cfile.c

#include <stdio.h>

extern void strcopy(char *d, const char *s);

int main()

{       const char *srcstr = "abcde";

char dststr[32];

/* dststr is an array since we're going to change it */

printf("Before copying:\n");

printf("  '%s'\n  '%s'\n",srcstr,dststr);

strcopy(dststr,srcstr);

printf("After copying:\n");

printf("  '%s'\n  '%s'\n",srcstr,dststr);

return 0;

}

Asmfile.s

AREA    SCopy, CODE, READONLY

EXPORT strcopy

strcopy

; r0 points to destination string

; r1 points to source string

LDRB    r2, [r1],#1     ; load byte and update address

STRB    r2, [r0],#1     ; store byte and update address;

CMP     r2, #0          ; check for zero terminator

BNE     strcopy         ; keep going if not

MOV     pc,lr           ; Return

END            ;注意!!汇编代码编写时一定要缩进,否则编译将会出错

这是一个c语言调用汇编的例子,功能是为了实现字符串的拷贝,其中汇编文件为字符串拷贝的功能子函数。在这里需要说明的是c语言调用汇编语言的一些基本规则,首先是参数传递的规则,c语言的函数前4个参数通过R0-R3来传递,其它参数通过堆栈(FD)传递,且这种传递是单项的,即汇编语言中的R0-R3的值不会再回传给c语言。拿例3举例来说,当在语言中调用strcopy(dststr,srcstr);时,字符串dststr的首地址将会传给r0,srcstr的首地址将会传给r1,当汇编语言拿到这两个寄存器时,就会通过地址依次加1的形式进行地址内容的复制也就是字符串的复制,当复制到最后一个字母e时,通过比较r2寄存器中的值是否为0来判断是否调出汇编程序(因为在c语言中声明字符串时末尾被自动的添加了一个\0),这里需要注意的是,此时寄存器r0的值为指向源字符串末尾的’\0’的地址值,而寄存器r1的值为指向已经拷贝过的目的字符串中的”e”的地址值,当调出汇编程序时,r0,r1这两个值将不会回传给strcopy(dststr,srcstr);中的两个参数dststr和srcstr,这两个参数的值仍然是c语言在初始化这两个字符串时指向字符串的首地址,这一点可以通过ATX调试时观察寄存器的变化情况来证明。但是为什么地址值没有变化,但却实现了字符串的拷贝了呢?这主要时因为通过汇编程序,虽然没有改变两个指针的位置,但却改变了两个字符串所在内存地址中的内容,这种方式就是c语言中常说的引用方式,即dststr和r0起初指向的是同一内存空间,但是字符串复制时只是利用r0来复制的,而dststr的位置却没有发生变化。因此在c语言中输出字符串时并不需要将dststr减去字符串的个数来实现指向字符串的首地址。

这个程序中第二个需要注意的地方是,汇编程序段中的起到临时存放字符串的r2寄存器,很奇怪的是这个地方的寄存器不能换成r4,如果换成r4的话,输出的结果就会有问题,这一点我现在还没有找到答案,希望将来某一天能遇见高人给我指点一下。

最后需要注意的地方是在汇编程序末尾一定要加上MOV  pc, lr

用ADS编译后,两个文件会被自动的链接,并在工程文件夹下生成一个.o文件,这个文件就是将来要下到开发板上的二进制文件,其中还有一个.axf的镜像文件,这个文件是用来进行ATX调试的,默认的单步调试是在反汇编中进行的,这就会给调试程序带来极大的不便,通过自己的摸索,发现可以通过设置strong source实现在c语言中进行单步调试,两外在单步调试中通过watch来观察c语言中的形参的值和地址的变化情况,便于程序的调试,需要强调的一点时,汇编程序与c程序的文件名不能相同,否则将无法用ATX进行调试。

另外,在汇编程序中访问c程序全局变量的例子。程序中变量globvl是在c程序中声明的全局变量。在汇编程序中首先用IMPORT伪操作声明该变量;再将其内存地址读入到寄存器R1中;再将其值读入到寄存器R0中;修改后再将寄存器R0的值赋于变量globvl。请参看例4

例4

#include <stdio.h>

int  globvl;

int main(){

globvl = 0;

asmsub();

printf(“globvl = %d”, globvl);

return 0;

}

AREA  globals, CODE, READONLY

EXPORT asmsub

IMPORT globvl

asmsub

LDR  r1,  =globvl

LDR  r0, [r1]

ADD  r0, r0, #2

STR  r0, [r1]

MOV  pc, lr

END                ;注意!!汇编代码编写时一定要缩进,否则编译将会出错

3、汇编调用c

最后我再谈一下如何在汇编中调用c,看一下例5

例5

int g(int a, int b, int c, int d, int e)

{

return a + b + c + d + e;

}

;汇编程序调用c程序g()计算5个整数i, 2*i, 3*i, 4*i, 5*i的和

EXPORT f

AREA  f, CODE, READONLY

IMPORT  g                 ;使用伪操作数IMPORT声明c程序g()

STR  lr, [sp,#-4]!        ;保存返回地址

ADD  r1, r0, r0          ;假设进入程序f时,r0中的值为i,r1值设为2*i

ADD  r2, r1, r0          ;r2的值设为3*i

ADD  r3, r1, r2        ;r3的值设为5*i

STR  r3, [sp, # -4]!     ;第五个参数5*i通过数据栈传递

ADD  r3, r1, r1        ;r4值设为4*i

BL   g        ;调用c程序g()

ADD  sp, sp, #4              ;调整数据栈指针,准备返回

LDR  pc, [sp], #4       ;返回

END                 ;注意!!汇编代码编写时一定要缩进,否则编译将会出错

注意,c语言最终返回的五个数之和放到了r0寄存器中。

关于C语言和汇编语言相互嵌套调用的更多相关文章

  1. C语言与汇编语言相互调用原理以及实例

    C语言与汇编语言相互调用原理以及实例 1.原理 其实不管是C语言还是汇编语言想要执行都是最终编译链接成为二进制文件. 这里一定要明确编译和链接是两个步骤,生成的文件格式也是不一样的. 编译生成的文件是 ...

  2. Swift2.0语言教程之函数嵌套调用形式

    Swift2.0语言教程之函数嵌套调用形式 Swift2.0语言函数嵌套调用形式 在Swift中,在函数中还能够调用函数,从而形成嵌套调用.嵌套调用的形式往往有两种:一种是在一个函数中调用其它函数:还 ...

  3. keil C语言与汇编语言混合编程

    C与汇编混合编程主要有以下几种:(1)C语言中嵌入汇编(2)无参数传递的函数调用(3)有参数传递的函数调用 一.C语言中嵌入汇编 1.在 C 文件中要嵌入汇编代码片以如下方式加入汇编代码: #prag ...

  4. 浅谈单片机中C语言与汇编语言的转换

    做了一单片机设计,要用C语言与汇编语言同时实现,现将这次设计的感受和收获,还有遇到的问题写下,欢迎感兴趣的朋友交流想法,提出建议. 单片机设计:基于51单片机的99码表设计 软件环境:Proteus8 ...

  5. Spring事务传播特性的浅析——事务方法嵌套调用的迷茫

    Spring事务传播机制回顾 Spring事务一个被讹传很广说法是:一个事务方法不应该调用另一个事务方法,否则将产生两个事务.结果造成开发人员在设计事务方法时束手束脚,生怕一不小心就踩到地雷. 其实这 ...

  6. 单片机C 语言与汇编语言混合编程

    在单片机应用系统设计中,过去主要采用汇编语言开发程序. 汇编语言编写的程序对单片机硬件操作很方便,编写的程序代码短,效率高,但系统设计的周期长,可读性和可移植性都很差.C语言程序开发是近年来单片机系统 ...

  7. Swift2.0语言教程之类的嵌套与可选链接

    Swift2.0语言教程之类的嵌套与可选链接 Swift2.0语言类的嵌套 在一个类中可以嵌套一个或者多个类.它们的嵌套形式也是不同的,大致分为了两种:直接嵌套和多次嵌套.下面依次讲解这两种方式. S ...

  8. “全栈2019”Java第七十四章:内部类与静态内部类相互嵌套

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. Go语言系列开发之延迟调用和作用域

    Hello,各位小伙伴大家好,我是小栈君,最近一段时间我们将继续分享关于go语言基础系列,当然后期小栈君已经在筹划关于java.Python,数据分析.人工智能和大数据等相关系列文章.希望能和大家一起 ...

随机推荐

  1. 2013 Multi-University Training Contest 3

    HDU-4622 Reincarnation 题意:给定一个字符串,有Q次询问,每次询问得出区间[L, R]内有多少个不同的子串. 分析:后缀数组搞,不过hash+dp也能够搞定这题,详解见http: ...

  2. Web Service 接口实现大量数据传输的解决方案

    1,流程图 2,流程说明:线程1开始请求接口获取1W条数据,当数据成功获取后,接口是闲置的,这时我们开始线程2获取数据,同时线程1继续执行获取数据的后续工作,如果转换数据,这里我用的办法是,使用预先定 ...

  3. [置顶] 将项目从tomcat 迁移到JBoss

    注:针对的是jboss5.0,其它版本没有测试过 ,主要参考了:http://www.diybl.com/course/3_program/java/javajs/20100719/460908.ht ...

  4. [转载] linux 速查表

    原文: http://www.nixtutor.com/linux/all-the-best-linux-cheat-sheets/ 1. Linux Command Line Linux Refer ...

  5. 百度编辑器Ueditor的简单调用

    先去ueditou.baidu.com网站下载百度编辑器,放到项目根目录下的Data目录中,然后引入文件 <!DOCTYPE html> <html lang="en&qu ...

  6. UIButton、UIImageView、UILabel的选择

    UIButton特点既能显示文字,又能显示图片(能显示2张图片,背景图片.内容图片)长按高亮的时候可以切换图片\文字直接通过addTarget...方法监听点击 UIImageView能显示图片,不能 ...

  7. 2015苹果WWDC开发者大会

    2015苹果WWDC开发者大会 (1)本届主题为“the epicenter of change(变革的中心)” (2)iOS 9.OS X.watchOS三款重要系统更新以及其他服务 (3)iOS ...

  8. iOS开发之 xcode6 APP 打包提交审核详细步骤

    一. 在xcode6.1和ios10.10.1环境下实现app发布 http://blog.csdn.net/mad1989/article/details/8167529 http://jingya ...

  9. [html] Quirks Standards

    [产生] Standards : 从IE6开始,引入了Standards模式 Quirks  : 在IE6之前CSS还不够成熟,所以IE5等之前的浏览器对CSS的支持很差,为了兼容ie5之前的页面, ...

  10. mysql 命令行快速导出数据,导入数据

    如果数据有20几万以上的时候,下面的方法很实用 导出数据 1.into outfile select * from table into outfile 'C:/a.sql'; 2.mysqldump ...