汇编程序设计以及混合汇编教学课件_第1页
汇编程序设计以及混合汇编教学课件_第2页
汇编程序设计以及混合汇编教学课件_第3页
汇编程序设计以及混合汇编教学课件_第4页
汇编程序设计以及混合汇编教学课件_第5页
已阅读5页,还剩47页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

汇编程序设计及混合汇编2020/12/111ARM汇编语言设计汇编程序设计规范IAR汇编器支持的伪指令简单汇编语言程序设计2020/12/112汇编程序设计特别说明: 开发工具不同,所以的汇编语言伪指令不同如:ADSvsIAR2020/12/113汇编语言程序设计规范-段段:相对独立的指令或数据序列,具有特定的名称段:多个段在程序编译链接时最终形成一个可执行的代码段代码段:内容为执行代码数据段:存放代码运行时需要用到的数据2020/12/114段的设置规则一个或多个代码段,代码段的属性为只读0个或多个包含初始化数据的数据段,数据段的属性为可读/写0个或多个不包含初始化数据的数据段,数据段的属性为可读/写2020/12/115注意源文件中,段之间的相对位置与可执行的映像文件中段的相对位置可能不相同RORWZIROCODERO-DATARO-CODEAB2020/12/116简单的ARM汇编程序

PROGRAMASM_EXAMPL……..;第1行RSEGCODE:CODE:ROOT(2)….;第2行CODE32ORG0x1000start:LDRR0,=0x3FF5000LDRR1,=0xFFSTRR1,[R0]MOVR0,#0x10MOVR1,#0x03ADDR0,R0,R1stop:BSTOPENDMOD

END2020/12/117伪指令语法格式汇编语言格式符号常量[标号[:]]指令操作数;注释十进制数:123,-456十六进制数:0x123,0FFFFJ八进制数:1234q二进制数:1010b2020/12/118汇编语言程序设计汇编程序设计规范IAR汇编器支持的伪指令简单汇编语言程序设计2020/12/119IAR汇编器支持的伪指令模块控制伪指令符号控制伪指令模式控制伪指令段定义伪指令赋值伪指令条件汇编伪指令宏处理伪指令数据定义伪指令汇编控制伪指令C语言风格预处理伪指令2020/12/1110模块控制伪指令伪指令说明END结束汇编ENDMOD结束当前汇编LIBRARY定义多模块程序中的每个小模块,用于创建库NAME定义程序模块RTMODEL声明运行模式属性2020/12/1111符号控制伪指令伪指令说明EXTERN导入外部符号PUBLIC向其它模块导出符号REQUIRE强制引用符号2020/12/1112模式控制伪操作伪指令说明CODE16通知编译器,其后的指令序列为16位Thumb指令。在此范围内标号的位0被置1,强制2字节对齐CODE32通知编译器,其后的指令序列为32位ARM指令。在此范围内标号的位0被清0,强制4字节对齐DATA在Thumb代码段内定义数据区2020/12/1113段定义伪指令伪指令说明ALIGNRAM以增量方式使存储器边界对齐ALIGNROM以填充0方式使存储器边界地址对齐ASEG定义绝对段ASEGN定义指定绝对段COMMON定义公共段EVEN将程序计数器按偶地址对齐ODD将程序计数器按奇地址对齐ORG设定起始地址RSEG定义可重定义段STACK定义堆栈段2020/12/1114赋值伪指令伪指令说明=、ALIAS、EQU定义模块内局部符号并永久赋值ASSIGN、SET、SETA、VAR定义临时符号并赋值DEFINE定义文件内全局符号并赋值LIMIT超限检查2020/12/1115条件汇编伪操作GBLLTest………IFTEST=TRUE指令序列1ELSE指令序列2ENDIF2020/12/1116宏处理伪指令伪指令说明ENDM结束宏定义MACRO定义宏ENDR结束重复结构REPT对指令重复汇编EXITM提前退出宏LOCAL重复并替换字节REPTC定义宏中的局部变量REPTI重复并替换字符串2020/12/1117数据定义伪指令伪指令说明DC8、DCB产生8位字节常数,包括字符串DC16、DCW产生16位半字常数,包括字符串DC24产生24位常数DC32、DCD产生32位常数DF32、DF64分别产生32位和64位浮点数DS8、DS16、DS24,DS32分别保留8位字节,16位半字,24位字和32位字的存储空间2020/12/1118汇编控制伪指令伪指令说明$,INCLUDE包含文件CASEON禁止对大小写字符敏感CASEOFF允许对大小写字符敏感LTORG声明文字池RADIX声明默认数制2020/12/1119混合使用C/C++/汇编内联汇编和嵌入型汇编的使用从汇编代码访问C全局变量在C++中使用C头文件C、C++和ARM汇编语言之间的调用2020/12/1120什么地方会用到汇编开机时硬件系统的初始化,包括CPU状态的设定,中断的使能,主频的设定,以及RAM的控制参数及初始化,中断处理方面也可能涉及汇编。一些对性能非常敏感的代码块,这是不能依靠C编译器的生成代码,而要手工编写汇编,达到优化的目的。操作系统移植2020/12/1121何时使用内联汇编和嵌入型汇编程序中使用饱和算术运算(Saturatingarithmetic),如SSAT16和USAT16指令。程序中需要对协处理器进行操作。在C或C++程序中完成对程序状态寄存器的操作

