ARM实验5_嵌入式C与汇编混合编程
五、c语言与汇编语言混合编程
2、 C程序调用汇编程序
第一步:建立汇编源文件Factorial.s
/* Factorial.s */ AREA Fctrl, CODE, READONLY EXPORT Factorial Factorial MOV R8 , R0 MOV R9 , #0 SUB R0,R8,#1 Loop MOV R1 , R9 UMULL R8 , R9 , R0 , R8 MLA R9 , R1 , R0 , R9 SUBS R0 , R0 , #1 BNE Loop LDR R0,=0xFFFFFFF0 STMIA R0,{R8,R9} MOV PC,LR MOV PC,LR ; 声明代码段 Fctrl
在ARM开发工具编译环境下设计程序,用ARM 汇编语言调用C语言实现20!的阶乘操作,并将 结果保存到寄存器R0中。
4ห้องสมุดไป่ตู้
1、汇编程序调用C程序
然后建立C语言源文件factorial.c
/* factorial.c */ long long Factorial(char N) { char i; long long Nx=1; for(i=1;i<=N;i++)Nx=Nx*i; return Nx; }
初始化过程
初始化存储器及 SDRAM 初始化堆栈
设置异常向量 初始化C语言运行环 境:设置参数 改变CPU运行模式为用 户模式(User Mode) 运行C程序
15
//内嵌汇编标识
13
本章提要
一 ARM微处理器体系结构 二 ARM 微处理器指令集 三 C语言与汇编语言的混合编程 四 ARM处理器初始化分析
14
应用示例-系统初始化
复位动作
嵌入式实验(汇编和C语言混合编程实验)
嵌入式实验(汇编和C语言混合编程实验)汇编和C语言混合编程实验7.1实验目的①掌握C程序中内嵌指令的使用方法。
②理解汇编程序调用C程序函数和变量的方法。
7.2 实验环境①硬件:PC机②软件:ADS1.27.3 实验内容①使用内嵌汇编的方法设计允许和禁止中断程序。
②验证汇编程序调用C程序函数和访问C程序变量的执行过程。
7.4 实验过程1、实验7-1 允许和禁止中断程序本实验使用内嵌汇编的方法完成允许和禁止中断程序设计,这里使用Armulator 作为调试的目标机。
(1)新建ARM工程exp7_1启动ADS开发环境,选择File→New(Project)选项,使用ARM Executable Image工程模板创建一个工程exp5_1.(2) 新建汇编程序文件exp7_1_1.c,并将其添加到工程exp7_1中选择File→New(File)选项,新建汇编源程序文件exp7_1_1.c并添加到工程exp7_1中,exp7_1_1.c源程序的参考代码如下: #include__inline void enable_IRQ(void) {int tmp;__asm {MRS tmp, CPSRBIC tmp, tmp, #0x80 MSR CPSR_c, tmp } }__inline void disable_IRQ(void) {int tmp; __asm{MRS tmp, CPSR ORR tmp, tmp, #0x80 MSR CPSR_c, tmp } }int main(void) {enable_IRQ( ); disable_IRQ( ); return 0;}(3) 设置工程exp7_1的编译和链接选项选择Edit→DebugRel Settings选项,打开DebugRel Settings对话框,设置工程编译和链接选项,在Language Settings→ARM Assembler选项中,选择Target选项卡,修改处理器类型为ARM920T. (4) 编译和链接工程在工程exp7_1窗口中,选择Make工具按钮,编译和链接工程exp7_1,如果有错误提示,请检查修改程序中的语法错误,直到编译和链接通过。
arm学习笔记五(cc++与arm汇编混合编程)
arm学习笔记五(cc++与arm汇编混合编程)混合编程常见⽅式:1 在c/c++程序中嵌⼊汇编指令语法格式:__asm{汇编语⾔程序}2 在汇编程序中访问c/c++定义的全局变量⽰例代码如下:test.c#include <stdio.h>int gVar_1=12;extern asmDouble(void)int main(void){printf("original value of gVar_1 is %d",gVar_1);admDouble();printf("modified value of gVar_1 is %d",gVar_1);return 0;}test.sAREA asmfile,CODE,READONLYEXPORT asmDouble;声明全局引⽤标号IMPORT gVar_1;引⽤asmDoubleldr r0,=gVar_1ldr r1,[r0]mov r2,#2mul r3,r1,r2str r3,[r0]mov pc,lrEND3 在c/c++程序中调⽤汇编函数⽰例代码如下:test1.sAREA asmfile,COCE,READONLYEXPORT asm_strcpy;声明全局引⽤标号asm_strcpy;函数名loop:ldrb r4,[r0],#1cmp r4,#0beq overstrb r4,[r1],#1b loopover:mov pc,lr;⽤于函数返回ENDtest1.c#include <stdio.h>extern void asm_strcpy(const char *src,char *dest);int main(){const char *s ="hello world";char d[32];asm_strcpy(s,d);printf("source:%s",s);printf("destination: %s",d);return 0;}上⾯程序jni的味道有⽊有?4 汇编程序中调⽤c/c++函数⽰例代码如下:test2.cint cFun(int a,int b,int c){return a+b+c;}test2.sEXPORT asmfileAREA asmfile,CODE,READONLY IMPORT cFun;引⽤函数ENTRY;指定应⽤程序⼊⼝mov r0,#11mov r1,#22mov r2,#33BL cFun;返回END。
ARM汇编语言与C_C_语言混合编程实现方法_王茹
ARM汇编语言与C_C_语言混合编程实现方法_王茹一、ARM汇编语言与C语言编译器在ARM汇编语言与C语言混合编程中,我们需要用到ARM汇编语言编写的程序和C语言编写的程序。
然而,C语言编译器无法直接编译ARM汇编语言,所以我们需要一个汇编编译器将汇编语言转换为机器码。
ARM汇编语言的编译器有很多种,其中常用的有GNU汇编器(gas)和ARM汇编器(armasm)。
GNU汇编器是GNU工具链中的一部分,可以将汇编语言转换为机器码。
ARM汇编器是ARM公司提供的一款汇编编译器,也可以将汇编语言转换为机器码。
我们可以通过在终端中输入命令来使用GNU汇编器将汇编语言编译为机器码,如下所示:```gcc -c assembly.s -o assembly.o```其中,`gcc`是GCC编译器的命令,`-c`参数表示只编译不连接,`assembly.s`是要编译的汇编文件,`-o`参数指定编译输出的目标文件为`assembly.o`。
二、ARM汇编语言与C语言的接口在ARM汇编语言与C语言混合编程中,我们通常需要在汇编语言和C 语言之间传递数据。
为了能够在汇编语言中访问C语言变量,我们需要定义一个接口。
在C语言中,我们可以使用`extern`关键字声明一个C语言变量,以供汇编语言调用。
例如,我们可以在C语言程序中定义一个全局变量`int var`,并使用`extern`关键字声明这个变量,如下所示:```cint var;extern int asm_function(; // 声明汇编语言函数```在汇编语言中,我们可以通过`IMPORT`伪指令引入C语言变量,以供汇编语言使用。
例如,我们可以在汇编语言程序中使用`IMPORT`伪指令引入C语言变量`var`,如下所示:```assemblyIMPORT var```在汇编语言中,我们可以通过`EXPORT`伪指令将汇编语言函数暴露给C语言使用。
例如,我们可以在汇编语言程序中使用`EXPORT`伪指令将汇编语言函数`asm_function`暴露给C语言使用,如下所示:```assemblyEXPORT asm_function```三、ARM汇编语言与C语言的调用汇编语言函数,或者在汇编语言中调用C语言函数。
ARM汇编与C混合编程
ARM汇编与C混合编程内联汇编即在C中直接使用汇编语句进行编程,使程序可以在C程序中实现C语言不能完成的一些工作,例如,在下面几种情况中必须使用内联汇编或嵌入型汇编程序中使用饱和算术运算(Saturating ArithmeTIc)程序需要对协处理器进行操作在C程序中完成对程序状态寄存器的操作__asm__ __volaTIle__("asm code":output:input:changed registers);Note:使用__asm__和__volaTIle__表示编译器将不检查后面的内容,而是直接交给汇编器。
如果希望变压器你优化,__volaTIle__可以不加没有asm code也不能省略""没有前面的和中间的部分,不可以相应的省略:没有changed 部分,必须相应的省略:最后的;不能省略,对于C语言来说这是一条语句汇编代码必须放在一个字符串内,且字符串中间不能直接按回车换行,可以写成多个字符串,注意中间不能有任何符号,这样就会将两个字符串合并为一个指令之间必须要换行,还可以使用\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表示使用立即数。
关于在ARM中(MDK下)C与汇编混合编程的问题
loopLDRBr2,[r0],#1//R0保存第一个参数
STRBr2,[r1],#1//R1保存第二个参数
CMPr2,#0
BNEloop
BLXlr//返回指令须要手动加入
}
intmain(void)
{
constchar*a=“Helloworld!”;
charb[20];
my_strcpy(a,b);
关于在ARM中(MDK下)C与汇编混合编程的问题
于:bbs.21ic/icview-156494-1-1.html([微控制器/MCU]小窍门:Cortex-M3
在MDK C语言中嵌入汇编语言的方法)
==================================
==========================
如果须要访问C程式中的变量,可以使用_cpp关键字,编译器如LDRr0,=__cpp(&some_variable)
LDRr1,=__cpp(some_function)
BL__cpp(some_function)
MOVr0,#__cpp(some_constant_expr)
**********************************
***************************
在传统的ARM处理器中(ARM7/ARM9),如果要在C程式中嵌入汇编,可以有
两种方法:
一、内联汇编的方式方法如下:intPCBsheji(inti)
{
intr0;
__asm
{
ADDr0,i,1
EORi,r0,i
}
returni;
}
在汇编语句可以直接做用C语言中的变量.编译器会对这些代码进一步优化,
ARM汇编语言与嵌入式C混合编程
TM
13
8.2.2按位或操作
按位或操作运算符“|”是把参与运算的两个 操作数对应的各个二进制位进行按位相或。 对应的两个二进制位中只要有一个为1,结果 就为1,当两个对应的二进制位都为0时,结 果位为0。参与运算的两个操作数均以补码形 式出现。
TM
14
14
例如7 | 3,7的补码为0000 0111,3的补码 为0000 0011,结果为0000 0111。按位与操 作可以实现将特定位的置位操作,也可以用 于提取出某数的指定位。
{
...
// 程序代码 B
TM
5
5
8.1.2 命名规则
(1)标识符的名称要简明,能够表达出确切的含义 ,可以使用完整的单词或通常可以理解的缩写。
(2)如果在命名中使用特殊约定或缩写,则要进 行注释说明。
(3)对于变量命名,一般不取单个字符 ,例如i、j 、k...
(4)函数名一般以大写字母开头;所有常量名字 母统一用大写。
优秀的代码还要具备易读性、易维护性、具 有可移植和高可靠性。
TM
3
3
8.1.1 嵌入式C程序书写规范
排版规则如下: (1)程序块要采用缩进风格编写 (2)较长的语句(例如超过80个字符)要分成多行书写 (3)循环、判断等语句中若有较长的表达式或语句,则要
进行适应的划分 (4)若函数或过程中参数较长,也要进行适当的划分。 (5)每行一般只写一条语句 (6)程序块的分界符语句的大括号“{”与“}”一般独占一
TM
6
6
8.1.3 注释说明
注释有助于程序员理解程序的整体结构,也便于以 后程序代码的维护与升级。常用的规则如下:
(1)注释语言必须准确、简洁且容易理解; (2)程序代码源文件头部应进行注释说明 ; (3)函数头部应进行注释; (4)程序中所用到的特定含义的常量、变量,在
基于ARM的C语言与汇编语言混合编程
基于ARM的C语言与汇编语言混合编程2009-07-30 19:12:34| 分类:ARM学习| 标签:|字号大中小订阅1、C语言与汇编语言混合编程应遵守的规则ARM编程中使用的C语言是标准C语言,ARM的开发环境实际上就是嵌入了一个C语言的集成开发环境,只不过这个开发环境与ARM的硬件紧密相关。
在使用C语言时,要用到和汇编语言的混合编程。
若汇编代码较为简洁,则可使用直接内嵌汇编的方法;否则要将汇编程序以文件的形式加入到项目中,按照ATPCS(ARM/Thumb过程调用标准,ARM/Thumb Procedure Call Standard)的规定与C程序相互调用与访问。
在C程序和ARM汇编程序之间相互调用时必须遵守ATPCS规则。
ATPCS规定了一些子程序间调用的基本规则,哪寄存器的使用规则,堆栈的使用规则和参数的传递规则等。
1)寄存器的使用规则子程序之间通过寄存器r0~r3来传递参数,当参数个数多于4个时,使用堆栈来传递参数。
此时r0~r3可记作A1~A4。
在子程序中,使用寄存器r4~r11保存局部变量。
因此当进行子程序调用时要注意对这些寄存器的保存和恢复。
此时r4~r11可记作V1~V8。
寄存器r12用于保存堆栈指针SP,当子程序返回时使用该寄存器出栈,记作IP。
寄存器r13用作堆栈指针,记作SP。
寄存器r14称为链接寄存器,记作LR。
该寄存器用于保存子程序的返回地址。
寄存器r15称为程序计数器,记作PC。
2)堆栈的使用规则ATPCS规定堆栈采用满递减类型(FD,Full Descending),即堆栈通过减小存储器地址而向下增长,堆栈指针指向内含有效数据项的最低地址。
3)参数的传递规则整数参数的前4个使用r0~r3传递,其他参数使用堆栈传递;浮点参数使用编号最小且能够满足需要的一组连续的FP寄存器传递参数。
子程序的返回结果为一个32位整数时,通过r0返回;返回结果为一个64位整数时,通过r0和r1返回;依此类推。
ARM中C语言和汇编语言混合编程_百度文库.
ARM中C语言和汇编语言混合编程在嵌入式系统开发中,目前使用的主要编程语言是C 和汇编,虽然C++已经有相应的编译器,但是现在使用还是比较少的。
在稍大规模的嵌入式程序设计中,大部分的代码都是用C来编写的,主要是因为C语言具有较强的结构性,便于人的理解,并且具有大量的库支持。
但对于一写硬件上的操作,很多地方还是要用到汇编语言,例如硬件系统的初始化中的CPU 状态的设定,中断的使能,主频的设定,RAM控制参数等。
另外在一些对性能非常敏感的代码块,基于汇编与机器码一一对应的关系,这时不能依靠C编译器的生成代码,而要手工编写汇编,从而达到优化的目的。
汇编语言是和CPU的指令集紧密相连的,作为涉及底层的嵌入式系统开发,熟练对应汇编语言的使用也是必须的。
单纯的C或者汇编编程请参考相关的书籍或者手册,这里主要讨论C和汇编的混合编程,包括相互之间的函数调用。
下面分四种情况来进行讨论,不涉及C++语言。
一、在C语言中内嵌汇编在C中内嵌的汇编指令包含大部分的ARM和Thumb指令,不过使用与单纯的汇编程序使用的指令略有不同,存在一些限制,主要有下面几个方面:a 不能直接向PC 寄存器赋值,程序跳转要使用B或者BL指令;b 在使用物理寄存器时,不要使用过于复杂的C表达式,避免物理寄存器冲突;c R12和R13可能被编译器用来存放中间编译结果,计算表达式值时可能把R0-R3、R12及R14用于子程序调用,因此避免直接使用这些物理寄存器;d 一般不要直接指定物理寄存器;e 让编译器进行分配内嵌汇编使用的标记是__asm或asm关键字,用法如下:__asm{instruction [; instruction]}或 asm("instruction[; instruction]"。
下面是一个例子来说明如何在C中内嵌汇编语言://C语言文件*.c /procatlaw/#includevoid my_strcpy(const char *src, char *dest{char ch;__asm{loop:ldrb ch, [src], #1strb ch, [dest], #1cmp ch, #0bne 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语言和汇编之间的值传递是用C语言的指针来实现的,因为指针对应的是地址,所以汇编中也可以访问。
C 和 ARM 汇编混合编程实验报告
实验四 C 和 ARM 汇编混合编程实验一实验目的1. 熟悉ADS 开发环境、AXD 及Multi_ICE 调试环境。
2. 掌握简单的ARM 汇编指令的使用方法。
3. 掌握S3C2410A 的I/O 控制寄存器的配置。
4. 掌握ARM 汇编指令和C 语言相互调用的方法二实验设备PC 机、ARM 仿真器、2410 实验箱、串口线。
三实验内容1. 熟悉ARM 开发环境的建立。
2. 使用ARM 汇编和C 语言设置 GPIO口的相应寄存器。
四实验原理1. C 程序与汇编程序相互调用规则为了使单独编译的 C语言程序和汇编程序之间能够相互调用,必须为子程序间的调用规定一定的规则。
ATPCS即ARM, Thumb过程调用标准(ARM/Thumb Procedure Call Standard),是 ARM程序和 Thumb程序中子程序调用的基本规则,它规定了一些子程序间调用的基本规则,如子程序调用过程中的寄存器的使用规则,堆栈的使用规则,参数的传递规则等。
下面结合实际介绍几种ATPCS 规则,如果读者想了解更多的规则,可以查看相关的书籍。
(1)基本ATPCS基本 ATPCS 规定了在子程序调用时的一些基本规则,包括下面 3方面的内容:①各寄存器的使用规则及其相应的名称。
②数据栈的使用规则。
③参数传递的规则。
相对于其它类型的 ATPCS,满足基本 ATPCS的程序的执行速度更快,所占用的内存更少。
但是它不能提供以下的支持: ARM 程序和 Thumb程序相互调用,数据以及代码的位置无关的支持,子程序的可重入性,数据栈检查的支持。
而派生的其他几种特定的ATPCS 就是在基本ATPCS 的基础上再添加其他的规则而形成的。
其目的就是提供上述的功能。
2.寄存器的使用规则寄存器的使用必须满足下面的规则:(1) 子程序间通过寄存器 R0~R3来传递参数。
这时,寄存器 R0~R3可以记作 A0~A3。
被调用的子程序在返回前无需恢复寄存器 R0~R3的内容。
C语言与ARM汇编的混合编程
ATPCS概述 9.1 ATPCS概述
3. 参数传递规则
根据参数个数是否固定,可以将子程序分为参数个数固定的 (nonvariadic)子程序和参数个数可变的(variadic)子程序。ATPCS为 这两种子程序规定了不同的参数传递规则。 参数个数可变的子程序参数传递规则 对于参数个数可变的子程序,当参数不超过4个时,可以使用寄存器 R0~R3来传递参数;当参数超过4个时,还可以使用数据栈来传递参数。 在传递参数时,将所有参数看做是存放在连续的内存单元中的字数据。 然后依次将各名字数据传送到寄存器R0、R1、R2、R3中,如果参数多于 4个,将剩余的字数据传送到数据栈中,入栈时低地址优先,即入栈的顺 序与参数顺序相反,最后一个字数据先入栈。 参数个数固定的子程序参数传递规则 参数个数固定的子程序的参数传递规则为:第一个整数参数按序分配给 R0~R3寄存器,剩余的参数按序分配给堆栈。
从汇编代码中访问C 9.3 从汇编代码中访问C程序全局变量
在ARM汇编代码中只能通过地址间接地访问C程序的全局变量。具体访问方法 是先用IMPORT伪操作声明该全局变量,然后用LDR伪指令将该全局变量的地址 读到一个寄存器中,最后根据变量类型用相应的LDR指令读取该变量的值,用相 应的STR指令修改该变量的值。 对无符号变量用以下对应指令: char类型用LDRB/STRB指令; short类型用LDRH/STRH指令; int类型用LDR/STR指令; 注意,这里是指ARM C(armcc编译器),short类型为16位,int类型为32位, 与标准C有所不同。 对于带符号的变量,则用等价的带符号数操作指令,如LDRSB/LDRSH等。 对于小于8个字的结构性变量,可以通过一条LDM/STM指令来读/写整个变量; 对于结构变量的数据成员,可以使用相应的LDR/STR指令来访问,但必须知道该 结构成员相对于结构变量开始地址的偏移量。
arm实验ARM汇编和C语言混合编程
辽宁工程技术大学上机实验报告实验分析1.ARM汇编程序访问C变量程序代码:test1.spreserve8area reset,code,readonlyentrycode32export armcodeimport globvar armcode ldr r1,=globvarldr r0,[r1]add r0,r0,#2str r0,[r1]mov pc,lrendtest2.c#include<stdio.h>int globvar=3;int _main(){return (0);}实验截图:实验分析续分析:在0x8018的位置上实现了3+2。
2.汇编程序调用C程序程序代码:test3.sarea reset,code,readonlyentrycode32export reset;arm_addimport gldr sp,=0x31000100str lr,[sp,#-4]!mov r0,#20mov r1,#1mov r2,#2mov r3,#3mov r4,#4str r4,[sp,#-4]!bl gadd sp,sp,#4ldr pc,[sp],#4endtest4.c#include<stdio.h>int g(int a,int b,int c,int d,int e){return a-b-c-d-e;}实验分析续运行结果截图:实验分析:在ARM汇编语言程序中,将5个数分别存入寄存器中,然后通过调用C语言程序,进行相减,最后将结果存到R0中。
3.C程序调用ARM汇编程序程序代码:test5.sarea SCopy,code,readonlyentryexport strcopystrcopyldrb r2,[r1],#1strb r2,[r0],#1cmp r2,#0bne strcopymov pc,lrendtest6.c#include<stdio.h>extern void strcopy(char * d,const char * s);int main(void){ const char * srcstr="First string-souce";char dststr[]="Second string-destination";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);}运行截图:由于自己的疏忽,截完图之后,没有保存到优盘,但是程序一定能运行,而且结果也能出来。
ARM汇编语言和C_C_语言混合编程的方法
ret urn a + b + c + d + e + f ;
嵌入式技术
电 子 测 量 技 术 EL EC TRON IC M EASU R EM EN T TEC HNOLO GY
第 29 卷 第 6 期 2006 年 12 月
ARM 汇编语言和 C/ C + + 语言混合编程的方法
史斌
(天津大学电子信息工程学院 天津 300072)
摘 要 : 文中首先对在嵌入式系统设计中广泛应用的 ARM 系列微处理器做了简要介绍 ;接着详细阐述了基于 ARM 核的嵌入式微处理器的汇编语言和 C/ C + + 语言混合编程的方法 :包括代码简洁而功能有限的在线汇编技术和功能 强大 、基于模块化设计的 A TPCS 规则 ;最后给出了详细的示例代码和分析 。 关键词 : 嵌入式系统 ; A RM ; 汇编语言 ; 在线汇编 ; A TPCS 规则
} 因为 CPSR 是一个物理寄存器 ,没有存储器的 I/ O 映 射 ,而 A RM 的 C/ C + + 语言使用的是 ANSI 标准 ,不像 KeilC51 那样有诸如 sbit 和 sf r 的扩展 ,所以访问 CPSR 的 唯一方法就是用汇编语言 ;通过在 C/ C + + 代码中插入一 段简短的汇编代码 ,来实现对 CPSR 的访问 。再比如一些 波形发生的场合 , 需要每隔一段精确的时间向端口送数 据 ,那么 C/ C + + 代码经编译后产生的指令数是无法预知 的 ,所以无法实现精确定时 ,因此就要使用在线汇编 。 在线汇编通过__asm 关键字实现 ,一般格式为 : ……/ / C/ C + + 代码
ARM汇编语言与C语言混合编程的实现方法
※吉 首 大 学 校 级 课 题— ——编 号 08JDY028,名 称 :体 育 信 息 的 组 织及民族传统体育信息共享共建平台的构建。
[责任编辑:汤静]
●
(上接第 418 页)族地区的特殊性出发,以琼州大学为大学与中学合作 的龙头,进行实证研究。 以期为具有民族特色的海南省师范院校学生 职前实习模式的建构提供新思路;其次,为琼州大学外语系英语教育 方向毕业生职前实习的开展提供新的契机;第三,为海南省全面推进 新课程改革提供新的切入点。 科
{
int ch;
__asm
{
loop:
LDRB ch, [src], #1
STRB ch, [dst], #1
CMP
ch, #0
BNE
loop
}
}
调用 my_strcpy()的 C 语言代码如下:
int main()
{
char *a = "Happy New Year! ";
char b[64];
my_strcpy(a, b);
作 者 简 介 :王 应 军 (1979— ), 男 ,河 南 禹 州 人 ,硕 士 ,讲 师 ,主 要 从 事 模 式 识 别 及图像处理技术的研究。
※基 金 项 目 :河 南 科 技 学 院 校 选 项 目 基 金 资 助 (06060 ,06055 )。
[责任编辑:王静]
● ●
●
(上接第 410 页)
printf("original string: ‘%ed string: ‘%s’\n", b);
return (0);
}
在这里 C 和汇编之间的值传递是用 C 的指针来实现的, 因为指
arm:c语言和汇编混合编程
arm:c语⾔和汇编混合编程仅作演⽰。
本⽂演⽰了:汇编嵌⼊到c语⾔; 汇编调⽤c语⾔,c语⾔调⽤汇编。
2.C函数参数从左到右是放到r0-r3,[不够再push stack];push stack⽤stmfd ldmfd,右边的参数会先⼊栈。
;//call_asm.sPRESERVE8AREA |C$$code|, CODE, READONLY ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IMPORT cfunc_printIMPORT c_addIMPORT c_subEXPORT AsmCallerAddEXPORT AsmCallerSubEXPORT AsmCallerPrintEXPORT slib_ReadCpuStatusAsmCallerAdd ; ,执⾏⼦函数TestFunc6(1,2)sub r13, r13, #4 ;sp-=4str r14, [r13] ;sp--->lrbl c_add ;BL : r0,r1中的参数传到⼦函数ldr r14, [r13] ;lr--->spadd r13, r13, #4 ;sp+=4bx r14 ;goto spAsmCallerSubmov ip, spstmfd sp!, {fp, ip, lr, pc}sub fp, ip, #4bl c_subldmfd sp, {fp, sp, pc} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AsmCallerPrintsub r13, r13, #4 ;sp -= 4str r14, [r13] ;sp ---> lrbl cfunc_print ;ldr r14, [r13] ;lr ---> spadd r13, r13, #4 ;sp += 4bx r14 ;goto spslib_ReadCpuStatusmov ip, spstmfd sp!, {fp, ip, lr, pc}sub fp, ip, #4mrs r0,cpsrldmfd sp, {fp, sp, pc}END//asm_c.c/*根据“ARM-thumb 过程调⽤标准”:r0-r3 ⽤作传⼊函数参数,传出函数返回值。
ARM汇编语言和C语言混合编程
ARM汇编语言和C语言混合编程一. 在线汇编( in-line assembly)在C代码中插入一段汇编代码,比如while(1){...port=0x00aa55ff;__asm{mov r4,portstr r5,[r4]}...}具体格式为__asm{指令1;指令2;指令3;...指令n;指令n+1;......}其中指令的操作数可以是物理寄存器,也可以是C语言的变量、行号和表达式,这点是比纯汇编最大的的好处(窃以为如斯,比如上面的例子)说到这其实写在线汇编代码的思路就和纯汇编差不多了,但要注意几个问题:1.不能直接向PC赋值实现程序跳转,只能使用B和BL这两条指令2.在线汇编器会使用R0-R3,R12-R13计算表达式,因此复杂的表达式不能和以上寄存器出现在同一条指令中:mov r0,一个复杂的表达式 ----汇编器可能报错mov r5,一个复杂的表达式 ----汇编可以通过3.在线汇编中使用物理寄存器时,如果上下文的C代码也使用了同一个,则不必自己保存和恢复该物理寄存器,C代码会自己负责处理4.尽量不使用物理寄存器,因为a.影响代码效率,很有可能编译器为此把一个本应放在寄存器中的变量放在存储器中.就如同在C中定义局部变量哪个是register的,哪个是volatile的,编译器自己的优化才是最佳的。
b.发生错误:比如...mov r0,#0xaamov r1,x%ymov r2,r0...很可能r2的值不是0xaa,因为在计算表达式x%y时会用到r0,将r0的内容冲掉5.可以使用b指令b 标号; 实现跳转,标号可以时C的也可以是汇编的6.因为要计算表达式的值,所以一条虚拟指令要被展开为若干条真实指令(如上面的mov r1,x%y)因此实际上对标志为C.N.V.Z的影响是展开后最后一条作用的结果,但如果总指令(就是你程序中写的那条虚拟指令)是算术指令,那么能正确设置cv nz, 如果是逻辑指令,那么N.z是正确的,V不影响,C不可靠7.不支持除nop之外的其它伪指令(ADR,ADRL,LDR)8.不支持BX和BLX指令9.LDM和STM指令的寄存器列表只允许物理寄存器,不能用变量和表达式10.逗号表达式要用一个括号扩起来,使其为一个整体add x,y,(f(),z)11.不要干预堆栈当然还有更复杂的规则,比如子程序调用(BL指令),但我觉得过于繁琐,失去了在线汇编这种简便快捷的风格,如果以上介绍的不能满足你的要求,我建议使用A TPCS规则。
ARM汇编语言与嵌入式C混合编程
18
应用举例:
例:通过3次异或操作将寄存器rPDATAE中的内容与变量tmp 的值进行交换。
rPDATAE = rPDATAE ^ tmp tmp = tmp ^ rPDATAE rPDATAE = rPDATAE ^ tmp
假定rPDATAE的初始值为0x12345678,tmp的初始值为0x56781234
按位异或运算符“^”是将参与运算的两个操 作数对应的各个二进制位进行相异或,当对 应的两个二进制位相异时,结果位为1,相同 时为0。参与运算的两个操作数均以补码形式 出现。
TM
17
17
例如7 | 3,7的补码为0000 0111,3的补码 为0000 0011,结果为0000 0100。
TM
18
} else { … //代码B
中断服务程序 void ISR_INT1(void) {
flg=1; }
} } }
解决方法:将 static char flg=0 改为 volatile static char flg=0
TM
28
8.3.2 地址强制转换与多级指针
1、地址强制转换 在C程序设计中,绝对地址0x0FA00只是被
TM
1
内容提要
8.1 8.2 8.3 8.4 8.5 8.6
嵌入式C编程规范 嵌入式C程序设计中的位运算 嵌入式C程序设计中的几点说明 嵌入式C程序设计格式 过程调用标准ATPCS与AAPCS ARM汇编语言与嵌入式C混合编程
TM
2
2
8.1 嵌入式C编程规范
在当前的嵌入式开发中,嵌入式C语言是最 为常见的程序设计语言,对于程序员来说, 能够完成相应功能的代码并不一定是优秀的 代码。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
昆明理工大学信息工程与自动化学院学生实验报告(2011 —2012 学年第 1 学期)课程名称:ARM嵌入式系统结构开课实验室:信自楼443 2012 年12月27日一、实验目的●掌握建立基本完整的ARM工程,包含启动代码,连接脚本等;●阅读Embest S3CEV40启动代码,观察处理器启动过程;●学会使用Embest IDE 辅助信息窗口来分析判断调试过程和结果;●学会在Embest IDE环境中编写、编译与调试汇编和C语言相互调用的程序。
●掌握通过memory/register/watch/variable窗口分析判断结果。
二、实验原理1. ARM异常向量表当正常的程序执行流程挂起时,称之为异常。
在处理异常之前,必须保存当前的处理器状态,以便从异常程序返回时可以继续执行当前的程序。
ARM异常向量表如表2-2所示。
由上可见,复位(Reset)入口是整个程序的实际入口点。
因此,编写代码时,第一条语句在0x00000000处开始执行。
2. ARM过程调用ATPCS(ARM)ATPCS是一系列用于规定应用程序之间相互调用的基本规则。
程序只要遵守ATPCS相应规则,就可以使用不同的源代码来编写程序。
程序间的相互调用最主要的是解决参数传递问题。
应用程序之间使用中间寄存器及数据栈来传递参数,其中第1~4个参数使用R0~R3,多于4个参数的则使用数据栈进行传递。
用不同语言编写的应用程序在调用时可以自定义参数传递的约定。
使用具有一定意义的形式来传递,可以很好地解决参数个数问题。
常用方法是把第1个或最后1个参数(包括个数本身)传递给应用程序。
ATPCS中寄存器的对应关系如表2-3所列。
表2-3 ATPCS规则中寄存器列表3. 链接脚本文件所有的链接都是通过链接脚本来控制实现的。
这些链接脚本文件使用链接命令语言编写。
链接脚本的最主要作用是描述我们编写的文件中这么多个部分应该如何的相应摆放在输出文件中,并控制存储区如何定位这些输出文件。
同时,如果需要,我们还可以使用链接脚本文件实现其它功能。
大部分链接脚本文件都是很简单的。
最简单的链接脚本只有一行命令:SECTIONS。
使用SECTIONS命令来告诉存储区应该如何摆放输出文件。
4.Embest IDE开发调试辅助窗口使用Embest IDE嵌入式开发环境,用户可以使用源代码编辑窗口编写源文件程序。
使用反汇编窗口观察程序代码的执行,使用Register窗口观察程序操作及CPU状态,使用外围寄存器窗口观察当前处理器的设置,使用Memory窗口观察内存单元使用情况,使用Watch 或Variables窗口观察程序变量,使用操作控制台执行特殊命令。
加上调试状态下丰富的右键快捷菜单功能,用户可以使用IDE实现或发现任何一部分应用软件,修改任何一个开发或运行时的错误。
三、实验内容1. 使用汇编完成一个随机数产生函数,通过C语言调用该函数,产生一系列随机数,存放到数组里面。
2. 下面是ARM的启动文件init.s及链接脚本文件ldscript的参考程序:参考程序init.s:#.arm.global _start.text_start:# 设置中断/异常向量B Reset_HandlerUndefined_Handler: B Undefined_HandlerSWI_Handler: B SWI_HandlerPrefetch_Handler: B Prefetch_HandlerAbort_Handler: B Abort_HandlerNOPIRQ_Handler: B IRQ_HandlerFIQ_Handler: B FIQ_HandlerReset_Handler: LDR sp, =0x00002000#----------------------------------------------------------------#- Branch on C code Main function (with interworking)#- Branch must be performed by an interworking call as either an ARM or Thumb #- main C function must be supported. This makes the code not position-#- independant. A Branch with link would generate errors#----------------------------------------------------------------.extern __mainldr r0, = __mainmov lr, pcbx r0#----------------------------------------------------------------#- Loop for ever#- End of application. Normally, never occur.#- Could jump on Software Reset ( B 0x0 ).#----------------------------------------------------------------End: B End.end链接脚本文件ldscript:SECTIONS{. = 0x0;.text : { *(.text) }.data : { *(.data) }.rodata : { *(.rodata) }.bss : { *(.bss) }}四、实验步骤:1.创建新的工程,工程名为:explasm;2.编写源代码文件并分别保存为randtest.c,init.s,random.s和ldscript,并加入工程里;3.按照编译、汇编器配置->链接器配置->调试器配置设置新工程;并编译链接工程;4.选择Debug菜单Remote Connect 进行连接软件仿真器,执行Download命令下载程序,并打开寄存器窗口。
5.下载调试文件,打开memory/register/watch/variable/call stack窗口,单步执行程序,并通过以上窗口,跟踪程序运行,观察分析运行结果,通过实验学会使用Embest IDE进行应用程序的开发与调试。
/********************************* Init.s*****************************/# *******************************************************# * NAME : 44BINIT.S *# * Version : 10.April.2000 *# * Description: *# * C start up codes *# * Configure memory, Initialize ISR ,stacks *# * Initialize C-variables *# * Fill zeros into zero-initialized C-variables *# *******************************************************#程序入口,arm汇编#.arm.global _start.text_start:# --- Setup interrupt / exception vectorsB Reset_HandlerUndefined_Handler:B Undefined_HandlerSWI_Handler:B SWI_HandlerPrefetch_Handler:B Prefetch_HandlerAbort_Handler:B Abort_HandlerNOP /* Reserved vector */IRQ_Handler:B IRQ_HandlerFIQ_Handler:B FIQ_HandlerReset_Handler:LDR sp, =0x00002000#------------------------------------------------------------------------------ #- Branch on C code Main function (with interworking)#----------------------------------------------------#- Branch must be performed by an interworking call as either an ARM or Thumb #- main C function must be supported. This makes the code not position-#- independant. A Branch with link would generate errors#------------------------------------------------------------------------------ .extern mainldr r0, = mainmov lr, pcbx r0#------------------------------------------------------------------------------ #- Loop for ever#---------------#- End of application. Normally, never occur.#- Could jump on Software Reset ( B 0x0 ).#------------------------------------------------------------------------------ End:b End.global __gccmain__gccmain:mov pc, lr.end/***********************************Ldscript*****************************/ SECTIONS{. = 0x0;.text : { *(.text) }.data : { *(.data) }.rodata : { *(.rodata) }.bss : { *(.bss) }}/***********************************random.s*****************************/ # Random number generator## This uses a 33-bit feedback shift register to generate a pseudo-randomly # ordered sequence of numbers which repeats in a cycle of length 2^33 - 1 # NOTE: randomseed should not be set to 0, otherwise a zero will be generated # continuously (not particularly random!).## This is a good application of direct ARM assembler, because the 33-bit# shift register can be implemented using RRX (which uses reg + carry).# An ANSI C version would be less efficient as the compiler would not use RRX.# AREA |Random$$code|, CODE, READONLY.GLOBAL randomnumberrandomnumber:# on exit:# a1 = low 32-bits of pseudo-random number# a2 = high bit (if you want to know it)LDR ip, seedpointerLDMIA ip, {a1, a2}TST a2, a2, LSR#1 /* to bit into carry */MOVS a3, a1, RRX /* 33-bit rotate right */ADC a2, a2, a2 /* carry into LSB of a2 */EOR a3, a3, a1, LSL#12 /* (involved!) */EOR a1, a3, a3, LSR#20 /* (similarly involved!)*/STMIA ip, {a1, a2}MOV pc, lrseedpointer:.LONG seed.DATA.GLOBAL seedseed:.LONG 0x55555555.LONG 0x55555555# END/*********************************randtest.c*****************************/ /* Random number generator demo programCalls assembler function 'randomnumber' defined in random.s*///#include <stdio.h>/* this function prototype is needed because 'randomnumber' is external */ extern unsigned int randomnumber( void );int main(){int i;int nTemp;unsigned int random[10];for( i = 0; i < 10; i++ ){nTemp = randomnumber();random[i] = nTemp;}return( 0 );}五、思考题:从汇编语言中调用C函数:使用C语言完成一个随机数产生函数,通过汇编语言调用该函数,产生一系列随机数,存放到数组里面。