嵌入式简单汇编程序实例
gcc内嵌汇编详解
gcc内嵌汇编详解有时候我们希望在C/C++代码中使⽤嵌⼊式汇编,因为C中没有对应的函数或语法可⽤。
⽐如我最近在ARM上写FIR程序时,需要对最后的结果进⾏饱和处理,但gcc没有提供ssat这样的函数,于是不得不在C代码中嵌⼊汇编指令。
1. ⼊门在C中嵌⼊汇编的最⼤问题是如何将C语⾔变量与指令操作数相关联。
当然,gcc都帮我们想好了。
下⾯是是⼀个简单例⼦。
asm(“fsinx %1, %0”:”=f”(result):”f”(angle));这⾥我们不需要关注fsinx指令是⼲啥的;只需要知道这条指令需要两个浮点寄存器作为操作数。
作为专职处理C语⾔的gcc编译器,它是没办法知道fsinx这条汇编指令需要什么样的操作数的,这就要求程序猿告知gcc相关信息,⽅法就是指令后⾯的”=f”和”f”,表⽰这是两个浮点寄存器操作数。
这被称为操作数规则(constraint)。
规则前⾯加上”=”表⽰这是⼀个输出操作数,否则是输⼊操作数。
constraint后⾯括号内的是与该寄存器关联的变量。
这样gcc就知道如何将这条嵌⼊式汇编语句转成实际的汇编指令了:fsinx:汇编指令名%1, %0:汇编指令操作数“=f”(result):操作数%0是⼀个浮点寄存器,与变量result关联(对输出操作数,“关联”的意思就是说gcc执⾏完这条汇编指令后会把寄存器%0的内容送到变量result中)“f”(angle):操作数%1是⼀个浮点寄存器,与变量angle关联(对输⼊操作数,“关联”的意思是就是说gcc执⾏这条汇编指令前会先将变量angle的值读取到寄存器%1中)因此这条嵌⼊式汇编会转换为⾄少三条汇编指令(⾮优化):1> 将angle变量的值加载到寄存器%12> fsinx汇编指令,源寄存器%1,⽬标寄存器%03> 将寄存器%0的值存储到变量result当然,在⾼优化级别下上⾯的叙述可能不适⽤;⽐如源操作数可能本来就已经在某个浮点寄存器中了。
嵌入式实验(汇编和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,如果有错误提示,请检查修改程序中的语法错误,直到编译和链接通过。
嵌入式汇编语言程序设计.
1.2.3 ARM汇编语言子程序调用
1.2 ARM汇编语言程序格式
1.2.1ARM汇编语言文件格式
1.2 ARM汇编语言程序格式
1.2.2ARM汇编语言程序格式
源文件的组织方式-----段 段的定义-----相对独立的,具有特定名称的,不可分割的指令或者数据序列
段的分类----代码段,数据段
1.2 ARM汇编语言程序格式
1.1.3 ARM汇编语言中的表达式
1.1 ARM汇编语言语句格式
1.1.3 ARM汇编语言中的表达式
表达式的组成 表达式中各元素的优先级
1.1 ARM汇编语言语句格式
1.1.3 ARM汇编语言中的表达式
1.1 ARM汇编语言语句格式
1.1.3 ARM汇编语言中的表达式
1.1 ARM汇编语言语句格式
1.3 ARM汇编语言程序设计举例
伪操作实例
1.3 ARM汇编语言程序设计举例
伪操作实例
字符串变量:Jaldjflj
aljfjlfj
1.3 言中的符号—变量:
变量替换
1.1 ARM汇编语言语句格式
1.1.2ARM汇编语言中的符号—变量:
变量替换
1.1 ARM汇编语言语句格式
1.1.2ARM汇编语言中的符号—数字常量:
数字常量的取值范围
数字常量的声明与赋值
1.1 ARM汇编语言语句格式
1.1.2ARM汇编语言中的符号—标号:
1.1 ARM汇编语言语句格式
9、 FILED
使用示例: MAP 0x100 ; 定义结构化内存表首地址的值为0x100。 A FIELD 16 ; 定义A的长度为16字节,位置为0x100 B FIELD 32 ; 定义B的长度为32字节,位置为0x110 S FIELD 256 ;定义S的长度为256字节,位置为0x130
嵌入式汇编
本节是第一次在内核源程序中接触到C语言中的嵌入式汇编代码。
由于我们在通常的C语言程序的编制过程中一般是不会使用嵌入式汇编程序的,因此这里有必要对其基本格式进行简单的描述,详细的说明可参见GNU gcc手册中[5]第4章的内容(Extensions to the C Language Family),或见参考文献[20](Using Inline Assembly with gcc)。
具有输入和输出参数的嵌入汇编的基本格式为:asm(“汇编语句”: 输出寄存器: 输入寄存器: 会被修改的寄存器);其中,“汇编语句”是你写汇编指令的地方;“输出寄存器”表示当这段嵌入汇编执行完之后,哪些寄存器用于存放输出数据。
此地,这些寄存器会分别对应一C 语言表达式或一个内存地址;“输入寄存器”表示在开始执行汇编代码时,这里指定的一些寄存器中应存放的输入值,它们也分别对应着一C变量或常数值。
下面我们用例子来说明嵌入汇编语句的使用方法。
我们在下面列出了前面代码中第22行开始的一段代码作为例子来详细解说,为了能看清楚我们将这段代码进行了重新编排和编号。
01 #define get_seg_byte(seg,addr) \02 ({ \03 register char __res; \04 __asm__("push %%fs; \05 mov %%ax,%%fs; \06 movb %%fs:%2,%%al; \07 pop %%fs" \08 :"=a" (__res) \09 :"" (seg),"m" (*(addr))); \10 __res;})这段10行代码定义了一个嵌入汇编语言宏函数。
因为是宏语句,需要在一行上定义,因此这里使用反斜杠'\'将这些语句连成一行。
这条宏定义将被替换到宏名称在程序中被引用的地方。
第1行定义了宏的名称,也即是宏函数名称get_seg_byte(seg,addr)。
单片机汇编语言设计实例详解
单片机汇编语言设计实例详解引言:单片机是嵌入式系统中常见的控制器,它具有体积小、功耗低、成本低等特点,被广泛应用于家电、汽车、工业控制等领域。
而汇编语言作为单片机的底层语言,直接操作硬件资源,具有高效性和灵活性。
本文将以一个实例,详细讲解如何使用单片机汇编语言进行设计。
实例背景:假设我们要设计一个温度检测系统,要求实时监测环境温度,并在温度超过某个阈值时触发报警。
硬件准备:1. 单片机:我们选择一款常用的8051单片机作为例子。
2. 温度传感器:我们选择一款数字温度传感器,它可以通过串行通信与单片机进行数据交互。
3. 显示屏:为了方便实时显示温度信息,我们选用一款数码管显示屏。
软件准备:1. Keil C51:这是一款常用的单片机开发软件,支持汇编语言的编写和调试。
2. 串口调试助手:用于测试串口通信功能。
设计步骤:1. 硬件连接:将单片机与温度传感器、显示屏连接起来。
注意接线的正确性和稳定性。
2. 编写初始化程序:使用汇编语言编写单片机的初始化程序,包括端口初始化、中断向量表设置、定时器初始化等。
3. 串口通信设置:通过串口与温度传感器进行数据交互,需要设置串口通信的波特率、数据位数、停止位等参数。
4. 温度检测程序:编写汇编语言程序,实时读取温度传感器的数据,并将数据送至显示屏进行显示。
5. 温度报警程序:在温度超过设定阈值时,触发报警程序,可以通过蜂鸣器等外设发出警报信号。
6. 调试与测试:使用Keil C51进行程序调试,通过串口调试助手测试串口通信和温度显示、报警功能。
设计思路:1. 初始化程序设计:先设置端口的输入输出方向,再设置中断向量表,最后初始化定时器。
这样可以确保程序的稳定性和可靠性。
2. 串口通信设置:根据温度传感器的通信协议,设置串口的波特率、数据位数、停止位等参数。
注意要与传感器的通信规范保持一致。
3. 温度检测程序设计:通过串口读取温度传感器的数据,并进行相应的处理。
常见的嵌入式编程案列
常见的嵌入式编程案列
【1】用#define声明一个常数,用以表示一年中有多少秒
#define SECONDS_PER_YEAR (60*60*24*365)UL
说明:首先,末尾#define语法末尾不能有分号;
其次,计算式最好带括号;
第三,这个表达式会使16位机的整型数溢出,因此需要用长整型符号L告诉编译器这个常数是长整型数,末尾用UL(无符号长整型)。
【2】用C编写死循环
第一种方案:while(1){}
第二种方案:for(;;){}
第三种方案:Loop:
goto Loop; //这种方案是用汇编写的
【3】访问特定内存位置:
在某工程中,一个整型变量的绝对地址是0x67a9,请将其设置为0xaa55,并且已知编译器是一个纯粹的ANSI编译器,请编写代码
int* ptr;
ptr=(int*)0x67a9;
*ptr=0xaa55;
【4】对中断服务代码的评论
以上程序有如下几个错误:
1、ISR不能返回一个值;
2、ISR不能传递参数,即不能有形参;
3、在许多处理器或编译器中,浮点数一般是不可重入的。
有些处理器或编译器需要使用额外的寄存器入栈,有些处理器或编译器是不允许在ISR中做浮点运算。
此外,ISR应该。
Gcc嵌入式汇编
2.6.3 Gcc嵌入式汇编在Linux的源代码中,有很多C语言的函数中嵌入一段汇编语言程序段,这就是gcc提供的“asm”功能,例如在include/asm-i386/system.h中定义的,读控制寄存器CR0的一个宏read_cr0():#define read_cr0() ({ \unsigned int __dummy; \__asm__( \"movl %%cr0,%0\n\t" \:"=r" (__dummy)); \__dummy; \})这种形式看起来比较陌生,这是因为这不是标准C所定义的形式,而是gcc 对C语言的扩充。
其中__dummy为C函数所定义的变量;关键词__asm__表示汇编代码的开始。
括弧中第一个引号中为汇编指令movl,紧接着有一个冒号,这种形式阅读起来比较复杂。
一般而言,嵌入式汇编语言片段比单纯的汇编语言代码要复杂得多,因为这里存在怎样分配和使用寄存器,以及把C代码中的变量应该存放在哪个寄存器中。
为了达到这个目的,就必须对一般的C语言进行扩充,增加对编译器的指导作用,因此,嵌入式汇编看起来晦涩而难以读懂。
1. 嵌入式汇编的一般形式:__asm__ __volatile__ ("<asm routine>" : output : input : modify);其中,__asm__表示汇编代码的开始,其后可以跟__volatile__(这是可选项),其含义是避免“asm”指令被删除、移动或组合;然后就是小括弧,括弧中的内容是我们介绍的重点:·"<asm routine>"为汇编指令部分,例如,"movl %%cr0,%0\n\t"。
数字前加前缀“%“,如%1,%2等表示使用寄存器的样板操作数。
可以使用的操作数总数取决于具体CPU 中通用寄存器的数量,如Intel可以有8个。
实验二 ARM嵌入式系统应用 汇编语言编程一
实验二
实验项目名称:ARM处理器寻址方式:
实验目的和要求:对ARM处理器的六种寻址方式进行练习。
实验原理:根据不同寻址方式,运行ARM指令,观察运行结果。
主要仪器设备:台式计算机、windows操作系统、应用软件等。
实验方法与步骤:1、根据6种寻址方式,输入ARM指令。
2、运行软件例程,观察结果。
实验数据记录、处理及结果分析:
寄存器寻址方式(P37---P40 每种寻址方式写出一条指令即可)
1、寄存器寻址:
2、立即寻址:
3、寄存器间接寻址:
4、变址寻址:
5、寄存器移位寻址:
6、多寄存器寻址:
综合练习:
(P43 指令示例运行结果观察:共8条指令选4条指令)
LDR R3, [R4] ;写出目标寄存器中的结果,如R3=0x?
…….
LDR R3, [R1], R2, LSL #3。
c 内嵌汇编格式
c 内嵌汇编格式在C语言中,可以使用内嵌汇编(Inline Assembly)来直接在C 代码中插入汇编代码。
内嵌汇编的格式如下:c复制代码asm (汇编语句);其中,汇编语句是你要插入的汇编代码。
例如,以下是一个简单的内嵌汇编示例,用于将一个整数变量x 的值加1:c复制代码int x = 5;asm ("addl $1, %0" : "=r"(x) :"0"(x));在这个示例中,addl $1, %0是一条汇编指令,用于将%0所指向的寄存器中的值加1。
: "=r"(x)表示将x的值存储到一个通用寄存器中,"0"(x)表示将x的值作为输入。
需要注意的是,内嵌汇编的语法和格式可能会因编译器和目标架构的不同而有所差异。
因此,在使用内嵌汇编时,需要仔细阅读你所使用的编译器的文档,并确保你的汇编代码与目标架构兼容。
在使用内嵌汇编时,需要注意以下几个方面:1.寄存器的使用:内嵌汇编允许你在代码中直接操作寄存器,因此需要了解目标架构中可用的寄存器以及它们的用途。
在某些架构中,寄存器的名称和数量可能因编译器或目标架构的不同而有所差异。
2.操作数的类型和大小:在汇编语言中,操作数的类型和大小是非常重要的。
例如,加法指令在不同的数据类型上可能有不同的行为。
因此,你需要确保你的汇编代码与C语言代码中的数据类型和大小相匹配。
3.内存操作数的使用:如果你在内嵌汇编中需要操作内存中的数据,需要使用操作数来指定内存地址。
在这种情况下,你需要确保内存地址是有效的,并且确保你的汇编代码不会导致访问违规或段错误等问题。
4.输入和输出操作数的约束:在内嵌汇编中,你需要使用约束来指定输入和输出操作数的位置和类型。
例如,你可以使用"=r"约束来指定一个通用寄存器作为输出操作数,使用"r"约束来指定一个通用寄存器作为输入操作数。
嵌入式实验简单ARM汇编编程实验
实验报告
题目1-3:实现程序:根据r0中存放的数据N,实现1+2+3……+N.
图1-3(1)
图1-3(2)
图1-3(3)
题目1-4:实现程序:使用LDR指令读取0x30003000地址上的数据,测试该数据的符号,若为正数,则利用STR指令向0x30003100单元写入1;
若为负数,则向该单元写入-1;若为0,则向该单元写入0。
图1-4(1)
图1-4(2)
图 1-4(3)
图1-4(4)
题目1-6:测试下列指令:(记录调试过程中,寄存器/地址寄存器的变化情况)
①MOV r0,#0x12345678;指令是否正确
②LDR r0, 0x1234和LDR r0,=0x1234;
③MOVS R15,#0x8000; 测试执行情况
④ MOV R0,0x30001000
LDR R1,[R0+4]
LDR R1,[R0+4]!
LDR R1,[R0]+4 ; 测试/理解LDR以上几种寻址工作过程;
图1-6(1)
图1-6(2)
图1-6(3)
题目1-7:下面是一个逆序拷贝程序,请将下面的C代码转换为汇编代码。
数组a和b分别存放在以0x30004000和0x30005000为起始地址的存储区内,类型为long(32位)。
for(i=0;i<7,i++)
{a[i]=b[7-i]};
1-7(1)
1-7(2)
1-7(3)
1-7(4)。
嵌入式开发-c语言经典程序50例
嵌入式开发-c语言经典程序50例【程序1】题目:809*??=800*??+9*??+1 其中??代表的两位数,8*??的结果为两位数,9*??的结果为3位数。
求??代表的两位数,及809*??后的结果。
1.程序分析:2.程序源代码:output(long b,long i){ printf('\n%ld/%ld=809*%ld+%ld',b,i,i,b%i);}main(){long int a,b,i;a=809;for(i=10;i<>{b=i*a+1;if(b>=1000&&b<><100&&9*i>=100)output(b,i); } }====================================== ========================【程序2】题目:八进制转换为十进制1.程序分析:2.程序源代码:main(){ char *p,s[6];int n;p=s;gets(p);n=0;while(*(p)!='\0'){n=n*8+*p-'0';p++;}printf('%d',n);}====================================== ========================【程序3】题目:求0—7所能组成的奇数个数。
1.程序分析:2.程序源代码:main(){long sum=4,s=4;int j;for(j=2;j<=8;j++) j="" is="" place="" of="">{ printf('\n%ld',sum);if(j<>s*=7;elses*=8;sum+=s;}printf('\nsum=%ld',sum);}====================================== ========================【程序4】题目:一个偶数总能表示为两个素数之和。
嵌入式汇编语言实验1
例1.数据块复制 例2.数据简单运算
23:34
河南理工大学通信工程
1
• • • • • • • • • • • • • • •
(1)计算1+2+3+...+100的结果。 程序清单: AREA sum,CODE,READONLY MOV R0, #0 ;初始化R0=0 MOV R2, #1 ;设置R2=0;R2控制循环次数 FOR CMP R2, #100 ;判断R2<100? BHS FOR_E ;若条件失败,退出循环 ADD R0,R0,R2 ;循环体,R0=R0 + R2 ADD R2,R2,#1 ;R2=R2 + 1 B FOR FOR_E LDR R1, #0X40000000; STR R2, [R1] ;保存结果到数组第9项 END
4
数据块复制汇编程序实例
AREA NUM EQU ENTRY LDR LDR MOV MOV Bcopy MOVS BEQ STMFD Ocopy LDMIA STMIA SUBS BNE LDMFD
23:34
B1ock,CODE,READONLY ;设置本段程序的名称及属性 20 ;设置将要复制的字数 ;标识程序人口点 R0,=src ;R0寄存器指向源数据区src R1,=dst ;Rl寄存器指向目标数据区dst R2,#NUM ;R2指定将要复制的宇数 SP,#&400 ;设置数据栈指针,用于保存工作寄存器数值 R3,R2,LSR #3 ;需要进行的以8个字为单位的复制次数 Cword ;不足8个字的数据,跳转到Cword以字为单位复制 SP!,{R4-R11} ;保存工作寄存器 R0!,{R4-R11} ;从源数据区读取8个字的数据,放到8个寄 ;存器中,并更新目标数据区指针R0 R1!,{R4-R11} ;将这8个字数据写入到目标数据区中并更新 ;目标数据区指针R1 R3,R3,#1 ;将块复制次数减l Ocopy ;循环,直到完成以8个字为单位的块复制 SP!,{R4-R11} ;恢复工作寄存器值
《嵌入式系统原理与应用》-汇编指令实验1
《嵌入式系统原理与应用》实验报告实验序号:01 实验项目名称:汇编指令实验1学号姓名专业、班实验地点指导教师实验时间一、实验目的1.了解ADS 1.2 集成开发环境及ARMulator 软件仿真;2.掌握ARM7TDMI 汇编指令的用法,并能编写简单的汇编程序;3. 掌握 ARM 数据处理指令的使用方法;4. 了解 ARM 指令灵活的第 2 个操作数。
二、实验设备(环境)及要求硬件:PC机;软件:PC机操作系统windows XP,ADS1.2集成开发环境。
三、实验内容与步骤1. 建立一个新的工程;2. 建立一个S 源文件,将该文件添加到工程中。
该程序可实现1+ (100)计算,并将结果写回到内存中;3. 设置编译连接控制选项;4. 编译连接工程。
5. 使用ADS 1.2 软件仿真,单步、全速运行程序,设置断点,打开寄存器窗口(Processor Registers)监视R0、R1 等寄存器的值,四、实验结果与数据处理截图:汇编代码:AREA Example1,CODE,READONLY;ENTRY;CODE32;START MOV R0,#0;MOV R1,#0;MOV R2,#1;MOV R3,#0x40000000;LOOPCMP R1,#100;ADDLS R1,R1,R2;ADD R0,R0,#1;CMP R1,#100BLS LOOP;STR R0,[R3];END五、分析与讨论1、指令MOV R0,#0x12345678 是否正确?为什么?2、本题实现的方法有很多种,请给出其他的实现方式。
六、教师评语成绩签名:日期:。
c语言内嵌汇编例子
c语言内嵌汇编例子C语言内嵌汇编例子1. 简单的内嵌汇编代码块#include <>int main() {int a = 3, b = 5, res;asm("addl %%ebx, %%eax;" : "=a"(res) : "a"(a), "b"(b));printf("The result is %d\n", res);return 0;}这个例子展示了一个简单的内嵌汇编代码块,使用了asm关键字将汇编代码嵌入到C语言代码中。
这段代码的作用是将a和b相加,结果存储到变量res中,并打印结果。
2. 内嵌汇编代码块中使用输入输出操作数#include <>int main() {int a = 5, b = 3, res;asm("movl %1, %%eax;""addl %2, %%eax;""movl %%eax, %0;": "=r"(res): "r"(a), "r"(b): "%eax");printf("The result is %d\n", res);return 0;}这个例子展示了如何在内嵌汇编代码块中使用输入输出操作数。
%1、%2和%0分别代表输入操作数a、b和输出操作数res。
使用movl指令将a加载到%eax寄存器中,然后使用addl指令将b与%eax寄存器中的值相加,最后使用movl指令将%eax寄存器中的值存储到res变量中。
3. 内嵌汇编代码块中使用约束#include <>int main() {int a = 2, b = 4, res;asm("movl %1, %%eax;""addl %2, %%eax;""movl %%eax, %0;": "=r"(res): "g"(a), "g"(b): "%eax");printf("The result is %d\n", res);return 0;}这个例子展示了如何在内嵌汇编代码块中使用约束。
C++内嵌汇编示例详解
C++内嵌汇编⽰例详解⽬录汇编语⾔汇编语⾔的特点1.内嵌汇编介绍2.汇编版本Hello, World!3.内联汇编A+B汇编语⾔汇编语⾔是⼀种功能很强的程序设计语⾔,也是利⽤了计算机所有硬件特性并能直接控制硬件的语⾔。
在汇编语⾔中,⽤助记符(Memoni)代替操作码,⽤地址符号(Symbol)或标号(Label)代替地址码。
这样⽤符号代替机器语⾔的⼆进制码,就把机器语⾔变成了汇编语⾔。
汇编语⾔⽐机器语⾔易于读写、调试和修改,同时也具有机器语⾔执⾏速度快、占⽤内存空间少等优点。
但在编写复杂程序时,相对⾼级语⾔来说汇编语⾔代码量较⼤,⽽且汇编语⾔依赖于具体的机型,不能通⽤,因此不能直接在不同处理机型之间移植。
虽然其移植性不好,但效率⾮常⾼,针对计算机特定硬件⽽编制的汇编语⾔程序,能准确地发挥计算机硬件的功能和特长,程序精炼⽽质量⾼,所以汇编语⾔⾄今仍是⼀种常⽤⽽强有⼒的底层开发语⾔。
汇编语⾔的特点汇编语⾔指令使⽤⼀些具有相应含义的助忆符来表达的,所以,它要⽐机器语⾔容易掌握和运⽤。
但因为要直接使⽤CPU资源,所以相对⾼级程序设计语⾔来说它⼜显得相对复杂。
汇编语⾔程序归纳起来⼤概有以下⼏个主要特点。
1. 与硬件相关:汇编语⾔指令是指机器指令的⼀种符号表⽰,⽽不同类型的CPU有不同的机器指令系统,也就有不同的汇编语⾔,所以汇编语⾔程序与机器有着密切的关系。
也就是说,不同型号的CPU之间是⽆法通⽤相同汇编代码的,因此导致汇编语⾔的移植性和通⽤性降低,这是汇编语⾔天⽣的缺陷。
2. 保持了机器语⾔的优点,具有直接和简捷的特点:正因为汇编语⾔有“与机器相关性”的特性,程序员⽤汇编语⾔编写程序时,可充分发挥⾃⼰的聪明才智,对机器内部的各种资源进⾏合理的安排,让它们始终处于最佳的使⽤状态,这样做的最终效果就是程序的执⾏代码短,执⾏速度快,所以,汇编语⾔是⾼效的程序设计语⾔。
另外汇编语⾔可有效地访问、控制计算机的各种硬件设备,如磁盘、存储器、CPU、I/O端⼝等,实现资源利⽤的最⼤化。
ARM内嵌汇编示例
"cmp r0, r2\n" "movlt r3, r0\n" "movlt r0, r2\n" "movlt r2, r3\n"
"cmp r1, r2\n" "movlt r3, r1\n" "movlt r1, r2\n" "movlt r2, r3\n"
return 0;
}
10and.c
//位操作,and 与,orr 或,eor 异或,bic 位清零
#include <stdio.h>
int main(int argc, char **argv) {
int and, orr, eor, bic;
__asm__ __volatile__( "mov r0, #5\n" "mov r1, #6\n" "orr r0, r0, r1\n" "mov %0, r0\n" "and r0, r0, r1\n" "mov %1, r0\n" "eor r0, r0, r1\n" "mov %2, r0\n" "mov r0, #0xff\n" "bic r0, r0, #0x2\n" "mov %3, r0\n" :"=&r"(and), "=&r"(orr), "=&r"(eor), "=&r"(bic) : :"r0", "r1"
嵌入C代码中的386汇编语言程序段
嵌入C代码中的386汇编语言程序段当需要在C语言的程序中嵌入一段汇编语言程序段时,可以使用gcc提供的“asm”语句功能。
例如,下面这么一行代码:#define __SLOW_DOWN_IO __asm__ __volatile__(“outb %al, $0x80”)这里,暂时忽略在asm和volatile前后的两个“__”字符,这也是gcc对C语言的一种扩充,后面我们还要讲到。
先来看括号里面加上了引号的汇编指令。
这是一条8位输出指令,如前所述在操作符上加了后缀“b”以表示这是8位的,而0x80因为是常数,即所谓“直接操作数”,所以要加上前缀“$”,而寄存器名al也加了前缀“%”。
知道了前面所讲AT&T格式与Intel格式的不同,这就是一条很普通的汇编指令,很容易理解。
在同一个asm语句中也可以插入多行汇编程序。
就在同一个文件中,在不同的条件下,__SLOW_DOWN_IO又有不同的定义:#define __SLOW_DOWN_IO __asm__ __volatile__(“jmp 1f \nl:\tjmp 1f \n1:”)这就不怎么直观了。
这里,一共插入了三行汇编语句,“\n”就是换行符,而“\t”则表示TAB符。
所以gcc将之翻译成下面的格式而交给gas去汇编:jmp 1f1: jmp 1f1:这里转移指令的目标1f表示往前(f表示forward)找到第一个标号为1的那一行。
相应地,如果是1b就表示往后找。
这也是从早期Unix汇编代码中继承下来的,读过Unix第6版的读者大概都还能记得。
所以,这一小段汇编代码的用意就在于使CPU空做两条跳转指令和消耗掉一些时间。
既然是要消耗掉一些时间,而不是要节省一些时间,那么为什么要用汇编语句来实现,而不是在C里面来实现呢?原因在于想要对此有比较确切的控制。
如果用C语言来消耗一些时间的话,你常常不能确切地知道经过编译以后,特别是经过优化的话,最后产生的汇编代码究竟怎样。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
ARM实验报告
姓名:郭健傧学号:L2101898
1.实验目的
(1)了解ADS1.2集成开发环境及ARMulator软件仿真;
(2)熟悉ARM的乘法指令和逻辑指令;
(3)结合ARM处理器硬件特性,比较处理函数的特性;
2.实验设备
硬件:pc机一台;
软件:Windowsxp系统,ADS1.2集成开发环境;
3.实验内容
(1)建立一个新的工程;
(2)建立一个汇编文件,并添加到工程;
(3)根据所给的两个C语言函数编写相应的汇编程序,并比较一下代码中fact1和fact2两个函数的特性;
4.实验步骤
(1)启动ADS1.2IDE集成开发环境,使用ARM Executable Image 工程模块建立一个工程heiye。
(2)建立汇编源文件test.s,编写程序实验,并添加到工程heiye中。
(3)设置工程连接地址Ro Base为0x40000000,RWBase为0x40003000。
设置调试入口地址Image entry point为0x40000000。
(4)编译链接工程,并启动AXD进行软件仿真调试。
5.编写程序如下:
C程序源代码:
int fact1(int limit)
{ int fact=1;
for(i=1;i<limit;i++)
fact*=i;
return fact;}
int fact2(int limit)
{int fact=1;
for(i=limit;i!=0;i--)
fact*=i;
return fact;}
(1)编写相应的汇编代码1:
;n!arithmetic
AREA heiye1,CODE,READONLY
CODE32
ENTRY
Main
LDR R0,limit ;装载limit
LDR R1,fact ;装载fact
MOV R2,R1 ;把r2设置为1
BL CYCLE ;调用循环程序
STR R1,result ;将结果存储到内存
MOV R0,#0x18 ;执行中止
SWI 0x123456
CYCLE
MUL R3,R1,R2
MOV R1,R3
ADD R2,R2,#1
CMP R0,R2 ;比较R0和R2的大小并修改状态位
BNE CYCLE
MOV PC,LR
AREA NUM,DATA,READWRITE ;定义数据段
fact DCD 1
limit DCD 0x0000000A
result DCD 0
END
(2)编写相应的汇编程序2:
;n!arithmetic
AREA heiye2,CODE,READONLY
CODE32
ENTRY
Main
LDR R0,limit ;装载limit
LDR R1,fact ;装载fact
BL CYCLE ;调用循环程序
STR R1,result ;将结果存储到内存
MOV R0,#0x18 ;执行中止
SWI 0x123456
CYCLE
MUL R3,R1,R0
MOV R1,R3
SUBS R0,R0,#1
BNE CYCLE ;判断R0是否为零
MOV PC,LR
AREA NUM,DATA,READWRITE ;定义数据段
fact DCD 1
limit DCD 0x0000000A
result DCD 0
END
6.程序中出现的问题
(1)刚开始时,由于马虎把result也写成了resule,导致(STR R1,result)时提示出错,经过仔细查看才发现。
程序入口ENTRY和程序结束END前没按Tab
键,编译时提示没有程序入口,这些地方要特别注意!
(2)仔细比较两个程序的运行结果会发现,第一个汇编程序运算的是(limit-1)!,第二个汇编程序运算的是(limit)!。
但当limit的取值较大时,结果溢出,暂时未能解决!请老师给予指导!
7.程序演示过程
可以单步运行程序,可以设置/取消断点,或者全程运行程序,停止运行程序,调试观看寄存器和0x40000000地址上的值,运行结果如下:
(程序1的单步运行演示)
(程序1的全程运行结果)
(程序2的单步运行演示)(程序2的全程运行结果)。