注:使用内联汇编编写的程序代码效率也比较高

2020/12/1122相互调用必须遵循ATPCSr8r9/sbr10/slr11r12r13/spr14/lrr15/pcr0r1r2r3r4r5r6r7寄存器变量必须保护作为函数传递的参数值Scratchregister(corruptible)StackPointer

LinkRegisterProgramCounter编译器使用一套规则来设置寄存器的用法CPSR标志位可被函数调用所破坏一些和编译过的代码交互工作的汇编码在接口层必须满足的规范Register-如果RWPI选项有效,作为栈的基地址-如果软件堆栈检查有效,作为栈的限制值-r14值压栈以后,r14可作为一个临时寄存器使用2020/12/1123在C程序中调用汇编在汇编程序中用exportname来定义在C程序中直接调用一般的链接即可externvoidmystrcopy(char*d,constchar*s);intmain(void){constchar*src=“Source”;

chardest[10];...

mystrcopy(dest,src);...}AREAStringCopy,CODE,READONLYEXPORTmystrcopymystrcopyLDRBr2,[r1],#1STRBr2,[r0],#1CMPr2,#0BNEmystrcopyMOVpc,lrEND这里所有的参数都是可以用寄存器来传递的,所以不需要在汇编程序中使用PUSH/POP来保护CALL2020/12/1124内联汇编的特点1由于内联汇编嵌入在C或C++程序中,所有在用法上有其自身的一些特点。①如果同一行中包含多条指令,则用分号隔开。②如果一条指令不能在一行中完成,使用反斜杠“/”将其连接。③内联汇编中的注释语句可以使用C或C++风格的。④汇编语言中使用逗号“,”作为指令操作数的分隔符,所以如果在C语言中使用逗号必须用圆括号括起来。如,__asm{ADDx,y,(f(),z)}。⑤内联汇编语言中的寄存器名被编译器视为C或C++语言中的变量,所以内联汇编中出现的寄存器名不一定和同名的物理寄存器相对应。而且这些寄存器名在使用前必须声明,否则编译器将提示警告信息。⑥内联汇编中的寄存器(除程序状态寄存器CPSR和SPSR外)在读取前必须先赋值,否则编译器将产生错误信息。2020/12/1125内联汇编与汇编之间的区别错误的内联汇编函数如下所示。intf(intx){__asm{STMFDsp!,{r0}//保存r0–不合法,因为在读之前没有对寄存器寄存器写操作ADDr0,x,1EORx,r0,xLDMFDsp!,{r0}//不需要恢复寄存器.}returnx;}将其进行改写,是它符合内联汇编的语法规则。intf(intx){intr0;__asm{ADDr0,x,1EORx,r0,x}returnx;}2020/12/1126内联汇编语法①__asm("instruction[;instruction]");//必须为单条指令__asm{instruction[;instruction]}②__asm{...instruction...}③asm("instruction[;instruction]");//必须为单条指令asm{instruction[;instruction]}④asm{...instruction...}2020/12/1127内联汇编(Inlineassembler)使用C变量代替寄存器不是一个真正的汇编文件通过优化器实现代码可能被改变只支持在ARM模式(notThumb)可以有自己独立的函数,但通常是内嵌在C函数中/*Qflagisbit27ofPSR*/constintQ_Flag=0x08000000;__inlineintClear_Q_flag(void){intold_psr,new_psr,result;

__asm

{MRSold_psr,CPSR

BICnew_psr,old_psr,#Q_FlagANDresult,old_psr,#Q_Flag

MSRCPSR_f,new_psr}returnresult;}2020/12/1128内联汇编的限制1可以在内联汇编代码中执行的操作有许多限制。这些限制提供安全的方法,并确保在汇编代码中不违反C和C++代码编译中的规则。①不能直接向程序计数器PC赋值。②内联汇编不支持标号变量。③不能在程序中使用“.”或{PC}得到当前指令地址值。④在16进制常量前加“0x”。⑤建议不要对堆栈进行操作。2020/12/1129内联汇编的限制2⑥编译器可能会使用r12和r13寄存器存放编译的中间结果,在计算表达式值可能会将寄存器r0~r3、r12及r14用于子程序调用。另外在内联汇编中设置程序状态寄存器CPSR中的标志位NZCV时,要特别小心。内联汇编中的设置很可能会和编译器计算的表达式的结果冲突。⑦可以使用内联汇编代码更改处理器模式。然而,更改处理器模式会禁止使用C或C++操作数或对已编译C或C++代码的调用,直到将处理器模式更改回原设置之后之前的函数库才可正常使用。⑧为Thumb状态编译C或C++时,内联汇编程序不可用且不汇编Thumb指令。2020/12/1130内联汇编的限制3⑨尽管可以使用通用协处理器指令指定VFP或FPA指令,但内联汇编程序不为它们提供直接支持。不能用内联汇编代码更改VFP向量模式。内联汇编可包含浮点表达式操作数,该操作数可使用编译程序生成的VFP代码求出操作数值。因此,仅由编译程序修改VFP状态很重要。⑩内嵌汇编不支持的指令:BX、BLX、BXJ和BKPT指令。而LDM、STM、LDRD和STRD指令可能被变形为等效的ARMLDR或STR指令2020/12/1131内联汇编中的虚拟寄存器内联汇编程序提供对ARM处理器物理寄存器的非直接访问。如果在内联汇编程序指令中将某个ARM寄存器用作操作数,它就成为相同名称的虚拟寄存器的引用,而不是对实际物理ARM寄存器的引用。例如内联汇编指令中使用了寄存器r0,但对于C编译器,指令中出现的r0只是一个变量,并非实际的物理寄存器r0,当程序运行时,可能是由物理寄存器r1来存放r0所代表的值。2020/12/1132内联汇编中虚拟寄存器举例#include<stdio.h>voidtest_inline_register(void){inti;intr5,r6,r7;__asm{MOVi,#0loop:MOVr5,#0MOVr6,#0MOVr7,#0ADDi,i,#1CMPi,#3BNEloop

}}intmain(void){

test_inline_register();printf("testinlineregister\n");

return0;}2020/12/1133输出结果test_inline_register:0000807CE3A00000MOVr0,#0>>>TEST_INLINE_REGISTER\#12loop:00008080E1A00000NOP>>>TEST_INLINE_REGISTER\#13MOVr5,#000008084E3A01000MOVr1,#0>>>TEST_INLINE_REGISTER\#14MOVr6,#000008088E3A02000MOVr2,#0>>>TEST_INLINE_REGISTER\#15MOVr7,#00000808CE3A03000MOVr3,#0>>>TEST_INLINE_REGISTER\#16ADDi,i,#100008090E2800001ADDr0,r0,#1>>>TEST_INLINE_REGISTER\#17CMPi,#300008094E3500003CMPr0,#3000080980A000000BEQ0x80a0<TEST_INLINE_REGISTER\#21>>>>TEST_INLINE_REGISTER\#18BNEloop0000809CEAFFFFF8B0x8084<TEST_INLINE_REGISTER\#13>>>>TEST_INLINE_REGISTER\#21}000080A0E12FFF1EBXr142020/12/1134内联汇编中的指令展开内联汇编代码中的ARM指令可能会在编译过程中扩展为几条指令。扩展取决于指令、指令中指定的操作数个数以及每个操作数的类型和值。通常,被扩展的指令有以下几种情况,含有常数操作的指令;LDM、STM、LDRD和STRD指令;乘法指令MUL被扩展为一系列的加法和移位指令。例:包含有常数操作的加法指令ADDr0,r0,#1023被编译器编译为如下两条指令ADDr0,r0,#1024SUBr0,r0,#12020/12/1135内联汇编使用举例1-中断使能__inlinevoidenable_IRQ(void){inttmp;__asm{MRStmp,CPSRBICtmp,tmp,#0x80MSRCPSR_c,tmp}}__inlinevoiddisable_IRQ(void){inttmp;__asm{MRStmp,CPSRORRtmp,tmp,#0x80MSRCPSR_c,tmp}}intmain(void){disable_IRQ();enable_IRQ();}2020/12/1136内联汇编举例2

#defineMUTEX_LOCKED

1023#defineMUTEX_UNLOCKED

0__inlineint

this_task(void)

{

inttask_id=0;

/*GetFastContextSwitchTaskID*/

__asm{MRCp15,0,task_id,c13,c0,0

}

return

(task_id>>25);}__inlineint

get_mutex(volatile

int*lock_addr){

int

owner;

/*Doesanyoneownlockatthemoment?*/

__asm{SWPowner,MUTEX_LOCKED,[lock_addr]}

if(owner==

MUTEX_UNLOCKED

){/*No?ReplaceMUTEX_LOCKEDwithourtaskid*/*lock_addr=this_task();}elseif(owner!=MUTEX_LOCKED){/*Yes?Andownerisavalidtaskid?*Putowner’staskidback*/

*lock_addr=owner;}

returnowner;}Resultingcode(-O2-Ospace):LDRr5,|L1.76|;&uart_mtxLDRr4,|L1.72|;#1023|L1.12|MOVr0,#0x400BLOS_sleepSWPr0,r4,[r5]CMPr0,#0 MRCEQp15,0x0,r1,c13,c0,0ASREQr1,r1,#25STREQr1,[r5,#0]BEQ|L1.52|CMPr0,r4 STRNEr0,[r5,#0]|L1.52|CMPr0,#0BNE|L1.12|+externvolatileintuart_mtx=0;...do{OS_sleep(1024);}

while(get_mutex(&uart_mtx)

);...

2020/12/1137嵌入型汇编用__asm或asm声明的函数可以有调用参数和返回类型。它们从C和C++中调用的方式与普通C和C++函数调用方式相同。嵌入式汇编函数语法是:__asmreturn-typefunction-name(parameter-list){//ARM/Thumb/Thumb-2assemblercodeinstruction[;instruction]...[instruction]}2020/12/1138嵌入型汇编举例#include<stdio.h>__asmvoidmy_strcpy(constchar*src,constchar*dst){loopLDRBr3,[r0],#1STRBr3,[r1],#1CMPr3,#0BNEloopMOVpc,lr}voidmain(){constchar*a="Helloworld!";charb[20];my_strcpy(a,b);printf("Originalstring:'%s'\n",a);printf("Copiedstring:'%s'\n",b);}2020/12/1139内联汇编和内嵌汇编的区别功能嵌入式汇编程序内联汇编程序指令集ARM和Thumb仅支持ARMARM汇编指令伪操作支持不支持ARMv6指令集支持仅支持媒体指令C/C++表达式只支持常数表达式完全支持汇编代码是否优化无优化完全优化寄存器访问使用指定的物理寄存器。还可以使用PC、LR和SP使用虚拟寄存器。不能使用PC、LR和SP寄存器是否支持BKPT指令不直接支持不支持2020/12/1140混合使用C/C++/汇编内联汇编和嵌入型汇编的使用从汇编代码访问C全局变量在C++中使用C头文件C、C++和ARM汇编语言之间的调用2020/12/1141在C中访问汇编全局变量在汇编代码中访问C全局变量,只能通过地址间接访问全局变量。要访问全局变量,必须在汇编中使用IMPORT伪操作引入全局变量,然后将地址载入寄存器。可以根据变量的类型使用载入和存储指令访问该变量。2020/12/1142在C中访问汇编全局变量-举例PRESERVE8AREAglobals,CODE,READONLYEXPORTasmsubroutineIMPORTglobvarasmsubroutineLDRr1,=globvar;readaddressofglobvarinto;r1fromliteralpoolLDRr0,[r1]ADDr0,r0,#2STRr0,[r1]MOVpc,lrEND2020/12/1143混合使用C/C++/汇编内联汇编和嵌入型汇编的使用从汇编代码访问C全局变量在C++中使用C头文件C、C++和ARM汇编语言之间的调用2020/12/1144在C++中使用C头文件本节描述如何在C++代码中使用C头文件。从C++调用C头文件之前,C头文件必须包含在extern“C”命令中。包含以下两部分内容:在C++中使用系统的C头文件;在C++中使用自定义的C头文件。2020/12/1145包含系统C头文件1要包括标准的系统C头文件,如stdio.h,不必进行任何特殊操作。只有使用extern"C"命令,则有编译器自动包含标准C头文件。例如:#include<stdio.h>intmain(){...//C++代码return0;}

2020/12/1146包含系统C头文件2C++标准规定可以通过特定的C++头文件获取C头文件。这些文件与标准C头文件一起安装,可以用常规方法进行引用。例如:#include<cstdio>intmain(){...//C++代码return0;}2020/12/1147在C++中使用自定义的C头文件①在#include文件之前使用extern,如下例所示。//C++codeextern"C"{#include"my-header1.h"#include"my-header2.h"}intmain(){//...return0;}②将extern"C"语句添加到头文件,如下例所示/*Cheaderfile*/#ifdef__cplusplus/*InsertstartofexternCconstruct*/extern"C"{#endif/*Bodyofheaderfile*/#ifdef__cplusplus/*InsertendofexternCconstruct*/}/*TheCheadernowbe*/#endif/*includedineitherCorC++code.*/2020/12/1148混合使用C/C++/汇编内联汇编和嵌入型汇编的使用从汇编代码访问C全局变量在C++中使用C头文件C、C++和ARM汇编语言之间的调用

2020/12/1149从C调用汇编语言#include<stdio.h>externvoidstrcopy(char*d,constchar*s);intma

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论